Version in base suite: 9.4.50-4+deb12u3
Base version: jetty9_9.4.50-4+deb12u3
Target version: jetty9_9.4.57-0+deb12u1
Base file: /srv/ftp-master.debian.org/ftp/pool/main/j/jetty9/jetty9_9.4.50-4+deb12u3.dsc
Target file: /srv/ftp-master.debian.org/policy/pool/main/j/jetty9/jetty9_9.4.57-0+deb12u1.dsc
CODE_OF_CONDUCT.md | 93
CONTRIBUTING.md | 8
Jenkinsfile | 5
KEYS.txt | 2
NOTICE.txt | 2
README.md | 2
VERSION.txt | 1502 +-
aggregates/jetty-all-compact3/pom.xml | 4
aggregates/jetty-all/pom.xml | 2
aggregates/jetty-all/src/main/resources/META-INF/MANIFEST.MF | 2
aggregates/jetty-websocket-all/pom.xml | 2
apache-jsp/pom.xml | 2
apache-jsp/src/main/config/modules/apache-jsp.mod | 2
apache-jstl/pom.xml | 2
apache-jstl/src/main/config/modules/apache-jstl.mod | 2
build-resources/pom.xml | 2
debian/changelog | 155
debian/control | 7
debian/copyright | 2
debian/jetty9.install | 1
debian/jetty9.timer | 9
debian/patches/01-maven-bundle-plugin-version.patch | 2
debian/patches/02-import-alpn-api.patch | 8
debian/patches/04-weksocket-1.1-compatibility.patch | 10
debian/patches/06-ignore-jetty-documentation.patch | 2
debian/patches/07-assembly-plugin-configuration.patch | 4
debian/patches/08-ignore-jetty-test-policy.patch | 2
debian/patches/09-tweak-distribution.patch | 18
debian/patches/CVE-2023-26048.patch | 433
debian/patches/CVE-2023-26049.patch | 367
debian/patches/CVE-2023-36478.patch | 7110 ----------
debian/patches/CVE-2023-36479.patch | 47
debian/patches/CVE-2023-40167.patch | 268
debian/patches/CVE-2023-41900.patch | 781 -
debian/patches/CVE-2023-44487.patch | 622
debian/patches/CVE-2024-22201.patch | 138
debian/patches/series | 8
debian/patches/servlet-api.patch | 2
debian/source/lintian-overrides | 2
examples/async-rest/async-rest-jar/pom.xml | 2
examples/async-rest/async-rest-webapp/pom.xml | 2
examples/async-rest/async-rest-webapp/src/main/webapp/WEB-INF/jetty-web.xml | 2
examples/async-rest/pom.xml | 2
examples/embedded/pom.xml | 2
examples/embedded/src/main/resources/exampleserver.xml | 2
examples/embedded/src/main/resources/fileserver.xml | 2
examples/embedded/src/main/resources/jetty-otherserver.xml | 2
examples/pom.xml | 2
jetty-alpn/jetty-alpn-client/pom.xml | 2
jetty-alpn/jetty-alpn-conscrypt-client/pom.xml | 2
jetty-alpn/jetty-alpn-conscrypt-server/pom.xml | 2
jetty-alpn/jetty-alpn-java-client/pom.xml | 2
jetty-alpn/jetty-alpn-java-server/pom.xml | 2
jetty-alpn/jetty-alpn-openjdk8-client/pom.xml | 2
jetty-alpn/jetty-alpn-openjdk8-server/pom.xml | 2
jetty-alpn/jetty-alpn-server/pom.xml | 2
jetty-alpn/jetty-alpn-server/src/main/config/etc/jetty-alpn.xml | 2
jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-available-false.mod | 2
jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-available-true.mod | 2
jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn.mod | 2
jetty-alpn/pom.xml | 2
jetty-annotations/pom.xml | 2
jetty-annotations/src/main/config/etc/jetty-annotations.xml | 2
jetty-annotations/src/main/config/modules/annotations.mod | 2
jetty-ant/pom.xml | 2
jetty-bom/pom.xml | 138
jetty-cdi/pom.xml | 12
jetty-cdi/src/main/config/etc/cdi/jetty-cdi.xml | 2
jetty-cdi/src/main/config/etc/cdi/jetty-cdi2.xml | 2
jetty-cdi/src/main/config/etc/cdi/jetty-web-cdi2.xml | 2
jetty-cdi/src/main/config/modules/cdi-decorate.mod | 2
jetty-cdi/src/main/config/modules/cdi-spi.mod | 2
jetty-cdi/src/main/config/modules/cdi.mod | 2
jetty-cdi/src/main/config/modules/cdi2.mod | 2
jetty-client/pom.xml | 12
jetty-client/src/main/config/modules/client.mod | 2
jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTLSTest.java | 5
jetty-continuation/pom.xml | 2
jetty-deploy/pom.xml | 2
jetty-deploy/src/main/config/etc/jetty-decorate.xml | 2
jetty-deploy/src/main/config/etc/jetty-deploy.xml | 2
jetty-deploy/src/main/config/etc/jetty-web-decorate.xml | 2
jetty-deploy/src/main/config/modules/decorate.mod | 2
jetty-deploy/src/main/config/modules/deploy.mod | 2
jetty-deploy/src/main/config/modules/global-webapp-common.d/global-webapp-common.xml | 2
jetty-deploy/src/main/config/modules/global-webapp-common.d/webapp-common.xml | 2
jetty-deploy/src/main/config/modules/global-webapp-common.mod | 2
jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentTempDirTest.java | 10
jetty-deploy/src/test/resources/binding-test-contexts-1.xml | 2
jetty-deploy/src/test/resources/context-binding-test-1.xml | 2
jetty-deploy/src/test/resources/jetty-deploy-wars.xml | 2
jetty-deploy/src/test/resources/jetty-deploymgr-contexts.xml | 2
jetty-deploy/src/test/resources/jetty-http.xml | 2
jetty-deploy/src/test/resources/jetty.xml | 5
jetty-deploy/src/test/resources/webapps/badapp/badapp.xml | 2
jetty-deploy/src/test/resources/webapps/foo.xml | 2
jetty-distribution/pom.xml | 2
jetty-distribution/src/main/resources/README.TXT | 2
jetty-distribution/src/main/resources/demo-base/webapps/ROOT/index.html | 12
jetty-distribution/src/main/resources/demo-base/webapps/example-moved.xml | 2
jetty-distribution/src/main/resources/start.ini | 2
jetty-fcgi/fcgi-client/pom.xml | 2
jetty-fcgi/fcgi-server/pom.xml | 2
jetty-fcgi/fcgi-server/src/main/config/modules/fcgi.mod | 4
jetty-fcgi/pom.xml | 2
jetty-gcloud/jetty-gcloud-session-manager/pom.xml | 2
jetty-gcloud/jetty-gcloud-session-manager/src/main/config-template/etc/sessions/gcloud/session-store.xml | 2
jetty-gcloud/jetty-gcloud-session-manager/src/main/config-template/modules/gcloud-datastore.mod | 2
jetty-gcloud/jetty-gcloud-session-manager/src/main/config-template/modules/gcloud.mod | 2
jetty-gcloud/jetty-gcloud-session-manager/src/main/config-template/modules/session-store-gcloud.mod | 2
jetty-gcloud/pom.xml | 4
jetty-hazelcast/pom.xml | 2
jetty-hazelcast/src/main/config/etc/sessions/hazelcast/default.xml | 2
jetty-hazelcast/src/main/config/etc/sessions/hazelcast/remote.xml | 2
jetty-hazelcast/src/main/config/modules/session-store-hazelcast-embedded.mod | 2
jetty-hazelcast/src/main/config/modules/session-store-hazelcast-remote.mod | 2
jetty-home/pom.xml | 2
jetty-home/src/main/resources/etc/jetty-setuid.xml | 2
jetty-home/src/main/resources/etc/jetty-started.xml | 2
jetty-home/src/main/resources/etc/jetty-stop.xml | 2
jetty-home/src/main/resources/modules/conscrypt.mod | 2
jetty-home/src/main/resources/modules/conscrypt/conscrypt.xml | 2
jetty-home/src/main/resources/modules/hawtio.mod | 2
jetty-home/src/main/resources/modules/hawtio/hawtio.xml | 2
jetty-home/src/main/resources/modules/jamon.mod | 2
jetty-home/src/main/resources/modules/jamon/jamon.xml | 2
jetty-home/src/main/resources/modules/jminix.mod | 2
jetty-home/src/main/resources/modules/jminix/jminix.xml | 2
jetty-home/src/main/resources/modules/jolokia.mod | 2
jetty-home/src/main/resources/modules/jolokia/jolokia.xml | 2
jetty-home/src/main/resources/modules/jsp.mod | 2
jetty-home/src/main/resources/modules/jstl.mod | 2
jetty-home/src/main/resources/modules/setuid.mod | 2
jetty-home/src/main/resources/modules/stop.mod | 2
jetty-http-spi/pom.xml | 18
jetty-http/pom.xml | 2
jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java | 1
jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.java | 5
jetty-http/src/main/java/org/eclipse/jetty/http/HttpComplianceSection.java | 1
jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java | 48
jetty-http/src/main/java/org/eclipse/jetty/http/HttpTokens.java | 44
jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java | 127
jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartFormInputStream.java | 24
jetty-http/src/main/java/org/eclipse/jetty/http/compression/EncodingException.java | 27
jetty-http/src/main/java/org/eclipse/jetty/http/compression/Huffman.java | 357
jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanDecoder.java | 143
jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanEncoder.java | 142
jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitIntegerDecoder.java | 113
jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitIntegerEncoder.java | 96
jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitStringDecoder.java | 138
jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitStringEncoder.java | 82
jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java | 83
jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java | 37
jetty-http/src/test/java/org/eclipse/jetty/http/HuffmanTest.java | 168
jetty-http/src/test/java/org/eclipse/jetty/http/NBitIntegerTest.java | 207
jetty-http2/http2-alpn-tests/pom.xml | 2
jetty-http2/http2-client/pom.xml | 7
jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java | 81
jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2ClientConnectionFactory.java | 83
jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2ClientSession.java | 15
jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DynamicTableTest.java | 190
jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java | 179
jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java | 56
jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java | 13
jetty-http2/http2-common/pom.xml | 2
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Connection.java | 22
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Session.java | 179
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Stream.java | 6
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/frames/HeadersFrame.java | 3
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/generator/Generator.java | 26
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ContinuationBodyParser.java | 36
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeaderBlockFragments.java | 33
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeaderBlockParser.java | 5
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeadersBodyParser.java | 41
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/Parser.java | 60
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/PushPromiseBodyParser.java | 17
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ResetBodyParser.java | 8
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ServerParser.java | 39
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java | 29
jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/UnknownBodyParser.java | 1
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java | 61
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/DataGenerateParseTest.java | 13
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/FrameFloodTest.java | 38
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/GoAwayGenerateParseTest.java | 13
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java | 13
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/MaxFrameSizeParseTest.java | 9
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PingGenerateParseTest.java | 19
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PriorityGenerateParseTest.java | 13
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java | 13
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ResetGenerateParseTest.java | 13
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/SettingsGenerateParseTest.java | 61
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/UnknownParseTest.java | 13
jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/WindowUpdateGenerateParseTest.java | 13
jetty-http2/http2-hpack/pom.xml | 2
jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackContext.java | 61
jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackDecoder.java | 174
jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java | 178
jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackException.java | 5
jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java | 14
jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java | 551
jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java | 42
jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/NBitInteger.java | 151
jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackContextTest.java | 33
jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java | 50
jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java | 30
jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java | 29
jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java | 49
jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HuffmanTest.java | 87
jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/NBitIntegerTest.java | 204
jetty-http2/http2-http-client-transport/pom.xml | 2
jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2.java | 21
jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpConnectionOverHTTP2.java | 5
jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/GoAwayTest.java | 151
jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java | 8
jetty-http2/http2-server/pom.xml | 2
jetty-http2/http2-server/src/main/config/etc/jetty-http2.xml | 2
jetty-http2/http2-server/src/main/config/etc/jetty-http2c.xml | 2
jetty-http2/http2-server/src/main/config/modules/http2.mod | 2
jetty-http2/http2-server/src/main/config/modules/http2c.mod | 2
jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java | 87
jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java | 8
jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerSession.java | 20
jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java | 19
jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java | 13
jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java | 45
jetty-http2/pom.xml | 2
jetty-infinispan/infinispan-common/pom.xml | 26
jetty-infinispan/infinispan-common/src/main/config/etc/sessions/infinispan/infinispan-common.xml | 2
jetty-infinispan/infinispan-embedded-query/pom.xml | 13
jetty-infinispan/infinispan-embedded-query/src/main/config-template/etc/sessions/infinispan/infinispan-embedded-query.xml | 2
jetty-infinispan/infinispan-embedded/pom.xml | 12
jetty-infinispan/infinispan-embedded/src/main/config-template/etc/sessions/infinispan/infinispan-embedded.xml | 2
jetty-infinispan/infinispan-remote-query/pom.xml | 23
jetty-infinispan/infinispan-remote-query/src/main/config-template/etc/sessions/infinispan/infinispan-remote-query.xml | 2
jetty-infinispan/infinispan-remote/pom.xml | 12
jetty-infinispan/infinispan-remote/src/main/config-template/etc/sessions/infinispan/infinispan-remote.xml | 2
jetty-infinispan/pom.xml | 2
jetty-io/pom.xml | 2
jetty-jaas/pom.xml | 4
jetty-jaas/src/main/config/etc/jetty-jaas.xml | 2
jetty-jaas/src/main/config/modules/jaas.mod | 2
jetty-jaspi/pom.xml | 5
jetty-jaspi/src/main/config/modules/jaspi.mod | 2
jetty-jmh/pom.xml | 20
jetty-jmx/pom.xml | 2
jetty-jmx/src/main/config/etc/jetty-jmx-remote.xml | 2
jetty-jmx/src/main/config/etc/jetty-jmx.xml | 2
jetty-jmx/src/main/config/modules/jmx-remote.mod | 2
jetty-jmx/src/main/config/modules/jmx.mod | 2
jetty-jndi/pom.xml | 2
jetty-jndi/src/main/jndi-config/modules/jndi.mod | 2
jetty-jndi/src/main/jndi-config/modules/mail.mod | 2
jetty-jspc-maven-plugin/pom.xml | 2
jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java | 2
jetty-jspc-maven-plugin/src/site/site.xml | 4
jetty-maven-plugin/pom.xml | 11
jetty-maven-plugin/src/it/jetty-cdi-run-forked/src/main/jetty/jetty-context.xml | 2
jetty-maven-plugin/src/it/jetty-cdi-run-forked/src/main/jetty/jetty.xml | 2
jetty-maven-plugin/src/it/jetty-deploy-war-mojo-it/src/config/jetty.xml | 2
jetty-maven-plugin/src/it/jetty-maven-plugin-provided-module-dep/web/src/config/jetty.xml | 2
jetty-maven-plugin/src/it/jetty-run-distro-mojo-it/jetty-simple-webapp/src/base/etc/test-jetty.xml | 2
jetty-maven-plugin/src/it/jetty-run-distro-mojo-it/jetty-simple-webapp/src/base/modules/testmod.mod | 2
jetty-maven-plugin/src/it/jetty-run-forked-mojo-it/jetty-simple-webapp/src/config/jetty.xml | 2
jetty-maven-plugin/src/it/jetty-run-mojo-it/jetty-simple-webapp/src/config/context.xml | 2
jetty-maven-plugin/src/it/jetty-run-mojo-it/jetty-simple-webapp/src/config/jetty.xml | 2
jetty-maven-plugin/src/it/jetty-run-mojo-jar-scan-it/MyWebApp/src/config/context.xml | 2
jetty-maven-plugin/src/it/jetty-run-mojo-jar-scan-it/MyWebApp/src/config/jetty.xml | 2
jetty-maven-plugin/src/it/jetty-run-mojo-jsp/src/config/jetty.xml | 2
jetty-maven-plugin/src/it/jetty-run-mojo-multi-module-single-war-it/webapp-war/src/config/jetty.xml | 2
jetty-maven-plugin/src/it/jetty-run-war-exploded-mojo-it/jetty-simple-webapp/src/config/jetty.xml | 2
jetty-maven-plugin/src/it/jetty-run-war-mojo-it/jetty-simple-webapp/src/config/jetty.xml | 2
jetty-maven-plugin/src/it/jetty-start-mojo-it/jetty-simple-webapp/src/config/jetty.xml | 2
jetty-maven-plugin/src/it/run-mojo-gwt-it/beer-server/src/config/jetty.xml | 3
jetty-maven-plugin/src/it/run-mojo-gwt-it/beer-server/src/main/jettyconf/context.xml | 3
jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEffectiveWebXml.java | 2
jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunDistro.java | 2
jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunForkedMojo.java | 2
jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunMojo.java | 2
jetty-maven-plugin/src/main/resources/jetty-maven.xml | 2
jetty-maven-plugin/src/main/resources/maven.mod | 2
jetty-maven-plugin/src/main/resources/maven.xml | 2
jetty-maven-plugin/src/site/site.xml | 4
jetty-memcached/jetty-memcached-sessions/pom.xml | 2
jetty-memcached/jetty-memcached-sessions/src/main/config/etc/sessions/session-data-cache/xmemcached.xml | 2
jetty-memcached/jetty-memcached-sessions/src/main/config/modules/sessions/session-data-cache/xmemcached.mod | 2
jetty-memcached/pom.xml | 2
jetty-nosql/pom.xml | 2
jetty-nosql/src/main/config/etc/sessions/mongo/session-store-by-address.xml | 2
jetty-nosql/src/main/config/etc/sessions/mongo/session-store-by-uri.xml | 2
jetty-nosql/src/main/config/modules/session-store-mongo.mod | 2
jetty-nosql/src/main/config/modules/sessions/mongo/address.mod | 2
jetty-nosql/src/main/config/modules/sessions/mongo/uri.mod | 2
jetty-openid/pom.xml | 2
jetty-openid/src/main/config/etc/jetty-openid.xml | 2
jetty-openid/src/main/config/modules/openid.mod | 2
jetty-openid/src/main/config/modules/openid/openid-baseloginservice.xml | 2
jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdAuthenticator.java | 12
jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdCredentials.java | 19
jetty-openid/src/test/java/org/eclipse/jetty/security/openid/OpenIdAuthenticationTest.java | 187
jetty-openid/src/test/java/org/eclipse/jetty/security/openid/OpenIdProvider.java | 250
jetty-osgi/jetty-osgi-alpn/pom.xml | 2
jetty-osgi/jetty-osgi-boot-jsp/pom.xml | 2
jetty-osgi/jetty-osgi-boot-warurl/pom.xml | 2
jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty-deploy.xml | 2
jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty-http.xml | 2
jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty.xml | 4
jetty-osgi/jetty-osgi-boot/pom.xml | 2
jetty-osgi/jetty-osgi-httpservice/contexts/httpservice.xml | 2
jetty-osgi/jetty-osgi-httpservice/pom.xml | 2
jetty-osgi/pom.xml | 23
jetty-osgi/test-jetty-osgi-context/pom.xml | 2
jetty-osgi/test-jetty-osgi-context/src/main/context/acme.xml | 2
jetty-osgi/test-jetty-osgi-fragment/pom.xml | 2
jetty-osgi/test-jetty-osgi-server/pom.xml | 2
jetty-osgi/test-jetty-osgi-webapp-resources/pom.xml | 2
jetty-osgi/test-jetty-osgi-webapp/pom.xml | 2
jetty-osgi/test-jetty-osgi/pom.xml | 10
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-alpn.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-deploy.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-context-as-service.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-webapp-as-service.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-annotations.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-javax-websocket.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-jsp.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-resources.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-websocket.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http2-jdk9.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http2.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-https.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-ssl.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-testrealm.xml | 2
jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml | 4
jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestOSGiUtil.java | 8
jetty-plus/pom.xml | 2
jetty-plus/src/main/plus-config/etc/jetty-plus.xml | 2
jetty-plus/src/main/plus-config/modules/plus.mod | 2
jetty-plus/src/main/plus-config/modules/transactions.mod | 2
jetty-proxy/pom.xml | 2
jetty-proxy/src/main/config/etc/jetty-proxy.xml | 2
jetty-proxy/src/main/config/modules/proxy.mod | 2
jetty-quickstart/pom.xml | 2
jetty-quickstart/src/main/config/etc/example-quickstart.xml | 2
jetty-quickstart/src/main/config/modules/quickstart.mod | 2
jetty-rewrite/pom.xml | 2
jetty-rewrite/src/main/config/etc/jetty-rewrite-customizer.xml | 2
jetty-rewrite/src/main/config/etc/jetty-rewrite.xml | 2
jetty-rewrite/src/main/config/etc/rewrite-compactpath.xml | 2
jetty-rewrite/src/main/config/modules/rewrite-compactpath.mod | 2
jetty-rewrite/src/main/config/modules/rewrite-customizer.mod | 2
jetty-rewrite/src/main/config/modules/rewrite.mod | 2
jetty-rewrite/src/test/resources/org.mortbay.jetty.rewrite.handler/jetty-rewrite.xml | 2
jetty-runner/pom.xml | 4
jetty-runner/src/main/java/org/eclipse/jetty/runner/Runner.java | 2
jetty-security/pom.xml | 2
jetty-security/src/main/config/modules/security.mod | 2
jetty-server/pom.xml | 7
jetty-server/src/main/config/etc/home-base-warning.xml | 2
jetty-server/src/main/config/etc/jetty-acceptratelimit.xml | 2
jetty-server/src/main/config/etc/jetty-bytebufferpool-logarithmic.xml | 2
jetty-server/src/main/config/etc/jetty-bytebufferpool.xml | 2
jetty-server/src/main/config/etc/jetty-connectionlimit.xml | 2
jetty-server/src/main/config/etc/jetty-customrequestlog.xml | 2
jetty-server/src/main/config/etc/jetty-debug.xml | 2
jetty-server/src/main/config/etc/jetty-debuglog.xml | 2
jetty-server/src/main/config/etc/jetty-gzip.xml | 2
jetty-server/src/main/config/etc/jetty-http-forwarded.xml | 2
jetty-server/src/main/config/etc/jetty-http.xml | 2
jetty-server/src/main/config/etc/jetty-https.xml | 2
jetty-server/src/main/config/etc/jetty-ipaccess.xml | 2
jetty-server/src/main/config/etc/jetty-lowresources.xml | 2
jetty-server/src/main/config/etc/jetty-proxy-protocol-ssl.xml | 2
jetty-server/src/main/config/etc/jetty-proxy-protocol.xml | 2
jetty-server/src/main/config/etc/jetty-requestlog.xml | 2
jetty-server/src/main/config/etc/jetty-ssl-context-reload.xml | 2
jetty-server/src/main/config/etc/jetty-ssl-context.xml | 4
jetty-server/src/main/config/etc/jetty-ssl.xml | 2
jetty-server/src/main/config/etc/jetty-stats.xml | 2
jetty-server/src/main/config/etc/jetty-threadlimit.xml | 2
jetty-server/src/main/config/etc/jetty-threadpool.xml | 2
jetty-server/src/main/config/etc/jetty.xml | 4
jetty-server/src/main/config/etc/sessions/file/session-store.xml | 2
jetty-server/src/main/config/etc/sessions/id-manager.xml | 2
jetty-server/src/main/config/etc/sessions/jdbc/datasource.xml | 2
jetty-server/src/main/config/etc/sessions/jdbc/driver.xml | 2
jetty-server/src/main/config/etc/sessions/jdbc/session-store.xml | 2
jetty-server/src/main/config/etc/sessions/session-cache-hash.xml | 2
jetty-server/src/main/config/etc/sessions/session-cache-null.xml | 2
jetty-server/src/main/config/etc/sessions/session-data-cache/session-caching-store.xml | 2
jetty-server/src/main/config/modules/acceptratelimit.mod | 2
jetty-server/src/main/config/modules/bytebufferpool-logarithmic.mod | 2
jetty-server/src/main/config/modules/bytebufferpool.mod | 2
jetty-server/src/main/config/modules/connectionlimit.mod | 2
jetty-server/src/main/config/modules/continuation.mod | 2
jetty-server/src/main/config/modules/customrequestlog.mod | 2
jetty-server/src/main/config/modules/debug.mod | 2
jetty-server/src/main/config/modules/debuglog.mod | 2
jetty-server/src/main/config/modules/ext.mod | 2
jetty-server/src/main/config/modules/gzip.mod | 2
jetty-server/src/main/config/modules/home-base-warning.mod | 2
jetty-server/src/main/config/modules/http-forwarded.mod | 2
jetty-server/src/main/config/modules/http.mod | 2
jetty-server/src/main/config/modules/https.mod | 2
jetty-server/src/main/config/modules/inetaccess.mod | 2
jetty-server/src/main/config/modules/inetaccess/jetty-inetaccess.xml | 2
jetty-server/src/main/config/modules/ipaccess.mod | 2
jetty-server/src/main/config/modules/jdbc.mod | 2
jetty-server/src/main/config/modules/jvm.mod | 2
jetty-server/src/main/config/modules/logback-access.mod | 2
jetty-server/src/main/config/modules/logback-access/jetty-logback-access.xml | 2
jetty-server/src/main/config/modules/lowresources.mod | 2
jetty-server/src/main/config/modules/proxy-protocol-ssl.mod | 2
jetty-server/src/main/config/modules/proxy-protocol.mod | 2
jetty-server/src/main/config/modules/requestlog.mod | 2
jetty-server/src/main/config/modules/resources.mod | 2
jetty-server/src/main/config/modules/server.mod | 2
jetty-server/src/main/config/modules/session-cache-hash.mod | 2
jetty-server/src/main/config/modules/session-cache-null.mod | 2
jetty-server/src/main/config/modules/session-store-cache.mod | 2
jetty-server/src/main/config/modules/session-store-file.mod | 2
jetty-server/src/main/config/modules/session-store-jdbc.mod | 2
jetty-server/src/main/config/modules/sessions.mod | 2
jetty-server/src/main/config/modules/sessions/jdbc/datasource.mod | 2
jetty-server/src/main/config/modules/sessions/jdbc/driver.mod | 2
jetty-server/src/main/config/modules/ssl-reload.mod | 2
jetty-server/src/main/config/modules/ssl.mod | 4
jetty-server/src/main/config/modules/stats.mod | 2
jetty-server/src/main/config/modules/threadpool.mod | 2
jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java | 102
jetty-server/src/main/java/org/eclipse/jetty/server/HomeBaseWarning.java | 2
jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java | 28
jetty-server/src/main/java/org/eclipse/jetty/server/MultiParts.java | 14
jetty-server/src/main/java/org/eclipse/jetty/server/Request.java | 27
jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java | 4
jetty-server/src/main/java/org/eclipse/jetty/server/handler/SizeLimitHandler.java | 22
jetty-server/src/main/java/org/eclipse/jetty/server/handler/ThreadLimitHandler.java | 72
jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java | 45
jetty-server/src/test/java/org/eclipse/jetty/server/CookieCutterLenientTest.java | 3
jetty-server/src/test/java/org/eclipse/jetty/server/CookieCutterTest.java | 90
jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java | 2
jetty-server/src/test/java/org/eclipse/jetty/server/handler/SizeLimitHandlerTest.java | 8
jetty-server/src/test/java/org/eclipse/jetty/server/handler/ThreadLimitHandlerTest.java | 25
jetty-servlet/pom.xml | 2
jetty-servlet/src/main/config/modules/servlet.mod | 2
jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java | 30
jetty-servlet/src/test/java/org/eclipse/jetty/servlet/MultiPartServletTest.java | 208
jetty-servlets/pom.xml | 2
jetty-servlets/src/main/config/modules/servlets.mod | 2
jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CGI.java | 3
jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java | 246
jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushCacheFilter.java | 7
jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushSessionCacheFilter.java | 9
jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java | 56
jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java | 2
jetty-spring/pom.xml | 4
jetty-spring/src/main/config/modules/spring.mod | 2
jetty-start/pom.xml | 2
jetty-start/src/main/java/org/eclipse/jetty/start/ModuleGraphWriter.java | 2
jetty-start/src/main/resources/org/eclipse/jetty/start/usage.txt | 4
jetty-start/src/test/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializerTest.java | 2
jetty-start/src/test/resources/bogus.xml | 1
jetty-start/src/test/resources/dist-home/modules/main.mod | 2
jetty-unixsocket/pom.xml | 2
jetty-unixsocket/src/main/config-template/etc/jetty-unixsocket-forwarded.xml | 2
jetty-unixsocket/src/main/config-template/etc/jetty-unixsocket-http.xml | 2
jetty-unixsocket/src/main/config-template/etc/jetty-unixsocket-http2c.xml | 2
jetty-unixsocket/src/main/config-template/etc/jetty-unixsocket-proxy-protocol.xml | 2
jetty-unixsocket/src/main/config-template/etc/jetty-unixsocket-secure.xml | 2
jetty-unixsocket/src/main/config-template/etc/jetty-unixsocket.xml | 2
jetty-unixsocket/src/main/config-template/modules/unixsocket-forwarded.mod | 2
jetty-unixsocket/src/main/config-template/modules/unixsocket-http.mod | 2
jetty-unixsocket/src/main/config-template/modules/unixsocket-http2c.mod | 2
jetty-unixsocket/src/main/config-template/modules/unixsocket-prefix.mod | 2
jetty-unixsocket/src/main/config-template/modules/unixsocket-proxy-protocol.mod | 2
jetty-unixsocket/src/main/config-template/modules/unixsocket-secure.mod | 2
jetty-util-ajax/pom.xml | 2
jetty-util/pom.xml | 2
jetty-util/src/main/config/etc/console-capture.xml | 2
jetty-util/src/main/config/modules/console-capture.mod | 2
jetty-util/src/main/config/modules/jcl-slf4j.mod | 2
jetty-util/src/main/config/modules/jul-impl.mod | 2
jetty-util/src/main/config/modules/jul-slf4j.mod | 2
jetty-util/src/main/config/modules/log4j-impl.mod | 2
jetty-util/src/main/config/modules/log4j2-api.mod | 2
jetty-util/src/main/config/modules/log4j2-impl.mod | 2
jetty-util/src/main/config/modules/log4j2-slf4j.mod | 2
jetty-util/src/main/config/modules/logback-impl.mod | 2
jetty-util/src/main/config/modules/logging-jetty.mod | 2
jetty-util/src/main/config/modules/logging-jul.mod | 2
jetty-util/src/main/config/modules/logging-log4j.mod | 2
jetty-util/src/main/config/modules/logging-log4j2.mod | 2
jetty-util/src/main/config/modules/logging-logback.mod | 2
jetty-util/src/main/config/modules/logging-slf4j.mod | 2
jetty-util/src/main/config/modules/slf4j-api.mod | 2
jetty-util/src/main/config/modules/slf4j-jul.mod | 2
jetty-util/src/main/config/modules/slf4j-log4j.mod | 2
jetty-util/src/main/config/modules/slf4j-log4j2.mod | 2
jetty-util/src/main/config/modules/slf4j-logback.mod | 2
jetty-util/src/main/config/modules/slf4j-simple-impl.mod | 2
jetty-util/src/main/java/org/eclipse/jetty/util/CharsetStringBuilder.java | 312
jetty-util/src/main/java/org/eclipse/jetty/util/IteratingCallback.java | 311
jetty-util/src/main/java/org/eclipse/jetty/util/Jetty.java | 2
jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStreamParser.java | 23
jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java | 73
jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java | 4
jetty-util/src/test/java/org/eclipse/jetty/util/IteratingCallbackTest.java | 84
jetty-util/src/test/java/org/eclipse/jetty/util/LazyListTest.java | 4
jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java | 2
jetty-util/src/test/java/org/eclipse/jetty/util/URIUtilTest.java | 39
jetty-util/src/test/java/org/eclipse/jetty/util/Utf8LineParserTest.java | 2
jetty-util/src/test/java/org/eclipse/jetty/util/resource/FileSystemResourceTest.java | 2
jetty-webapp/pom.xml | 2
jetty-webapp/src/main/config/etc/jetty-webapp.xml | 2
jetty-webapp/src/main/config/modules/webapp.mod | 2
jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java | 4
jetty-websocket/javax-websocket-client-impl/pom.xml | 2
jetty-websocket/javax-websocket-client-impl/src/test/resources/examples/jetty-websocket-httpclient.xml | 2
jetty-websocket/javax-websocket-server-impl/pom.xml | 2
jetty-websocket/javax-websocket-server-impl/src/main/config/modules/websocket.mod | 2
jetty-websocket/jetty-websocket-tests/pom.xml | 2
jetty-websocket/pom.xml | 2
jetty-websocket/websocket-api/pom.xml | 2
jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/ExtensionFactory.java | 7
jetty-websocket/websocket-client/pom.xml | 2
jetty-websocket/websocket-client/src/test/resources/httpclient/simple/jetty-websocket-httpclient.xml | 2
jetty-websocket/websocket-common/pom.xml | 2
jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/WebSocketRemoteEndpointTest.java | 2
jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/FragmentExtensionTest.java | 2
jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/FrameFlusherTest.java | 2
jetty-websocket/websocket-server/pom.xml | 2
jetty-websocket/websocket-servlet/pom.xml | 2
jetty-xml/pom.xml | 2
jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java | 55
jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlParser.java | 35
jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java | 57
jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlParserTest.java | 37
jetty-xml/src/test/resources/org/eclipse/jetty/xml/configureWithAttr.xml | 2
jetty-xml/src/test/resources/org/eclipse/jetty/xml/configureWithElements.xml | 2
jetty-xml/src/test/resources/org/eclipse/jetty/xml/mortbay.xml | 3
pom.xml | 226
scripts/release-jetty.sh | 11
tests/pom.xml | 2
tests/test-continuation/pom.xml | 2
tests/test-distribution/pom.xml | 18
tests/test-distribution/src/test/java/org/eclipse/jetty/tests/distribution/AbstractDistributionTest.java | 5
tests/test-distribution/src/test/java/org/eclipse/jetty/tests/distribution/DemoBaseTests.java | 7
tests/test-distribution/src/test/resources/badapp/badapp_throwonunavailable_false.xml | 2
tests/test-distribution/src/test/resources/badapp/badapp_throwonunavailable_true.xml | 2
tests/test-distribution/src/test/resources/test-realm.xml | 2
tests/test-http-client-transport/pom.xml | 2
tests/test-integration/pom.xml | 2
tests/test-integration/src/test/java/org/eclipse/jetty/test/AllowedResourceAliasCheckerTest.java | 88
tests/test-integration/src/test/java/org/eclipse/jetty/test/DeploymentErrorInitializer.java | 2
tests/test-integration/src/test/java/org/eclipse/jetty/test/HttpInputInterceptorTest.java | 14
tests/test-integration/src/test/java/org/eclipse/jetty/test/jsp/JspAndDefaultWithAliasesTest.java | 30
tests/test-integration/src/test/resources/DefaultHandler.xml | 2
tests/test-integration/src/test/resources/NIOHttp.xml | 2
tests/test-integration/src/test/resources/NIOHttps.xml | 2
tests/test-integration/src/test/resources/RFC2616Base.xml | 6
tests/test-integration/src/test/resources/RFC2616_Filters.xml | 2
tests/test-integration/src/test/resources/RFC2616_Redirects.xml | 2
tests/test-integration/src/test/resources/docroots/deployerror/badapp-unavailable-false.xml | 2
tests/test-integration/src/test/resources/docroots/deployerror/badapp.xml | 2
tests/test-integration/src/test/resources/ssl.xml | 2
tests/test-integration/src/test/resources/webapp-contexts/RFC2616/rfc2616-webapp.xml | 2
tests/test-jmx/jmx-webapp-it/pom.xml | 2
tests/test-jmx/jmx-webapp/pom.xml | 2
tests/test-jmx/pom.xml | 2
tests/test-loginservice/pom.xml | 7
tests/test-quickstart/pom.xml | 2
tests/test-quickstart/src/test/resources/test-jndi.xml | 2
tests/test-quickstart/src/test/resources/test-spec.xml | 2
tests/test-quickstart/src/test/resources/test.xml | 2
tests/test-sessions/pom.xml | 2
tests/test-sessions/test-file-sessions/pom.xml | 2
tests/test-sessions/test-gcloud-sessions/pom.xml | 7
tests/test-sessions/test-hazelcast-sessions/pom.xml | 2
tests/test-sessions/test-infinispan-sessions/pom.xml | 7
tests/test-sessions/test-jdbc-sessions/pom.xml | 7
tests/test-sessions/test-memcached-sessions/pom.xml | 7
tests/test-sessions/test-mongodb-sessions/pom.xml | 7
tests/test-sessions/test-sessions-common/pom.xml | 2
tests/test-webapps/pom.xml | 2
tests/test-webapps/test-cdi-common-webapp/pom.xml | 2
tests/test-webapps/test-felix-webapp/pom.xml | 2
tests/test-webapps/test-http2-webapp/pom.xml | 2
tests/test-webapps/test-jaas-webapp/pom.xml | 2
tests/test-webapps/test-jaas-webapp/src/main/config/demo-base/webapps/test-jaas.xml | 2
tests/test-webapps/test-jaas-webapp/src/main/webapp/WEB-INF/jetty-web.xml | 2
tests/test-webapps/test-jaas-webapp/src/main/webapp/index.html | 6
tests/test-webapps/test-jetty-webapp/pom.xml | 3
tests/test-webapps/test-jetty-webapp/src/main/assembly/embedded-jetty-web-for-webbundle.xml | 2
tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/etc/demo-rewrite-rules.xml | 2
tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/etc/test-realm.xml | 2
tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/webapps/test.xml | 2
tests/test-webapps/test-jetty-webapp/src/main/webapp/WEB-INF/jetty-web.xml | 2
tests/test-webapps/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml | 12
tests/test-webapps/test-jetty-webapp/src/main/webapp/index.html | 6
tests/test-webapps/test-jetty-webapp/src/main/webapp/remote.html | 6
tests/test-webapps/test-jndi-webapp/pom.xml | 2
tests/test-webapps/test-jndi-webapp/src/main/templates/jetty-test-jndi-header.xml | 2
tests/test-webapps/test-jndi-webapp/src/main/templates/plugin-context-header.xml | 2
tests/test-webapps/test-jndi-webapp/src/main/webapp/WEB-INF/jetty-env.xml | 2
tests/test-webapps/test-jndi-webapp/src/main/webapp/WEB-INF/jetty-web.xml | 2
tests/test-webapps/test-jndi-webapp/src/main/webapp/index.html | 4
tests/test-webapps/test-mock-resources/pom.xml | 2
tests/test-webapps/test-owb-cdi-webapp/pom.xml | 2
tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/jetty-env.xml | 2
tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/jetty-web-owb.xml | 4
tests/test-webapps/test-proxy-webapp/pom.xml | 2
tests/test-webapps/test-proxy-webapp/src/main/webapp/WEB-INF/jetty-web.xml | 2
tests/test-webapps/test-proxy-webapp/src/main/webapp/WEB-INF/web.xml | 6
tests/test-webapps/test-proxy-webapp/src/test/java/org/eclipse/jetty/ProxyWebAppTest.java | 5
tests/test-webapps/test-servlet-spec/pom.xml | 2
tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml | 2
tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml | 2
tests/test-webapps/test-servlet-spec/test-spec-webapp/src/main/templates/annotations-context-header.xml | 2
tests/test-webapps/test-servlet-spec/test-spec-webapp/src/main/templates/plugin-context-header.xml | 2
tests/test-webapps/test-servlet-spec/test-spec-webapp/src/main/webapp/WEB-INF/jetty-env.xml | 2
tests/test-webapps/test-servlet-spec/test-spec-webapp/src/main/webapp/WEB-INF/jetty-web.xml | 2
tests/test-webapps/test-servlet-spec/test-spec-webapp/src/main/webapp/index.html | 6
tests/test-webapps/test-servlet-spec/test-spec-webapp/src/test/jetty-plugin-env.xml | 2
tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml | 2
tests/test-webapps/test-simple-session-webapp/pom.xml | 2
tests/test-webapps/test-simple-webapp/pom.xml | 2
tests/test-webapps/test-webapp-rfc2616/pom.xml | 2
tests/test-webapps/test-websocket-client-provided-webapp/pom.xml | 2
tests/test-webapps/test-websocket-client-provided-webapp/src/main/resources/jetty-websocket-httpclient.xml | 2
tests/test-webapps/test-websocket-client-webapp/pom.xml | 2
tests/test-webapps/test-weld-cdi-webapp/pom.xml | 2
tests/test-webapps/test-weld-cdi-webapp/src/main/webapp/WEB-INF/jetty-env.xml | 2
631 files changed, 7458 insertions(+), 13760 deletions(-)
diff -Nru jetty9-9.4.50/CODE_OF_CONDUCT.md jetty9-9.4.57/CODE_OF_CONDUCT.md
--- jetty9-9.4.50/CODE_OF_CONDUCT.md 1970-01-01 00:00:00.000000000 +0000
+++ jetty9-9.4.57/CODE_OF_CONDUCT.md 2024-12-19 21:51:26.000000000 +0000
@@ -0,0 +1,93 @@
+# Community Code of Conduct
+
+**Version 2.0
+January 1, 2023**
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as community members, contributors, Committers[^1], and Project Leads (collectively "Contributors") pledge to make participation in our projects and our community a harassment-free and inclusive experience for everyone.
+
+This Community Code of Conduct ("Code") outlines our behavior expectations as members of our community in all Eclipse Foundation activities, both offline and online. It is not intended to govern scenarios or behaviors outside of the scope of Eclipse Foundation activities. Nor is it intended to replace or supersede the protections offered to all our community members under the law. Please follow both the spirit and letter of this Code and encourage other Contributors to follow these principles into our work. Failure to read or acknowledge this Code does not excuse a Contributor from compliance with the Code.
+
+## Our Standards
+
+Examples of behavior that contribute to creating a positive and professional environment include:
+
+- Using welcoming and inclusive language;
+- Actively encouraging all voices;
+- Helping others bring their perspectives and listening actively. If you find yourself dominating a discussion, it is especially important to encourage other voices to join in;
+- Being respectful of differing viewpoints and experiences;
+- Gracefully accepting constructive criticism;
+- Focusing on what is best for the community;
+- Showing empathy towards other community members;
+- Being direct but professional; and
+- Leading by example by holding yourself and others accountable
+
+Examples of unacceptable behavior by Contributors include:
+
+- The use of sexualized language or imagery;
+- Unwelcome sexual attention or advances;
+- Trolling, insulting/derogatory comments, and personal or political attacks;
+- Public or private harassment, repeated harassment;
+- Publishing others' private information, such as a physical or electronic address, without explicit permission;
+- Violent threats or language directed against another person;
+- Sexist, racist, or otherwise discriminatory jokes and language;
+- Posting sexually explicit or violent material;
+- Sharing private content, such as emails sent privately or non-publicly, or unlogged forums such as IRC channel history;
+- Personal insults, especially those using racist or sexist terms;
+- Excessive or unnecessary profanity;
+- Advocating for, or encouraging, any of the above behavior; and
+- Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+With the support of the Eclipse Foundation employees, consultants, officers, and directors (collectively, the "Staff"), Committers, and Project Leads, the Eclipse Foundation Conduct Committee (the "Conduct Committee") is responsible for clarifying the standards of acceptable behavior. The Conduct Committee takes appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+## Scope
+
+This Code applies within all Project, Working Group, and Interest Group spaces and communication channels of the Eclipse Foundation (collectively, "Eclipse spaces"), within any Eclipse-organized event or meeting, and in public spaces when an individual is representing an Eclipse Foundation Project, Working Group, Interest Group, or their communities. Examples of representing a Project or community include posting via an official social media account, personal accounts, or acting as an appointed representative at an online or offline event. Representation of Projects, Working Groups, and Interest Groups may be further defined and clarified by Committers, Project Leads, or the Staff.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Conduct Committee via conduct@eclipse-foundation.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Without the explicit consent of the reporter, the Conduct Committee is obligated to maintain confidentiality with regard to the reporter of an incident. The Conduct Committee is further obligated to ensure that the respondent is provided with sufficient information about the complaint to reply. If such details cannot be provided while maintaining confidentiality, the Conduct Committee will take the respondent‘s inability to provide a defense into account in its deliberations and decisions. Further details of enforcement guidelines may be posted separately.
+
+Staff, Committers and Project Leads have the right to report, remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code, or to block temporarily or permanently any Contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. Any such actions will be reported to the Conduct Committee for transparency and record keeping.
+
+Any Staff (including officers and directors of the Eclipse Foundation), Committers, Project Leads, or Conduct Committee members who are the subject of a complaint to the Conduct Committee will be recused from the process of resolving any such complaint.
+
+## Responsibility
+
+The responsibility for administering this Code rests with the Conduct Committee, with oversight by the Executive Director and the Board of Directors. For additional information on the Conduct Committee and its process, please write to Used to decoded Huffman encoded strings. Characters which are illegal field-vchar values are replaced with
-+ * either ' ' or '?' as described in RFC9110 Used to encode strings Huffman encoding. Characters are encoded with ISO-8859-1, if any multi-byte characters or
-+ * control characters are present the encoder will throw {@link EncodingException}. Used to decode string literals as described in RFC7541. The string literal representation consists of a single bit to indicate whether huffman encoding is used,
-+ * followed by the string byte length encoded with the n-bit integer representation also from RFC7541, and
-+ * the bytes of the string are directly after this. Characters which are illegal field-vchar values are replaced with
-+ * either ' ' or '?' as described in RFC9110 Sets the limit for the encoder HPACK dynamic table capacity. Setting this value to {@code 0} disables the use of the dynamic table. The HTTP/2 specification requires that stream ids are monotonically increasing,
-- * see https://tools.ietf.org/html/rfc7540#section-5.1.1.
-+ * field-vchar = VCHAR / obs-text
-+ * obs-text = %x80-FF
-+ * VCHAR = %x21-7E
-+ *
-+ * @param c the character to test.
-+ * @return the original character or the replacement character ' ' or '?',
-+ * the return value is guaranteed to be a valid ISO-8859-1 character.
-+ */
-+ public static char sanitizeFieldVchar(char c)
-+ {
-+ switch (c)
-+ {
-+ // A recipient of CR, LF, or NUL within a field value MUST either reject the message
-+ // or replace each of those characters with SP before further processing
-+ case '\r':
-+ case '\n':
-+ case 0x00:
-+ return ' ';
-+
-+ default:
-+ if (isIllegalFieldVchar(c))
-+ return '?';
-+ }
-+ return c;
-+ }
-+
-+ /**
-+ * Checks whether this is an invalid VCHAR based on RFC9110.
-+ * If this not a valid ISO-8859-1 character or a control character
-+ * we say that it is illegal.
-+ *
-+ * @param c the character to test.
-+ * @return true if this is invalid VCHAR.
-+ */
-+ public static boolean isIllegalFieldVchar(char c)
-+ {
-+ return (c >= 256 || c < ' ');
-+ }
- }
-
-diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/compression/EncodingException.java b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/EncodingException.java
-new file mode 100644
-index 0000000..5f05557
---- /dev/null
-+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/EncodingException.java
-@@ -0,0 +1,27 @@
-+//
-+// ========================================================================
-+// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
-+// ------------------------------------------------------------------------
-+// All rights reserved. This program and the accompanying materials
-+// are made available under the terms of the Eclipse Public License v1.0
-+// and Apache License v2.0 which accompanies this distribution.
-+//
-+// The Eclipse Public License is available at
-+// http://www.eclipse.org/legal/epl-v10.html
-+//
-+// The Apache License v2.0 is available at
-+// http://www.opensource.org/licenses/apache2.0.php
-+//
-+// You may elect to redistribute this code under either of these licenses.
-+// ========================================================================
-+//
-+
-+package org.eclipse.jetty.http.compression;
-+
-+public class EncodingException extends Exception
-+{
-+ public EncodingException(String message)
-+ {
-+ super(message);
-+ }
-+}
-diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/compression/Huffman.java b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/Huffman.java
-new file mode 100644
-index 0000000..6e2cb33
---- /dev/null
-+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/Huffman.java
-@@ -0,0 +1,357 @@
-+//
-+// ========================================================================
-+// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
-+// ------------------------------------------------------------------------
-+// All rights reserved. This program and the accompanying materials
-+// are made available under the terms of the Eclipse Public License v1.0
-+// and Apache License v2.0 which accompanies this distribution.
-+//
-+// The Eclipse Public License is available at
-+// http://www.eclipse.org/legal/epl-v10.html
-+//
-+// The Apache License v2.0 is available at
-+// http://www.opensource.org/licenses/apache2.0.php
-+//
-+// You may elect to redistribute this code under either of these licenses.
-+// ========================================================================
-+//
-+
-+package org.eclipse.jetty.http.compression;
-+
-+/**
-+ * This class contains the Huffman Codes defined in RFC7541.
-+ */
-+public class Huffman
-+{
-+ private Huffman()
-+ {
-+ }
-+
-+ // Appendix C: Huffman Codes
-+ // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#appendix-C
-+ static final int[][] CODES =
-+ {
-+ /* ( 0) |11111111|11000 */ {0x1ff8, 13},
-+ /* ( 1) |11111111|11111111|1011000 */ {0x7fffd8, 23},
-+ /* ( 2) |11111111|11111111|11111110|0010 */ {0xfffffe2, 28},
-+ /* ( 3) |11111111|11111111|11111110|0011 */ {0xfffffe3, 28},
-+ /* ( 4) |11111111|11111111|11111110|0100 */ {0xfffffe4, 28},
-+ /* ( 5) |11111111|11111111|11111110|0101 */ {0xfffffe5, 28},
-+ /* ( 6) |11111111|11111111|11111110|0110 */ {0xfffffe6, 28},
-+ /* ( 7) |11111111|11111111|11111110|0111 */ {0xfffffe7, 28},
-+ /* ( 8) |11111111|11111111|11111110|1000 */ {0xfffffe8, 28},
-+ /* ( 9) |11111111|11111111|11101010 */ {0xffffea, 24},
-+ /* ( 10) |11111111|11111111|11111111|111100 */ {0x3ffffffc, 30},
-+ /* ( 11) |11111111|11111111|11111110|1001 */ {0xfffffe9, 28},
-+ /* ( 12) |11111111|11111111|11111110|1010 */ {0xfffffea, 28},
-+ /* ( 13) |11111111|11111111|11111111|111101 */ {0x3ffffffd, 30},
-+ /* ( 14) |11111111|11111111|11111110|1011 */ {0xfffffeb, 28},
-+ /* ( 15) |11111111|11111111|11111110|1100 */ {0xfffffec, 28},
-+ /* ( 16) |11111111|11111111|11111110|1101 */ {0xfffffed, 28},
-+ /* ( 17) |11111111|11111111|11111110|1110 */ {0xfffffee, 28},
-+ /* ( 18) |11111111|11111111|11111110|1111 */ {0xfffffef, 28},
-+ /* ( 19) |11111111|11111111|11111111|0000 */ {0xffffff0, 28},
-+ /* ( 20) |11111111|11111111|11111111|0001 */ {0xffffff1, 28},
-+ /* ( 21) |11111111|11111111|11111111|0010 */ {0xffffff2, 28},
-+ /* ( 22) |11111111|11111111|11111111|111110 */ {0x3ffffffe, 30},
-+ /* ( 23) |11111111|11111111|11111111|0011 */ {0xffffff3, 28},
-+ /* ( 24) |11111111|11111111|11111111|0100 */ {0xffffff4, 28},
-+ /* ( 25) |11111111|11111111|11111111|0101 */ {0xffffff5, 28},
-+ /* ( 26) |11111111|11111111|11111111|0110 */ {0xffffff6, 28},
-+ /* ( 27) |11111111|11111111|11111111|0111 */ {0xffffff7, 28},
-+ /* ( 28) |11111111|11111111|11111111|1000 */ {0xffffff8, 28},
-+ /* ( 29) |11111111|11111111|11111111|1001 */ {0xffffff9, 28},
-+ /* ( 30) |11111111|11111111|11111111|1010 */ {0xffffffa, 28},
-+ /* ( 31) |11111111|11111111|11111111|1011 */ {0xffffffb, 28},
-+ /*' ' ( 32) |010100 */ {0x14, 6},
-+ /*'!' ( 33) |11111110|00 */ {0x3f8, 10},
-+ /*'"' ( 34) |11111110|01 */ {0x3f9, 10},
-+ /*'#' ( 35) |11111111|1010 */ {0xffa, 12},
-+ /*'$' ( 36) |11111111|11001 */ {0x1ff9, 13},
-+ /*'%' ( 37) |010101 */ {0x15, 6},
-+ /*'&' ( 38) |11111000 */ {0xf8, 8},
-+ /*''' ( 39) |11111111|010 */ {0x7fa, 11},
-+ /*'(' ( 40) |11111110|10 */ {0x3fa, 10},
-+ /*')' ( 41) |11111110|11 */ {0x3fb, 10},
-+ /*'*' ( 42) |11111001 */ {0xf9, 8},
-+ /*'+' ( 43) |11111111|011 */ {0x7fb, 11},
-+ /*',' ( 44) |11111010 */ {0xfa, 8},
-+ /*'-' ( 45) |010110 */ {0x16, 6},
-+ /*'.' ( 46) |010111 */ {0x17, 6},
-+ /*'/' ( 47) |011000 */ {0x18, 6},
-+ /*'0' ( 48) |00000 */ {0x0, 5},
-+ /*'1' ( 49) |00001 */ {0x1, 5},
-+ /*'2' ( 50) |00010 */ {0x2, 5},
-+ /*'3' ( 51) |011001 */ {0x19, 6},
-+ /*'4' ( 52) |011010 */ {0x1a, 6},
-+ /*'5' ( 53) |011011 */ {0x1b, 6},
-+ /*'6' ( 54) |011100 */ {0x1c, 6},
-+ /*'7' ( 55) |011101 */ {0x1d, 6},
-+ /*'8' ( 56) |011110 */ {0x1e, 6},
-+ /*'9' ( 57) |011111 */ {0x1f, 6},
-+ /*':' ( 58) |1011100 */ {0x5c, 7},
-+ /*';' ( 59) |11111011 */ {0xfb, 8},
-+ /*'<' ( 60) |11111111|1111100 */ {0x7ffc, 15},
-+ /*'=' ( 61) |100000 */ {0x20, 6},
-+ /*'>' ( 62) |11111111|1011 */ {0xffb, 12},
-+ /*'?' ( 63) |11111111|00 */ {0x3fc, 10},
-+ /*'@' ( 64) |11111111|11010 */ {0x1ffa, 13},
-+ /*'A' ( 65) |100001 */ {0x21, 6},
-+ /*'B' ( 66) |1011101 */ {0x5d, 7},
-+ /*'C' ( 67) |1011110 */ {0x5e, 7},
-+ /*'D' ( 68) |1011111 */ {0x5f, 7},
-+ /*'E' ( 69) |1100000 */ {0x60, 7},
-+ /*'F' ( 70) |1100001 */ {0x61, 7},
-+ /*'G' ( 71) |1100010 */ {0x62, 7},
-+ /*'H' ( 72) |1100011 */ {0x63, 7},
-+ /*'I' ( 73) |1100100 */ {0x64, 7},
-+ /*'J' ( 74) |1100101 */ {0x65, 7},
-+ /*'K' ( 75) |1100110 */ {0x66, 7},
-+ /*'L' ( 76) |1100111 */ {0x67, 7},
-+ /*'M' ( 77) |1101000 */ {0x68, 7},
-+ /*'N' ( 78) |1101001 */ {0x69, 7},
-+ /*'O' ( 79) |1101010 */ {0x6a, 7},
-+ /*'P' ( 80) |1101011 */ {0x6b, 7},
-+ /*'Q' ( 81) |1101100 */ {0x6c, 7},
-+ /*'R' ( 82) |1101101 */ {0x6d, 7},
-+ /*'S' ( 83) |1101110 */ {0x6e, 7},
-+ /*'T' ( 84) |1101111 */ {0x6f, 7},
-+ /*'U' ( 85) |1110000 */ {0x70, 7},
-+ /*'V' ( 86) |1110001 */ {0x71, 7},
-+ /*'W' ( 87) |1110010 */ {0x72, 7},
-+ /*'X' ( 88) |11111100 */ {0xfc, 8},
-+ /*'Y' ( 89) |1110011 */ {0x73, 7},
-+ /*'Z' ( 90) |11111101 */ {0xfd, 8},
-+ /*'[' ( 91) |11111111|11011 */ {0x1ffb, 13},
-+ /*'\' ( 92) |11111111|11111110|000 */ {0x7fff0, 19},
-+ /*']' ( 93) |11111111|11100 */ {0x1ffc, 13},
-+ /*'^' ( 94) |11111111|111100 */ {0x3ffc, 14},
-+ /*'_' ( 95) |100010 */ {0x22, 6},
-+ /*'`' ( 96) |11111111|1111101 */ {0x7ffd, 15},
-+ /*'a' ( 97) |00011 */ {0x3, 5},
-+ /*'b' ( 98) |100011 */ {0x23, 6},
-+ /*'c' ( 99) |00100 */ {0x4, 5},
-+ /*'d' (100) |100100 */ {0x24, 6},
-+ /*'e' (101) |00101 */ {0x5, 5},
-+ /*'f' (102) |100101 */ {0x25, 6},
-+ /*'g' (103) |100110 */ {0x26, 6},
-+ /*'h' (104) |100111 */ {0x27, 6},
-+ /*'i' (105) |00110 */ {0x6, 5},
-+ /*'j' (106) |1110100 */ {0x74, 7},
-+ /*'k' (107) |1110101 */ {0x75, 7},
-+ /*'l' (108) |101000 */ {0x28, 6},
-+ /*'m' (109) |101001 */ {0x29, 6},
-+ /*'n' (110) |101010 */ {0x2a, 6},
-+ /*'o' (111) |00111 */ {0x7, 5},
-+ /*'p' (112) |101011 */ {0x2b, 6},
-+ /*'q' (113) |1110110 */ {0x76, 7},
-+ /*'r' (114) |101100 */ {0x2c, 6},
-+ /*'s' (115) |01000 */ {0x8, 5},
-+ /*'t' (116) |01001 */ {0x9, 5},
-+ /*'u' (117) |101101 */ {0x2d, 6},
-+ /*'v' (118) |1110111 */ {0x77, 7},
-+ /*'w' (119) |1111000 */ {0x78, 7},
-+ /*'x' (120) |1111001 */ {0x79, 7},
-+ /*'y' (121) |1111010 */ {0x7a, 7},
-+ /*'z' (122) |1111011 */ {0x7b, 7},
-+ /*'{' (123) |11111111|1111110 */ {0x7ffe, 15},
-+ /*'|' (124) |11111111|100 */ {0x7fc, 11},
-+ /*'}' (125) |11111111|111101 */ {0x3ffd, 14},
-+ /*'~' (126) |11111111|11101 */ {0x1ffd, 13},
-+ /* (127) |11111111|11111111|11111111|1100 */ {0xffffffc, 28},
-+ /* (128) |11111111|11111110|0110 */ {0xfffe6, 20},
-+ /* (129) |11111111|11111111|010010 */ {0x3fffd2, 22},
-+ /* (130) |11111111|11111110|0111 */ {0xfffe7, 20},
-+ /* (131) |11111111|11111110|1000 */ {0xfffe8, 20},
-+ /* (132) |11111111|11111111|010011 */ {0x3fffd3, 22},
-+ /* (133) |11111111|11111111|010100 */ {0x3fffd4, 22},
-+ /* (134) |11111111|11111111|010101 */ {0x3fffd5, 22},
-+ /* (135) |11111111|11111111|1011001 */ {0x7fffd9, 23},
-+ /* (136) |11111111|11111111|010110 */ {0x3fffd6, 22},
-+ /* (137) |11111111|11111111|1011010 */ {0x7fffda, 23},
-+ /* (138) |11111111|11111111|1011011 */ {0x7fffdb, 23},
-+ /* (139) |11111111|11111111|1011100 */ {0x7fffdc, 23},
-+ /* (140) |11111111|11111111|1011101 */ {0x7fffdd, 23},
-+ /* (141) |11111111|11111111|1011110 */ {0x7fffde, 23},
-+ /* (142) |11111111|11111111|11101011 */ {0xffffeb, 24},
-+ /* (143) |11111111|11111111|1011111 */ {0x7fffdf, 23},
-+ /* (144) |11111111|11111111|11101100 */ {0xffffec, 24},
-+ /* (145) |11111111|11111111|11101101 */ {0xffffed, 24},
-+ /* (146) |11111111|11111111|010111 */ {0x3fffd7, 22},
-+ /* (147) |11111111|11111111|1100000 */ {0x7fffe0, 23},
-+ /* (148) |11111111|11111111|11101110 */ {0xffffee, 24},
-+ /* (149) |11111111|11111111|1100001 */ {0x7fffe1, 23},
-+ /* (150) |11111111|11111111|1100010 */ {0x7fffe2, 23},
-+ /* (151) |11111111|11111111|1100011 */ {0x7fffe3, 23},
-+ /* (152) |11111111|11111111|1100100 */ {0x7fffe4, 23},
-+ /* (153) |11111111|11111110|11100 */ {0x1fffdc, 21},
-+ /* (154) |11111111|11111111|011000 */ {0x3fffd8, 22},
-+ /* (155) |11111111|11111111|1100101 */ {0x7fffe5, 23},
-+ /* (156) |11111111|11111111|011001 */ {0x3fffd9, 22},
-+ /* (157) |11111111|11111111|1100110 */ {0x7fffe6, 23},
-+ /* (158) |11111111|11111111|1100111 */ {0x7fffe7, 23},
-+ /* (159) |11111111|11111111|11101111 */ {0xffffef, 24},
-+ /* (160) |11111111|11111111|011010 */ {0x3fffda, 22},
-+ /* (161) |11111111|11111110|11101 */ {0x1fffdd, 21},
-+ /* (162) |11111111|11111110|1001 */ {0xfffe9, 20},
-+ /* (163) |11111111|11111111|011011 */ {0x3fffdb, 22},
-+ /* (164) |11111111|11111111|011100 */ {0x3fffdc, 22},
-+ /* (165) |11111111|11111111|1101000 */ {0x7fffe8, 23},
-+ /* (166) |11111111|11111111|1101001 */ {0x7fffe9, 23},
-+ /* (167) |11111111|11111110|11110 */ {0x1fffde, 21},
-+ /* (168) |11111111|11111111|1101010 */ {0x7fffea, 23},
-+ /* (169) |11111111|11111111|011101 */ {0x3fffdd, 22},
-+ /* (170) |11111111|11111111|011110 */ {0x3fffde, 22},
-+ /* (171) |11111111|11111111|11110000 */ {0xfffff0, 24},
-+ /* (172) |11111111|11111110|11111 */ {0x1fffdf, 21},
-+ /* (173) |11111111|11111111|011111 */ {0x3fffdf, 22},
-+ /* (174) |11111111|11111111|1101011 */ {0x7fffeb, 23},
-+ /* (175) |11111111|11111111|1101100 */ {0x7fffec, 23},
-+ /* (176) |11111111|11111111|00000 */ {0x1fffe0, 21},
-+ /* (177) |11111111|11111111|00001 */ {0x1fffe1, 21},
-+ /* (178) |11111111|11111111|100000 */ {0x3fffe0, 22},
-+ /* (179) |11111111|11111111|00010 */ {0x1fffe2, 21},
-+ /* (180) |11111111|11111111|1101101 */ {0x7fffed, 23},
-+ /* (181) |11111111|11111111|100001 */ {0x3fffe1, 22},
-+ /* (182) |11111111|11111111|1101110 */ {0x7fffee, 23},
-+ /* (183) |11111111|11111111|1101111 */ {0x7fffef, 23},
-+ /* (184) |11111111|11111110|1010 */ {0xfffea, 20},
-+ /* (185) |11111111|11111111|100010 */ {0x3fffe2, 22},
-+ /* (186) |11111111|11111111|100011 */ {0x3fffe3, 22},
-+ /* (187) |11111111|11111111|100100 */ {0x3fffe4, 22},
-+ /* (188) |11111111|11111111|1110000 */ {0x7ffff0, 23},
-+ /* (189) |11111111|11111111|100101 */ {0x3fffe5, 22},
-+ /* (190) |11111111|11111111|100110 */ {0x3fffe6, 22},
-+ /* (191) |11111111|11111111|1110001 */ {0x7ffff1, 23},
-+ /* (192) |11111111|11111111|11111000|00 */ {0x3ffffe0, 26},
-+ /* (193) |11111111|11111111|11111000|01 */ {0x3ffffe1, 26},
-+ /* (194) |11111111|11111110|1011 */ {0xfffeb, 20},
-+ /* (195) |11111111|11111110|001 */ {0x7fff1, 19},
-+ /* (196) |11111111|11111111|100111 */ {0x3fffe7, 22},
-+ /* (197) |11111111|11111111|1110010 */ {0x7ffff2, 23},
-+ /* (198) |11111111|11111111|101000 */ {0x3fffe8, 22},
-+ /* (199) |11111111|11111111|11110110|0 */ {0x1ffffec, 25},
-+ /* (200) |11111111|11111111|11111000|10 */ {0x3ffffe2, 26},
-+ /* (201) |11111111|11111111|11111000|11 */ {0x3ffffe3, 26},
-+ /* (202) |11111111|11111111|11111001|00 */ {0x3ffffe4, 26},
-+ /* (203) |11111111|11111111|11111011|110 */ {0x7ffffde, 27},
-+ /* (204) |11111111|11111111|11111011|111 */ {0x7ffffdf, 27},
-+ /* (205) |11111111|11111111|11111001|01 */ {0x3ffffe5, 26},
-+ /* (206) |11111111|11111111|11110001 */ {0xfffff1, 24},
-+ /* (207) |11111111|11111111|11110110|1 */ {0x1ffffed, 25},
-+ /* (208) |11111111|11111110|010 */ {0x7fff2, 19},
-+ /* (209) |11111111|11111111|00011 */ {0x1fffe3, 21},
-+ /* (210) |11111111|11111111|11111001|10 */ {0x3ffffe6, 26},
-+ /* (211) |11111111|11111111|11111100|000 */ {0x7ffffe0, 27},
-+ /* (212) |11111111|11111111|11111100|001 */ {0x7ffffe1, 27},
-+ /* (213) |11111111|11111111|11111001|11 */ {0x3ffffe7, 26},
-+ /* (214) |11111111|11111111|11111100|010 */ {0x7ffffe2, 27},
-+ /* (215) |11111111|11111111|11110010 */ {0xfffff2, 24},
-+ /* (216) |11111111|11111111|00100 */ {0x1fffe4, 21},
-+ /* (217) |11111111|11111111|00101 */ {0x1fffe5, 21},
-+ /* (218) |11111111|11111111|11111010|00 */ {0x3ffffe8, 26},
-+ /* (219) |11111111|11111111|11111010|01 */ {0x3ffffe9, 26},
-+ /* (220) |11111111|11111111|11111111|1101 */ {0xffffffd, 28},
-+ /* (221) |11111111|11111111|11111100|011 */ {0x7ffffe3, 27},
-+ /* (222) |11111111|11111111|11111100|100 */ {0x7ffffe4, 27},
-+ /* (223) |11111111|11111111|11111100|101 */ {0x7ffffe5, 27},
-+ /* (224) |11111111|11111110|1100 */ {0xfffec, 20},
-+ /* (225) |11111111|11111111|11110011 */ {0xfffff3, 24},
-+ /* (226) |11111111|11111110|1101 */ {0xfffed, 20},
-+ /* (227) |11111111|11111111|00110 */ {0x1fffe6, 21},
-+ /* (228) |11111111|11111111|101001 */ {0x3fffe9, 22},
-+ /* (229) |11111111|11111111|00111 */ {0x1fffe7, 21},
-+ /* (230) |11111111|11111111|01000 */ {0x1fffe8, 21},
-+ /* (231) |11111111|11111111|1110011 */ {0x7ffff3, 23},
-+ /* (232) |11111111|11111111|101010 */ {0x3fffea, 22},
-+ /* (233) |11111111|11111111|101011 */ {0x3fffeb, 22},
-+ /* (234) |11111111|11111111|11110111|0 */ {0x1ffffee, 25},
-+ /* (235) |11111111|11111111|11110111|1 */ {0x1ffffef, 25},
-+ /* (236) |11111111|11111111|11110100 */ {0xfffff4, 24},
-+ /* (237) |11111111|11111111|11110101 */ {0xfffff5, 24},
-+ /* (238) |11111111|11111111|11111010|10 */ {0x3ffffea, 26},
-+ /* (239) |11111111|11111111|1110100 */ {0x7ffff4, 23},
-+ /* (240) |11111111|11111111|11111010|11 */ {0x3ffffeb, 26},
-+ /* (241) |11111111|11111111|11111100|110 */ {0x7ffffe6, 27},
-+ /* (242) |11111111|11111111|11111011|00 */ {0x3ffffec, 26},
-+ /* (243) |11111111|11111111|11111011|01 */ {0x3ffffed, 26},
-+ /* (244) |11111111|11111111|11111100|111 */ {0x7ffffe7, 27},
-+ /* (245) |11111111|11111111|11111101|000 */ {0x7ffffe8, 27},
-+ /* (246) |11111111|11111111|11111101|001 */ {0x7ffffe9, 27},
-+ /* (247) |11111111|11111111|11111101|010 */ {0x7ffffea, 27},
-+ /* (248) |11111111|11111111|11111101|011 */ {0x7ffffeb, 27},
-+ /* (249) |11111111|11111111|11111111|1110 */ {0xffffffe, 28},
-+ /* (250) |11111111|11111111|11111101|100 */ {0x7ffffec, 27},
-+ /* (251) |11111111|11111111|11111101|101 */ {0x7ffffed, 27},
-+ /* (252) |11111111|11111111|11111101|110 */ {0x7ffffee, 27},
-+ /* (253) |11111111|11111111|11111101|111 */ {0x7ffffef, 27},
-+ /* (254) |11111111|11111111|11111110|000 */ {0x7fffff0, 27},
-+ /* (255) |11111111|11111111|11111011|10 */ {0x3ffffee, 26},
-+ /*EOS (256) |11111111|11111111|11111111|111111 */ {0x3fffffff, 30}
-+ };
-+
-+ static final int[][] LCCODES = new int[CODES.length][];
-+ static final char EOS = 256;
-+
-+ // Huffman decode tree stored in a flattened char array for good
-+ // locality of reference.
-+ static final char[] tree;
-+ static final char[] rowsym;
-+ static final byte[] rowbits;
-+
-+ // Build the Huffman lookup tree and LC TABLE
-+ static
-+ {
-+ System.arraycopy(CODES, 0, LCCODES, 0, CODES.length);
-+ for (int i = 'A'; i <= 'Z'; i++)
-+ {
-+ LCCODES[i] = LCCODES['a' + i - 'A'];
-+ }
-+
-+ int r = 0;
-+ for (int[] ints : CODES)
-+ {
-+ r += (ints[1] + 7) / 8;
-+ }
-+ tree = new char[r * 256];
-+ rowsym = new char[r];
-+ rowbits = new byte[r];
-+
-+ r = 0;
-+ for (int sym = 0; sym < CODES.length; sym++)
-+ {
-+ int code = CODES[sym][0];
-+ int len = CODES[sym][1];
-+
-+ int current = 0;
-+
-+ while (len > 8)
-+ {
-+ len -= 8;
-+ int i = ((code >>> len) & 0xFF);
-+
-+ int t = current * 256 + i;
-+ current = tree[t];
-+ if (current == 0)
-+ {
-+ tree[t] = (char)++r;
-+ current = r;
-+ }
-+ }
-+
-+ int terminal = ++r;
-+ rowsym[r] = (char)sym;
-+ int b = len & 0x07;
-+ int terminalBits = b == 0 ? 8 : b;
-+
-+ rowbits[r] = (byte)terminalBits;
-+ int shift = 8 - len;
-+ int start = current * 256 + ((code << shift) & 0xFF);
-+ int end = start + (1 << shift);
-+ for (int i = start; i < end; i++)
-+ {
-+ tree[i] = (char)terminal;
-+ }
-+ }
-+ }
-+}
-diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanDecoder.java b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanDecoder.java
-new file mode 100644
-index 0000000..48851c1
---- /dev/null
-+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanDecoder.java
-@@ -0,0 +1,143 @@
-+//
-+// ========================================================================
-+// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
-+// ------------------------------------------------------------------------
-+// All rights reserved. This program and the accompanying materials
-+// are made available under the terms of the Eclipse Public License v1.0
-+// and Apache License v2.0 which accompanies this distribution.
-+//
-+// The Eclipse Public License is available at
-+// http://www.eclipse.org/legal/epl-v10.html
-+//
-+// The Apache License v2.0 is available at
-+// http://www.opensource.org/licenses/apache2.0.php
-+//
-+// You may elect to redistribute this code under either of these licenses.
-+// ========================================================================
-+//
-+
-+package org.eclipse.jetty.http.compression;
-+
-+import java.nio.ByteBuffer;
-+
-+import org.eclipse.jetty.http.HttpTokens;
-+import org.eclipse.jetty.util.CharsetStringBuilder;
-+
-+import static org.eclipse.jetty.http.compression.Huffman.rowbits;
-+import static org.eclipse.jetty.http.compression.Huffman.rowsym;
-+
-+/**
-+ *
This implementation uses a queue to atomically reserve a stream id and claim - * a slot in the queue; the slot is then assigned the entries to write.
- *Concurrent threads push slots in the queue but only one thread flushes - * the slots, up to the slot that has a non-null entries to write, therefore - * guaranteeing that frames are sent strictly in their stream id order.
- *This class also coordinates the creation of streams with the close of -- * the session, see https://tools.ietf.org/html/rfc7540#section-6.8.
-+ * the session, see -+ * RFC 7540, 6.8. - */ - private class StreamsState - { -@@ -2168,7 +2220,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio - if (flushing == null) - flushing = thread; - else if (flushing != thread) -- return; // another thread is flushing -+ return; // Another thread is flushing. - - Slot slot = slots.peek(); - entries = slot == null ? null : slot.entries; -@@ -2176,7 +2228,8 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio - if (entries == null) - { - flushing = null; -- break; // No more slots or null entries, so we may iterate on the flusher -+ // No more slots or null entries, so we may iterate on the flusher. -+ break; - } - - slots.poll(); -diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/generator/Generator.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/generator/Generator.java -index 97f9aea..b4c3c27 100644 ---- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/generator/Generator.java -+++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/generator/Generator.java -@@ -35,15 +35,21 @@ public class Generator - - public Generator(ByteBufferPool byteBufferPool) - { -- this(byteBufferPool, 4096, 0); -+ this(byteBufferPool, 0); - } - -+ @Deprecated - public Generator(ByteBufferPool byteBufferPool, int maxDynamicTableSize, int maxHeaderBlockFragment) -+ { -+ this(byteBufferPool, maxHeaderBlockFragment); -+ } -+ -+ public Generator(ByteBufferPool byteBufferPool, int maxHeaderBlockFragment) - { - this.byteBufferPool = byteBufferPool; - - headerGenerator = new HeaderGenerator(); -- hpackEncoder = new HpackEncoder(maxDynamicTableSize); -+ hpackEncoder = new HpackEncoder(); - - this.generators = new FrameGenerator[FrameType.values().length]; - this.generators[FrameType.HEADERS.getType()] = new HeadersGenerator(headerGenerator, hpackEncoder, maxHeaderBlockFragment); -@@ -66,14 +72,21 @@ public class Generator - return byteBufferPool; - } - -+ public HpackEncoder getHpackEncoder() -+ { -+ return hpackEncoder; -+ } -+ -+ @Deprecated - public void setValidateHpackEncoding(boolean validateEncoding) - { -- hpackEncoder.setValidateEncoding(validateEncoding); -+ getHpackEncoder().setValidateEncoding(validateEncoding); - } - -- public void setHeaderTableSize(int headerTableSize) -+ @Deprecated -+ public void setHeaderTableSize(int maxTableSize) - { -- hpackEncoder.setRemoteMaxDynamicTableSize(headerTableSize); -+ getHpackEncoder().setTableCapacity(maxTableSize); - } - - public void setMaxFrameSize(int maxFrameSize) -@@ -91,8 +104,9 @@ public class Generator - return dataGenerator.generate(lease, frame, maxLength); - } - -+ @Deprecated - public void setMaxHeaderListSize(int value) - { -- hpackEncoder.setMaxHeaderListSize(value); -+ getHpackEncoder().setMaxHeaderListSize(value); - } - } -diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeaderBlockParser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeaderBlockParser.java -index 48becb1..848864d 100644 ---- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeaderBlockParser.java -+++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeaderBlockParser.java -@@ -50,6 +50,11 @@ public class HeaderBlockParser - this.notifier = notifier; - } - -+ public int getMaxHeaderListSize() -+ { -+ return hpackDecoder.getMaxHeaderListSize(); -+ } -+ - /** - * Parses @{code blockLength} HPACK bytes from the given {@code buffer}. - * -diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeadersBodyParser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeadersBodyParser.java -index e222420..909d49f 100644 ---- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeadersBodyParser.java -+++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeadersBodyParser.java -@@ -194,6 +194,10 @@ public class HeadersBodyParser extends BodyParser - { - if (hasFlag(Flags.END_HEADERS)) - { -+ int maxLength = headerBlockParser.getMaxHeaderListSize(); -+ if (maxLength > 0 && length > maxLength) -+ return connectionFailure(buffer, ErrorCode.REFUSED_STREAM_ERROR.code, "invalid_headers_frame"); -+ - MetaData metaData = headerBlockParser.parse(buffer, length); - if (metaData == HeaderBlockParser.SESSION_FAILURE) - return false; -diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/Parser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/Parser.java -index 5e2dfd0..1d727f7 100644 ---- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/Parser.java -+++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/Parser.java -@@ -49,33 +49,47 @@ public class Parser - private static final Logger LOG = Log.getLogger(Parser.class); - - private final ByteBufferPool byteBufferPool; -- private final Listener listener; - private final HeaderParser headerParser; - private final HpackDecoder hpackDecoder; - private final BodyParser[] bodyParsers; -+ private Listener listener; - private UnknownBodyParser unknownBodyParser; -- private int maxFrameLength = Frame.DEFAULT_MAX_LENGTH; -+ private int maxFrameSize = Frame.DEFAULT_MAX_LENGTH; - private int maxSettingsKeys = SettingsFrame.DEFAULT_MAX_KEYS; - private boolean continuation; - private State state = State.HEADER; - -+ @Deprecated - public Parser(ByteBufferPool byteBufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize) - { -- this(byteBufferPool, listener, maxDynamicTableSize, maxHeaderSize, RateControl.NO_RATE_CONTROL); -+ this(byteBufferPool, maxHeaderSize, RateControl.NO_RATE_CONTROL); - } - -- public Parser(ByteBufferPool byteBufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize, RateControl rateControl) -+ public Parser(ByteBufferPool byteBufferPool, int maxHeaderSize) -+ { -+ this(byteBufferPool, maxHeaderSize, RateControl.NO_RATE_CONTROL); -+ } -+ -+ public Parser(ByteBufferPool byteBufferPool, int maxHeaderSize, RateControl rateControl) - { - this.byteBufferPool = byteBufferPool; -- this.listener = listener; - this.headerParser = new HeaderParser(rateControl == null ? RateControl.NO_RATE_CONTROL : rateControl); -- this.hpackDecoder = new HpackDecoder(maxDynamicTableSize, maxHeaderSize); -+ this.hpackDecoder = new HpackDecoder(maxHeaderSize); - this.bodyParsers = new BodyParser[FrameType.values().length]; - } - -+ @Deprecated - public void init(UnaryOperatorSets the limit for the capacity of the dynamic header table.
-+ *This value acts as a limit for the values received from the -+ * remote peer via the HPACK dynamic table size update instruction.
-+ *After calling this method, a SETTINGS frame must be sent to the other -+ * peer, containing the {@code SETTINGS_HEADER_TABLE_SIZE} setting with -+ * the value passed as argument to this method.
-+ * -+ * @param maxTableCapacity the limit for capacity of the dynamic header table -+ */ -+ public void setMaxTableCapacity(int maxTableCapacity) -+ { -+ _maxTableCapacity = maxTableCapacity; -+ } -+ -+ /** -+ * @param maxTableSizeLimit the local dynamic table max size -+ * @deprecated use {@link #setMaxTableCapacity(int)} instead -+ */ -+ @Deprecated -+ public void setLocalMaxDynamicTableSize(int maxTableSizeLimit) -+ { -+ setMaxTableCapacity(maxTableSizeLimit); -+ } -+ -+ public int getMaxHeaderListSize() -+ { -+ return _builder.getMaxSize(); -+ } -+ -+ public void setMaxHeaderListSize(int maxHeaderListSize) - { -- _localMaxDynamicTableSize = localMaxdynamciTableSize; -+ _builder.setMaxSize(maxHeaderListSize); - } - - public MetaData decode(ByteBuffer buffer) throws HpackException.SessionException, HpackException.StreamException -@@ -69,27 +118,22 @@ public class HpackDecoder - if (LOG.isDebugEnabled()) - LOG.debug(String.format("CtxTbl[%x] decoding %d octets", _context.hashCode(), buffer.remaining())); - -- // If the buffer is big, don't even think about decoding it -- if (buffer.remaining() > _builder.getMaxSize()) -- throw new HpackException.SessionException("431 Request Header Fields too large"); -+ // If the buffer is larger than the max headers size, don't even start decoding it. -+ int maxSize = _builder.getMaxSize(); -+ if (maxSize > 0 && buffer.remaining() > maxSize) -+ throw new HpackException.SessionException("Header fields size too large"); - - boolean emitted = false; -- - while (buffer.hasRemaining()) - { -- if (LOG.isDebugEnabled() && buffer.hasArray()) -- { -- int l = Math.min(buffer.remaining(), 32); -- LOG.debug("decode {}{}", -- TypeUtil.toHexString(buffer.array(), buffer.arrayOffset() + buffer.position(), l), -- l < buffer.remaining() ? "..." : ""); -- } -+ if (LOG.isDebugEnabled()) -+ LOG.debug("decode {}", BufferUtil.toHexString(buffer)); - - byte b = buffer.get(); - if (b < 0) - { - // 7.1 indexed if the high bit is set -- int index = NBitInteger.decode(buffer, 7); -+ int index = integerDecode(buffer, 7); - Entry entry = _context.get(index); - if (entry == null) - throw new HpackException.SessionException("Unknown index %d", index); -@@ -130,11 +174,11 @@ public class HpackDecoder - case 2: // 7.3 - case 3: // 7.3 - // change table size -- int size = NBitInteger.decode(buffer, 5); -+ int size = integerDecode(buffer, 5); - if (LOG.isDebugEnabled()) -- LOG.debug("decode resize=" + size); -- if (size > _localMaxDynamicTableSize) -- throw new IllegalArgumentException(); -+ LOG.debug("decode resize={}", size); -+ if (size > getMaxTableCapacity()) -+ throw new HpackException.CompressionException("Dynamic table resize exceeded max limit"); - if (emitted) - throw new HpackException.CompressionException("Dynamic table resize after fields"); - _context.resize(size); -@@ -143,7 +187,7 @@ public class HpackDecoder - case 0: // 7.2.2 - case 1: // 7.2.3 - indexed = false; -- nameIndex = NBitInteger.decode(buffer, 4); -+ nameIndex = integerDecode(buffer, 4); - break; - - case 4: // 7.2.1 -@@ -151,7 +195,7 @@ public class HpackDecoder - case 6: // 7.2.1 - case 7: // 7.2.1 - indexed = true; -- nameIndex = NBitInteger.decode(buffer, 6); -+ nameIndex = integerDecode(buffer, 6); - break; - - default: -@@ -170,12 +214,11 @@ public class HpackDecoder - else - { - huffmanName = (buffer.get() & 0x80) == 0x80; -- int length = NBitInteger.decode(buffer, 7); -- _builder.checkSize(length, huffmanName); -+ int length = integerDecode(buffer, 7); - if (huffmanName) -- name = Huffman.decode(buffer, length); -+ name = huffmanDecode(buffer, length); - else -- name = toASCIIString(buffer, length); -+ name = toISO88591String(buffer, length); - check: - for (int i = name.length(); i-- > 0; ) - { -@@ -211,12 +254,11 @@ public class HpackDecoder - - // decode the value - boolean huffmanValue = (buffer.get() & 0x80) == 0x80; -- int length = NBitInteger.decode(buffer, 7); -- _builder.checkSize(length, huffmanValue); -+ int length = integerDecode(buffer, 7); - if (huffmanValue) -- value = Huffman.decode(buffer, length); -+ value = huffmanDecode(buffer, length); - else -- value = toASCIIString(buffer, length); -+ value = toISO88591String(buffer, length); - - // Make the new field - HttpField field; -@@ -277,19 +319,61 @@ public class HpackDecoder - return _builder.build(); - } - -- public static String toASCIIString(ByteBuffer buffer, int length) -+ private int integerDecode(ByteBuffer buffer, int prefix) throws HpackException.CompressionException -+ { -+ try -+ { -+ if (prefix != 8) -+ buffer.position(buffer.position() - 1); -+ -+ _integerDecoder.setPrefix(prefix); -+ int decodedInt = _integerDecoder.decodeInt(buffer); -+ if (decodedInt < 0) -+ throw new EncodingException("invalid integer encoding"); -+ return decodedInt; -+ } -+ catch (EncodingException e) -+ { -+ HpackException.CompressionException compressionException = new HpackException.CompressionException(e.getMessage()); -+ compressionException.initCause(e); -+ throw compressionException; -+ } -+ finally -+ { -+ _integerDecoder.reset(); -+ } -+ } -+ -+ private String huffmanDecode(ByteBuffer buffer, int length) throws HpackException.CompressionException -+ { -+ try -+ { -+ _huffmanDecoder.setLength(length); -+ String decoded = _huffmanDecoder.decode(buffer); -+ if (decoded == null) -+ throw new HpackException.CompressionException("invalid string encoding"); -+ return decoded; -+ } -+ catch (EncodingException e) -+ { -+ HpackException.CompressionException compressionException = new HpackException.CompressionException(e.getMessage()); -+ compressionException.initCause(e); -+ throw compressionException; -+ } -+ finally -+ { -+ _huffmanDecoder.reset(); -+ } -+ } -+ -+ public static String toISO88591String(ByteBuffer buffer, int length) - { -- StringBuilder builder = new StringBuilder(length); -- int position = buffer.position(); -- int start = buffer.arrayOffset() + position; -- int end = start + length; -- buffer.position(position + length); -- byte[] array = buffer.array(); -- for (int i = start; i < end; i++) -+ CharsetStringBuilder.Iso88591StringBuilder builder = new CharsetStringBuilder.Iso88591StringBuilder(); -+ for (int i = 0; i < length; ++i) - { -- builder.append((char)(0x7f & array[i])); -+ builder.append(HttpTokens.sanitizeFieldVchar((char)buffer.get())); - } -- return builder.toString(); -+ return builder.build(); - } - - @Override -diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java -index 1011252..cb68bad 100644 ---- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java -+++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java -@@ -19,7 +19,6 @@ - package org.eclipse.jetty.http2.hpack; - - import java.nio.ByteBuffer; --import java.nio.charset.StandardCharsets; - import java.util.EnumMap; - import java.util.EnumSet; - import java.util.HashSet; -@@ -34,10 +33,13 @@ import org.eclipse.jetty.http.HttpStatus; - import org.eclipse.jetty.http.HttpVersion; - import org.eclipse.jetty.http.MetaData; - import org.eclipse.jetty.http.PreEncodedHttpField; -+import org.eclipse.jetty.http.compression.HuffmanEncoder; -+import org.eclipse.jetty.http.compression.NBitIntegerEncoder; -+import org.eclipse.jetty.http.compression.NBitStringEncoder; - import org.eclipse.jetty.http2.hpack.HpackContext.Entry; - import org.eclipse.jetty.http2.hpack.HpackContext.StaticEntry; -+import org.eclipse.jetty.util.BufferUtil; - import org.eclipse.jetty.util.StringUtil; --import org.eclipse.jetty.util.TypeUtil; - import org.eclipse.jetty.util.log.Log; - import org.eclipse.jetty.util.log.Logger; - -@@ -97,34 +99,78 @@ public class HpackEncoder - - private final HpackContext _context; - private final boolean _debug; -- private int _remoteMaxDynamicTableSize; -- private int _localMaxDynamicTableSize; -+ private int _maxTableCapacity; -+ private int _tableCapacity; - private int _maxHeaderListSize; - private int _headerListSize; - private boolean _validateEncoding = true; - -- public HpackEncoder() -- { -- this(4096, 4096, -1); -- } -- -+ @Deprecated - public HpackEncoder(int localMaxDynamicTableSize) - { - this(localMaxDynamicTableSize, 4096, -1); - } - -+ @Deprecated - public HpackEncoder(int localMaxDynamicTableSize, int remoteMaxDynamicTableSize) - { - this(localMaxDynamicTableSize, remoteMaxDynamicTableSize, -1); - } - -+ @Deprecated - public HpackEncoder(int localMaxDynamicTableSize, int remoteMaxDynamicTableSize, int maxHeaderListSize) - { -- _context = new HpackContext(remoteMaxDynamicTableSize); -- _remoteMaxDynamicTableSize = remoteMaxDynamicTableSize; -- _localMaxDynamicTableSize = localMaxDynamicTableSize; -- _maxHeaderListSize = maxHeaderListSize; -+ this(); -+ setLocalMaxDynamicTableSize(localMaxDynamicTableSize); -+ setRemoteMaxDynamicTableSize(remoteMaxDynamicTableSize); -+ setMaxHeaderListSize(maxHeaderListSize); -+ } -+ -+ public HpackEncoder() -+ { -+ _context = new HpackContext(0); - _debug = LOG.isDebugEnabled(); -+ setMaxTableCapacity(HpackContext.DEFAULT_MAX_TABLE_CAPACITY); -+ setTableCapacity(HpackContext.DEFAULT_MAX_TABLE_CAPACITY); -+ } -+ -+ public int getMaxTableCapacity() -+ { -+ return _maxTableCapacity; -+ } -+ -+ /** -+ *Sets the limit for the capacity of the dynamic header table.
-+ *This value is set by the remote peer via the -+ * {@code SETTINGS_HEADER_TABLE_SIZE} setting.
-+ * -+ * @param maxTableSizeLimit the limit for capacity of the dynamic header table -+ */ -+ public void setMaxTableCapacity(int maxTableSizeLimit) -+ { -+ _maxTableCapacity = maxTableSizeLimit; -+ } -+ -+ public int getTableCapacity() -+ { -+ return _tableCapacity; -+ } -+ -+ /** -+ *Sets the capacity of the dynamic header table.
-+ *The value of the capacity may be changed from {@code 0} -+ * up to {@link #getMaxTableCapacity()}. -+ * An HPACK instruction with the new capacity value will -+ * be sent to the decoder when the next call to -+ * {@link #encode(ByteBuffer, MetaData)} is made.
-+ * -+ * @param tableCapacity the capacity of the dynamic header table -+ */ -+ public void setTableCapacity(int tableCapacity) -+ { -+ if (tableCapacity > getMaxTableCapacity()) -+ throw new IllegalArgumentException("Max table capacity exceeded"); -+ _tableCapacity = tableCapacity; - } - - public int getMaxHeaderListSize() -@@ -142,14 +188,16 @@ public class HpackEncoder - return _context; - } - -- public void setRemoteMaxDynamicTableSize(int remoteMaxDynamicTableSize) -+ @Deprecated -+ public void setRemoteMaxDynamicTableSize(int maxTableSize) - { -- _remoteMaxDynamicTableSize = remoteMaxDynamicTableSize; -+ setTableCapacity(maxTableSize); - } - -- public void setLocalMaxDynamicTableSize(int localMaxDynamicTableSize) -+ @Deprecated -+ public void setLocalMaxDynamicTableSize(int maxTableSizeLimit) - { -- _localMaxDynamicTableSize = localMaxDynamicTableSize; -+ setMaxTableCapacity(maxTableSizeLimit); - } - - public boolean isValidateEncoding() -@@ -185,10 +233,10 @@ public class HpackEncoder - _headerListSize = 0; - int pos = buffer.position(); - -- // Check the dynamic table sizes! -- int maxDynamicTableSize = Math.min(_remoteMaxDynamicTableSize, _localMaxDynamicTableSize); -- if (maxDynamicTableSize != _context.getMaxDynamicTableSize()) -- encodeMaxDynamicTableSize(buffer, maxDynamicTableSize); -+ // If max table size changed, send the correspondent instruction. -+ int tableCapacity = getTableCapacity(); -+ if (tableCapacity != _context.getMaxDynamicTableSize()) -+ encodeMaxDynamicTableSize(buffer, tableCapacity); - - // Add Request/response meta fields - if (metadata.isRequest()) -@@ -255,13 +303,9 @@ public class HpackEncoder - } - } - -- // Check size -- if (_maxHeaderListSize > 0 && _headerListSize > _maxHeaderListSize) -- { -- LOG.warn("Header list size too large {} > {} for {}", _headerListSize, _maxHeaderListSize); -- if (LOG.isDebugEnabled()) -- LOG.debug("metadata={}", metadata); -- } -+ int maxHeaderListSize = getMaxHeaderListSize(); -+ if (maxHeaderListSize > 0 && _headerListSize > maxHeaderListSize) -+ throw new HpackException.SessionException("Header size %d > %d", _headerListSize, maxHeaderListSize); - - if (LOG.isDebugEnabled()) - LOG.debug(String.format("CtxTbl[%x] encoded %d octets", _context.hashCode(), buffer.position() - pos)); -@@ -278,13 +322,11 @@ public class HpackEncoder - } - } - -- public void encodeMaxDynamicTableSize(ByteBuffer buffer, int maxDynamicTableSize) -+ public void encodeMaxDynamicTableSize(ByteBuffer buffer, int maxTableSize) - { -- if (maxDynamicTableSize > _remoteMaxDynamicTableSize) -- throw new IllegalArgumentException(); - buffer.put((byte)0x20); -- NBitInteger.encode(buffer, 5, maxDynamicTableSize); -- _context.resize(maxDynamicTableSize); -+ NBitIntegerEncoder.encode(buffer, 5, maxTableSize); -+ _context.resize(maxTableSize); - } - - public void encode(ByteBuffer buffer, HttpField field) -@@ -295,8 +337,6 @@ public class HpackEncoder - int fieldSize = field.getName().length() + field.getValue().length(); - _headerListSize += fieldSize + 32; - -- final int p = _debug ? buffer.position() : -1; -- - String encoding = null; - - // Is there an index entry for the field? -@@ -314,9 +354,9 @@ public class HpackEncoder - { - int index = _context.index(entry); - buffer.put((byte)0x80); -- NBitInteger.encode(buffer, 7, index); -+ NBitIntegerEncoder.encode(buffer, 7, index); - if (_debug) -- encoding = "IdxField" + (entry.isStatic() ? "S" : "") + (1 + NBitInteger.octectsNeeded(7, index)); -+ encoding = "IdxField" + (entry.isStatic() ? "S" : "") + NBitIntegerEncoder.octetsNeeded(7, index); - } - } - else -@@ -390,19 +430,19 @@ public class HpackEncoder - - if (_debug) - encoding = "Lit" + -- ((name == null) ? "HuffN" : ("IdxN" + (name.isStatic() ? "S" : "") + (1 + NBitInteger.octectsNeeded(4, _context.index(name))))) + -+ ((name == null) ? "HuffN" : ("IdxN" + (name.isStatic() ? "S" : "") + (1 + NBitIntegerEncoder.octetsNeeded(4, _context.index(name))))) + - (huffman ? "HuffV" : "LitV") + - (neverIndex ? "!!Idx" : "!Idx"); - } - else if (fieldSize >= _context.getMaxDynamicTableSize() || header == HttpHeader.CONTENT_LENGTH && !"0".equals(field.getValue())) - { -- // The field is too large or a non zero content length, so do not index. -+ // The field is too large or a non-zero content length, so do not index. - indexed = false; - encodeName(buffer, (byte)0x00, 4, header.asString(), name); - encodeValue(buffer, true, field.getValue()); - if (_debug) - encoding = "Lit" + -- ((name == null) ? "HuffN" : "IdxNS" + (1 + NBitInteger.octectsNeeded(4, _context.index(name)))) + -+ ((name == null) ? "HuffN" : "IdxNS" + (1 + NBitIntegerEncoder.octetsNeeded(4, _context.index(name)))) + - "HuffV!Idx"; - } - else -@@ -413,7 +453,7 @@ public class HpackEncoder - encodeName(buffer, (byte)0x40, 6, header.asString(), name); - encodeValue(buffer, huffman, field.getValue()); - if (_debug) -- encoding = ((name == null) ? "LitHuffN" : ("LitIdxN" + (name.isStatic() ? "S" : "") + (1 + NBitInteger.octectsNeeded(6, _context.index(name))))) + -+ encoding = ((name == null) ? "LitHuffN" : ("LitIdxN" + (name.isStatic() ? "S" : "") + (1 + NBitIntegerEncoder.octetsNeeded(6, _context.index(name))))) + - (huffman ? "HuffVIdx" : "LitVIdx"); - } - } -@@ -425,10 +465,8 @@ public class HpackEncoder - - if (_debug) - { -- byte[] bytes = new byte[buffer.position() - p]; -- buffer.position(p); -- buffer.get(bytes); -- LOG.debug("encode {}:'{}' to '{}'", encoding, field, TypeUtil.toHexString(bytes)); -+ if (LOG.isDebugEnabled()) -+ LOG.debug("encode {}:'{}' to '{}'", encoding, field, BufferUtil.toHexString((ByteBuffer)buffer.duplicate().flip())); - } - } - -@@ -440,55 +478,17 @@ public class HpackEncoder - // leave name index bits as 0 - // Encode the name always with lowercase huffman - buffer.put((byte)0x80); -- NBitInteger.encode(buffer, 7, Huffman.octetsNeededLC(name)); -- Huffman.encodeLC(buffer, name); -+ NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeededLowerCase(name)); -+ HuffmanEncoder.encodeLowerCase(buffer, name); - } - else - { -- NBitInteger.encode(buffer, bits, _context.index(entry)); -+ NBitIntegerEncoder.encode(buffer, bits, _context.index(entry)); - } - } - - static void encodeValue(ByteBuffer buffer, boolean huffman, String value) - { -- if (huffman) -- { -- // huffman literal value -- buffer.put((byte)0x80); -- -- int needed = Huffman.octetsNeeded(value); -- if (needed >= 0) -- { -- NBitInteger.encode(buffer, 7, needed); -- Huffman.encode(buffer, value); -- } -- else -- { -- // Not iso_8859_1 -- byte[] bytes = value.getBytes(StandardCharsets.UTF_8); -- NBitInteger.encode(buffer, 7, Huffman.octetsNeeded(bytes)); -- Huffman.encode(buffer, bytes); -- } -- } -- else -- { -- // add literal assuming iso_8859_1 -- buffer.put((byte)0x00).mark(); -- NBitInteger.encode(buffer, 7, value.length()); -- for (int i = 0; i < value.length(); i++) -- { -- char c = value.charAt(i); -- if (c < ' ' || c > 127) -- { -- // Not iso_8859_1, so re-encode as UTF-8 -- buffer.reset(); -- byte[] bytes = value.getBytes(StandardCharsets.UTF_8); -- NBitInteger.encode(buffer, 7, bytes.length); -- buffer.put(bytes, 0, bytes.length); -- return; -- } -- buffer.put((byte)c); -- } -- } -+ NBitStringEncoder.encode(buffer, 8, value, huffman); - } - } -diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackException.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackException.java -index 2aad122..df89d80 100644 ---- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackException.java -+++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackException.java -@@ -18,7 +18,6 @@ - - package org.eclipse.jetty.http2.hpack; - --@SuppressWarnings("serial") - public abstract class HpackException extends Exception - { - HpackException(String messageFormat, Object... args) -@@ -35,7 +34,7 @@ public abstract class HpackException extends Exception - */ - public static class StreamException extends HpackException - { -- StreamException(String messageFormat, Object... args) -+ public StreamException(String messageFormat, Object... args) - { - super(messageFormat, args); - } -@@ -48,7 +47,7 @@ public abstract class HpackException extends Exception - */ - public static class SessionException extends HpackException - { -- SessionException(String messageFormat, Object... args) -+ public SessionException(String messageFormat, Object... args) - { - super(messageFormat, args); - } -diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java -index 769819d..629ef2c 100644 ---- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java -+++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java -@@ -23,6 +23,8 @@ import java.nio.ByteBuffer; - import org.eclipse.jetty.http.HttpFieldPreEncoder; - import org.eclipse.jetty.http.HttpHeader; - import org.eclipse.jetty.http.HttpVersion; -+import org.eclipse.jetty.http.compression.HuffmanEncoder; -+import org.eclipse.jetty.http.compression.NBitIntegerEncoder; - import org.eclipse.jetty.util.BufferUtil; - - /** -@@ -31,18 +33,12 @@ import org.eclipse.jetty.util.BufferUtil; - public class HpackFieldPreEncoder implements HttpFieldPreEncoder - { - -- /** -- * @see org.eclipse.jetty.http.HttpFieldPreEncoder#getHttpVersion() -- */ - @Override - public HttpVersion getHttpVersion() - { - return HttpVersion.HTTP_2; - } - -- /** -- * @see org.eclipse.jetty.http.HttpFieldPreEncoder#getEncodedField(org.eclipse.jetty.http.HttpHeader, java.lang.String, java.lang.String) -- */ - @Override - public byte[] getEncodedField(HttpHeader header, String name, String value) - { -@@ -78,12 +74,12 @@ public class HpackFieldPreEncoder implements HttpFieldPreEncoder - - int nameIdx = HpackContext.staticIndex(header); - if (nameIdx > 0) -- NBitInteger.encode(buffer, bits, nameIdx); -+ NBitIntegerEncoder.encode(buffer, bits, nameIdx); - else - { - buffer.put((byte)0x80); -- NBitInteger.encode(buffer, 7, Huffman.octetsNeededLC(name)); -- Huffman.encodeLC(buffer, name); -+ NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeededLowerCase(name)); -+ HuffmanEncoder.encodeLowerCase(buffer, name); - } - - HpackEncoder.encodeValue(buffer, huffman, value); -diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java -deleted file mode 100644 -index 26e948b..0000000 ---- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java -+++ /dev/null -@@ -1,551 +0,0 @@ --// --// ======================================================================== --// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. --// ------------------------------------------------------------------------ --// All rights reserved. This program and the accompanying materials --// are made available under the terms of the Eclipse Public License v1.0 --// and Apache License v2.0 which accompanies this distribution. --// --// The Eclipse Public License is available at --// http://www.eclipse.org/legal/epl-v10.html --// --// The Apache License v2.0 is available at --// http://www.opensource.org/licenses/apache2.0.php --// --// You may elect to redistribute this code under either of these licenses. --// ======================================================================== --// -- --package org.eclipse.jetty.http2.hpack; -- --import java.nio.ByteBuffer; -- --import org.eclipse.jetty.util.Utf8StringBuilder; -- --public class Huffman --{ -- -- // Appendix C: Huffman Codes -- // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#appendix-C -- static final int[][] CODES = -- { -- /* ( 0) |11111111|11000 */ {0x1ff8, 13}, -- /* ( 1) |11111111|11111111|1011000 */ {0x7fffd8, 23}, -- /* ( 2) |11111111|11111111|11111110|0010 */ {0xfffffe2, 28}, -- /* ( 3) |11111111|11111111|11111110|0011 */ {0xfffffe3, 28}, -- /* ( 4) |11111111|11111111|11111110|0100 */ {0xfffffe4, 28}, -- /* ( 5) |11111111|11111111|11111110|0101 */ {0xfffffe5, 28}, -- /* ( 6) |11111111|11111111|11111110|0110 */ {0xfffffe6, 28}, -- /* ( 7) |11111111|11111111|11111110|0111 */ {0xfffffe7, 28}, -- /* ( 8) |11111111|11111111|11111110|1000 */ {0xfffffe8, 28}, -- /* ( 9) |11111111|11111111|11101010 */ {0xffffea, 24}, -- /* ( 10) |11111111|11111111|11111111|111100 */ {0x3ffffffc, 30}, -- /* ( 11) |11111111|11111111|11111110|1001 */ {0xfffffe9, 28}, -- /* ( 12) |11111111|11111111|11111110|1010 */ {0xfffffea, 28}, -- /* ( 13) |11111111|11111111|11111111|111101 */ {0x3ffffffd, 30}, -- /* ( 14) |11111111|11111111|11111110|1011 */ {0xfffffeb, 28}, -- /* ( 15) |11111111|11111111|11111110|1100 */ {0xfffffec, 28}, -- /* ( 16) |11111111|11111111|11111110|1101 */ {0xfffffed, 28}, -- /* ( 17) |11111111|11111111|11111110|1110 */ {0xfffffee, 28}, -- /* ( 18) |11111111|11111111|11111110|1111 */ {0xfffffef, 28}, -- /* ( 19) |11111111|11111111|11111111|0000 */ {0xffffff0, 28}, -- /* ( 20) |11111111|11111111|11111111|0001 */ {0xffffff1, 28}, -- /* ( 21) |11111111|11111111|11111111|0010 */ {0xffffff2, 28}, -- /* ( 22) |11111111|11111111|11111111|111110 */ {0x3ffffffe, 30}, -- /* ( 23) |11111111|11111111|11111111|0011 */ {0xffffff3, 28}, -- /* ( 24) |11111111|11111111|11111111|0100 */ {0xffffff4, 28}, -- /* ( 25) |11111111|11111111|11111111|0101 */ {0xffffff5, 28}, -- /* ( 26) |11111111|11111111|11111111|0110 */ {0xffffff6, 28}, -- /* ( 27) |11111111|11111111|11111111|0111 */ {0xffffff7, 28}, -- /* ( 28) |11111111|11111111|11111111|1000 */ {0xffffff8, 28}, -- /* ( 29) |11111111|11111111|11111111|1001 */ {0xffffff9, 28}, -- /* ( 30) |11111111|11111111|11111111|1010 */ {0xffffffa, 28}, -- /* ( 31) |11111111|11111111|11111111|1011 */ {0xffffffb, 28}, -- /*' ' ( 32) |010100 */ {0x14, 6}, -- /*'!' ( 33) |11111110|00 */ {0x3f8, 10}, -- /*'"' ( 34) |11111110|01 */ {0x3f9, 10}, -- /*'#' ( 35) |11111111|1010 */ {0xffa, 12}, -- /*'$' ( 36) |11111111|11001 */ {0x1ff9, 13}, -- /*'%' ( 37) |010101 */ {0x15, 6}, -- /*'&' ( 38) |11111000 */ {0xf8, 8}, -- /*''' ( 39) |11111111|010 */ {0x7fa, 11}, -- /*'(' ( 40) |11111110|10 */ {0x3fa, 10}, -- /*')' ( 41) |11111110|11 */ {0x3fb, 10}, -- /*'*' ( 42) |11111001 */ {0xf9, 8}, -- /*'+' ( 43) |11111111|011 */ {0x7fb, 11}, -- /*',' ( 44) |11111010 */ {0xfa, 8}, -- /*'-' ( 45) |010110 */ {0x16, 6}, -- /*'.' ( 46) |010111 */ {0x17, 6}, -- /*'/' ( 47) |011000 */ {0x18, 6}, -- /*'0' ( 48) |00000 */ {0x0, 5}, -- /*'1' ( 49) |00001 */ {0x1, 5}, -- /*'2' ( 50) |00010 */ {0x2, 5}, -- /*'3' ( 51) |011001 */ {0x19, 6}, -- /*'4' ( 52) |011010 */ {0x1a, 6}, -- /*'5' ( 53) |011011 */ {0x1b, 6}, -- /*'6' ( 54) |011100 */ {0x1c, 6}, -- /*'7' ( 55) |011101 */ {0x1d, 6}, -- /*'8' ( 56) |011110 */ {0x1e, 6}, -- /*'9' ( 57) |011111 */ {0x1f, 6}, -- /*':' ( 58) |1011100 */ {0x5c, 7}, -- /*';' ( 59) |11111011 */ {0xfb, 8}, -- /*'<' ( 60) |11111111|1111100 */ {0x7ffc, 15}, -- /*'=' ( 61) |100000 */ {0x20, 6}, -- /*'>' ( 62) |11111111|1011 */ {0xffb, 12}, -- /*'?' ( 63) |11111111|00 */ {0x3fc, 10}, -- /*'@' ( 64) |11111111|11010 */ {0x1ffa, 13}, -- /*'A' ( 65) |100001 */ {0x21, 6}, -- /*'B' ( 66) |1011101 */ {0x5d, 7}, -- /*'C' ( 67) |1011110 */ {0x5e, 7}, -- /*'D' ( 68) |1011111 */ {0x5f, 7}, -- /*'E' ( 69) |1100000 */ {0x60, 7}, -- /*'F' ( 70) |1100001 */ {0x61, 7}, -- /*'G' ( 71) |1100010 */ {0x62, 7}, -- /*'H' ( 72) |1100011 */ {0x63, 7}, -- /*'I' ( 73) |1100100 */ {0x64, 7}, -- /*'J' ( 74) |1100101 */ {0x65, 7}, -- /*'K' ( 75) |1100110 */ {0x66, 7}, -- /*'L' ( 76) |1100111 */ {0x67, 7}, -- /*'M' ( 77) |1101000 */ {0x68, 7}, -- /*'N' ( 78) |1101001 */ {0x69, 7}, -- /*'O' ( 79) |1101010 */ {0x6a, 7}, -- /*'P' ( 80) |1101011 */ {0x6b, 7}, -- /*'Q' ( 81) |1101100 */ {0x6c, 7}, -- /*'R' ( 82) |1101101 */ {0x6d, 7}, -- /*'S' ( 83) |1101110 */ {0x6e, 7}, -- /*'T' ( 84) |1101111 */ {0x6f, 7}, -- /*'U' ( 85) |1110000 */ {0x70, 7}, -- /*'V' ( 86) |1110001 */ {0x71, 7}, -- /*'W' ( 87) |1110010 */ {0x72, 7}, -- /*'X' ( 88) |11111100 */ {0xfc, 8}, -- /*'Y' ( 89) |1110011 */ {0x73, 7}, -- /*'Z' ( 90) |11111101 */ {0xfd, 8}, -- /*'[' ( 91) |11111111|11011 */ {0x1ffb, 13}, -- /*'\' ( 92) |11111111|11111110|000 */ {0x7fff0, 19}, -- /*']' ( 93) |11111111|11100 */ {0x1ffc, 13}, -- /*'^' ( 94) |11111111|111100 */ {0x3ffc, 14}, -- /*'_' ( 95) |100010 */ {0x22, 6}, -- /*'`' ( 96) |11111111|1111101 */ {0x7ffd, 15}, -- /*'a' ( 97) |00011 */ {0x3, 5}, -- /*'b' ( 98) |100011 */ {0x23, 6}, -- /*'c' ( 99) |00100 */ {0x4, 5}, -- /*'d' (100) |100100 */ {0x24, 6}, -- /*'e' (101) |00101 */ {0x5, 5}, -- /*'f' (102) |100101 */ {0x25, 6}, -- /*'g' (103) |100110 */ {0x26, 6}, -- /*'h' (104) |100111 */ {0x27, 6}, -- /*'i' (105) |00110 */ {0x6, 5}, -- /*'j' (106) |1110100 */ {0x74, 7}, -- /*'k' (107) |1110101 */ {0x75, 7}, -- /*'l' (108) |101000 */ {0x28, 6}, -- /*'m' (109) |101001 */ {0x29, 6}, -- /*'n' (110) |101010 */ {0x2a, 6}, -- /*'o' (111) |00111 */ {0x7, 5}, -- /*'p' (112) |101011 */ {0x2b, 6}, -- /*'q' (113) |1110110 */ {0x76, 7}, -- /*'r' (114) |101100 */ {0x2c, 6}, -- /*'s' (115) |01000 */ {0x8, 5}, -- /*'t' (116) |01001 */ {0x9, 5}, -- /*'u' (117) |101101 */ {0x2d, 6}, -- /*'v' (118) |1110111 */ {0x77, 7}, -- /*'w' (119) |1111000 */ {0x78, 7}, -- /*'x' (120) |1111001 */ {0x79, 7}, -- /*'y' (121) |1111010 */ {0x7a, 7}, -- /*'z' (122) |1111011 */ {0x7b, 7}, -- /*'{' (123) |11111111|1111110 */ {0x7ffe, 15}, -- /*'|' (124) |11111111|100 */ {0x7fc, 11}, -- /*'}' (125) |11111111|111101 */ {0x3ffd, 14}, -- /*'~' (126) |11111111|11101 */ {0x1ffd, 13}, -- /* (127) |11111111|11111111|11111111|1100 */ {0xffffffc, 28}, -- /* (128) |11111111|11111110|0110 */ {0xfffe6, 20}, -- /* (129) |11111111|11111111|010010 */ {0x3fffd2, 22}, -- /* (130) |11111111|11111110|0111 */ {0xfffe7, 20}, -- /* (131) |11111111|11111110|1000 */ {0xfffe8, 20}, -- /* (132) |11111111|11111111|010011 */ {0x3fffd3, 22}, -- /* (133) |11111111|11111111|010100 */ {0x3fffd4, 22}, -- /* (134) |11111111|11111111|010101 */ {0x3fffd5, 22}, -- /* (135) |11111111|11111111|1011001 */ {0x7fffd9, 23}, -- /* (136) |11111111|11111111|010110 */ {0x3fffd6, 22}, -- /* (137) |11111111|11111111|1011010 */ {0x7fffda, 23}, -- /* (138) |11111111|11111111|1011011 */ {0x7fffdb, 23}, -- /* (139) |11111111|11111111|1011100 */ {0x7fffdc, 23}, -- /* (140) |11111111|11111111|1011101 */ {0x7fffdd, 23}, -- /* (141) |11111111|11111111|1011110 */ {0x7fffde, 23}, -- /* (142) |11111111|11111111|11101011 */ {0xffffeb, 24}, -- /* (143) |11111111|11111111|1011111 */ {0x7fffdf, 23}, -- /* (144) |11111111|11111111|11101100 */ {0xffffec, 24}, -- /* (145) |11111111|11111111|11101101 */ {0xffffed, 24}, -- /* (146) |11111111|11111111|010111 */ {0x3fffd7, 22}, -- /* (147) |11111111|11111111|1100000 */ {0x7fffe0, 23}, -- /* (148) |11111111|11111111|11101110 */ {0xffffee, 24}, -- /* (149) |11111111|11111111|1100001 */ {0x7fffe1, 23}, -- /* (150) |11111111|11111111|1100010 */ {0x7fffe2, 23}, -- /* (151) |11111111|11111111|1100011 */ {0x7fffe3, 23}, -- /* (152) |11111111|11111111|1100100 */ {0x7fffe4, 23}, -- /* (153) |11111111|11111110|11100 */ {0x1fffdc, 21}, -- /* (154) |11111111|11111111|011000 */ {0x3fffd8, 22}, -- /* (155) |11111111|11111111|1100101 */ {0x7fffe5, 23}, -- /* (156) |11111111|11111111|011001 */ {0x3fffd9, 22}, -- /* (157) |11111111|11111111|1100110 */ {0x7fffe6, 23}, -- /* (158) |11111111|11111111|1100111 */ {0x7fffe7, 23}, -- /* (159) |11111111|11111111|11101111 */ {0xffffef, 24}, -- /* (160) |11111111|11111111|011010 */ {0x3fffda, 22}, -- /* (161) |11111111|11111110|11101 */ {0x1fffdd, 21}, -- /* (162) |11111111|11111110|1001 */ {0xfffe9, 20}, -- /* (163) |11111111|11111111|011011 */ {0x3fffdb, 22}, -- /* (164) |11111111|11111111|011100 */ {0x3fffdc, 22}, -- /* (165) |11111111|11111111|1101000 */ {0x7fffe8, 23}, -- /* (166) |11111111|11111111|1101001 */ {0x7fffe9, 23}, -- /* (167) |11111111|11111110|11110 */ {0x1fffde, 21}, -- /* (168) |11111111|11111111|1101010 */ {0x7fffea, 23}, -- /* (169) |11111111|11111111|011101 */ {0x3fffdd, 22}, -- /* (170) |11111111|11111111|011110 */ {0x3fffde, 22}, -- /* (171) |11111111|11111111|11110000 */ {0xfffff0, 24}, -- /* (172) |11111111|11111110|11111 */ {0x1fffdf, 21}, -- /* (173) |11111111|11111111|011111 */ {0x3fffdf, 22}, -- /* (174) |11111111|11111111|1101011 */ {0x7fffeb, 23}, -- /* (175) |11111111|11111111|1101100 */ {0x7fffec, 23}, -- /* (176) |11111111|11111111|00000 */ {0x1fffe0, 21}, -- /* (177) |11111111|11111111|00001 */ {0x1fffe1, 21}, -- /* (178) |11111111|11111111|100000 */ {0x3fffe0, 22}, -- /* (179) |11111111|11111111|00010 */ {0x1fffe2, 21}, -- /* (180) |11111111|11111111|1101101 */ {0x7fffed, 23}, -- /* (181) |11111111|11111111|100001 */ {0x3fffe1, 22}, -- /* (182) |11111111|11111111|1101110 */ {0x7fffee, 23}, -- /* (183) |11111111|11111111|1101111 */ {0x7fffef, 23}, -- /* (184) |11111111|11111110|1010 */ {0xfffea, 20}, -- /* (185) |11111111|11111111|100010 */ {0x3fffe2, 22}, -- /* (186) |11111111|11111111|100011 */ {0x3fffe3, 22}, -- /* (187) |11111111|11111111|100100 */ {0x3fffe4, 22}, -- /* (188) |11111111|11111111|1110000 */ {0x7ffff0, 23}, -- /* (189) |11111111|11111111|100101 */ {0x3fffe5, 22}, -- /* (190) |11111111|11111111|100110 */ {0x3fffe6, 22}, -- /* (191) |11111111|11111111|1110001 */ {0x7ffff1, 23}, -- /* (192) |11111111|11111111|11111000|00 */ {0x3ffffe0, 26}, -- /* (193) |11111111|11111111|11111000|01 */ {0x3ffffe1, 26}, -- /* (194) |11111111|11111110|1011 */ {0xfffeb, 20}, -- /* (195) |11111111|11111110|001 */ {0x7fff1, 19}, -- /* (196) |11111111|11111111|100111 */ {0x3fffe7, 22}, -- /* (197) |11111111|11111111|1110010 */ {0x7ffff2, 23}, -- /* (198) |11111111|11111111|101000 */ {0x3fffe8, 22}, -- /* (199) |11111111|11111111|11110110|0 */ {0x1ffffec, 25}, -- /* (200) |11111111|11111111|11111000|10 */ {0x3ffffe2, 26}, -- /* (201) |11111111|11111111|11111000|11 */ {0x3ffffe3, 26}, -- /* (202) |11111111|11111111|11111001|00 */ {0x3ffffe4, 26}, -- /* (203) |11111111|11111111|11111011|110 */ {0x7ffffde, 27}, -- /* (204) |11111111|11111111|11111011|111 */ {0x7ffffdf, 27}, -- /* (205) |11111111|11111111|11111001|01 */ {0x3ffffe5, 26}, -- /* (206) |11111111|11111111|11110001 */ {0xfffff1, 24}, -- /* (207) |11111111|11111111|11110110|1 */ {0x1ffffed, 25}, -- /* (208) |11111111|11111110|010 */ {0x7fff2, 19}, -- /* (209) |11111111|11111111|00011 */ {0x1fffe3, 21}, -- /* (210) |11111111|11111111|11111001|10 */ {0x3ffffe6, 26}, -- /* (211) |11111111|11111111|11111100|000 */ {0x7ffffe0, 27}, -- /* (212) |11111111|11111111|11111100|001 */ {0x7ffffe1, 27}, -- /* (213) |11111111|11111111|11111001|11 */ {0x3ffffe7, 26}, -- /* (214) |11111111|11111111|11111100|010 */ {0x7ffffe2, 27}, -- /* (215) |11111111|11111111|11110010 */ {0xfffff2, 24}, -- /* (216) |11111111|11111111|00100 */ {0x1fffe4, 21}, -- /* (217) |11111111|11111111|00101 */ {0x1fffe5, 21}, -- /* (218) |11111111|11111111|11111010|00 */ {0x3ffffe8, 26}, -- /* (219) |11111111|11111111|11111010|01 */ {0x3ffffe9, 26}, -- /* (220) |11111111|11111111|11111111|1101 */ {0xffffffd, 28}, -- /* (221) |11111111|11111111|11111100|011 */ {0x7ffffe3, 27}, -- /* (222) |11111111|11111111|11111100|100 */ {0x7ffffe4, 27}, -- /* (223) |11111111|11111111|11111100|101 */ {0x7ffffe5, 27}, -- /* (224) |11111111|11111110|1100 */ {0xfffec, 20}, -- /* (225) |11111111|11111111|11110011 */ {0xfffff3, 24}, -- /* (226) |11111111|11111110|1101 */ {0xfffed, 20}, -- /* (227) |11111111|11111111|00110 */ {0x1fffe6, 21}, -- /* (228) |11111111|11111111|101001 */ {0x3fffe9, 22}, -- /* (229) |11111111|11111111|00111 */ {0x1fffe7, 21}, -- /* (230) |11111111|11111111|01000 */ {0x1fffe8, 21}, -- /* (231) |11111111|11111111|1110011 */ {0x7ffff3, 23}, -- /* (232) |11111111|11111111|101010 */ {0x3fffea, 22}, -- /* (233) |11111111|11111111|101011 */ {0x3fffeb, 22}, -- /* (234) |11111111|11111111|11110111|0 */ {0x1ffffee, 25}, -- /* (235) |11111111|11111111|11110111|1 */ {0x1ffffef, 25}, -- /* (236) |11111111|11111111|11110100 */ {0xfffff4, 24}, -- /* (237) |11111111|11111111|11110101 */ {0xfffff5, 24}, -- /* (238) |11111111|11111111|11111010|10 */ {0x3ffffea, 26}, -- /* (239) |11111111|11111111|1110100 */ {0x7ffff4, 23}, -- /* (240) |11111111|11111111|11111010|11 */ {0x3ffffeb, 26}, -- /* (241) |11111111|11111111|11111100|110 */ {0x7ffffe6, 27}, -- /* (242) |11111111|11111111|11111011|00 */ {0x3ffffec, 26}, -- /* (243) |11111111|11111111|11111011|01 */ {0x3ffffed, 26}, -- /* (244) |11111111|11111111|11111100|111 */ {0x7ffffe7, 27}, -- /* (245) |11111111|11111111|11111101|000 */ {0x7ffffe8, 27}, -- /* (246) |11111111|11111111|11111101|001 */ {0x7ffffe9, 27}, -- /* (247) |11111111|11111111|11111101|010 */ {0x7ffffea, 27}, -- /* (248) |11111111|11111111|11111101|011 */ {0x7ffffeb, 27}, -- /* (249) |11111111|11111111|11111111|1110 */ {0xffffffe, 28}, -- /* (250) |11111111|11111111|11111101|100 */ {0x7ffffec, 27}, -- /* (251) |11111111|11111111|11111101|101 */ {0x7ffffed, 27}, -- /* (252) |11111111|11111111|11111101|110 */ {0x7ffffee, 27}, -- /* (253) |11111111|11111111|11111101|111 */ {0x7ffffef, 27}, -- /* (254) |11111111|11111111|11111110|000 */ {0x7fffff0, 27}, -- /* (255) |11111111|11111111|11111011|10 */ {0x3ffffee, 26}, -- /*EOS (256) |11111111|11111111|11111111|111111 */ {0x3fffffff, 30} -- }; -- -- static final int[][] LCCODES = new int[CODES.length][]; -- static final char EOS = 256; -- -- // Huffman decode tree stored in a flattened char array for good -- // locality of reference. -- static final char[] tree; -- static final char[] rowsym; -- static final byte[] rowbits; -- -- // Build the Huffman lookup tree and LC TABLE -- static -- { -- System.arraycopy(CODES, 0, LCCODES, 0, CODES.length); -- for (int i = 'A'; i <= 'Z'; i++) -- { -- LCCODES[i] = LCCODES['a' + i - 'A']; -- } -- -- int r = 0; -- for (int i = 0; i < CODES.length; i++) -- { -- r += (CODES[i][1] + 7) / 8; -- } -- tree = new char[r * 256]; -- rowsym = new char[r]; -- rowbits = new byte[r]; -- -- r = 0; -- for (int sym = 0; sym < CODES.length; sym++) -- { -- int code = CODES[sym][0]; -- int len = CODES[sym][1]; -- -- int current = 0; -- -- while (len > 8) -- { -- len -= 8; -- int i = ((code >>> len) & 0xFF); -- -- int t = current * 256 + i; -- current = tree[t]; -- if (current == 0) -- { -- tree[t] = (char)++r; -- current = r; -- } -- } -- -- int terminal = ++r; -- rowsym[r] = (char)sym; -- int b = len & 0x07; -- int terminalBits = b == 0 ? 8 : b; -- -- rowbits[r] = (byte)terminalBits; -- int shift = 8 - len; -- int start = current * 256 + ((code << shift) & 0xFF); -- int end = start + (1 << shift); -- for (int i = start; i < end; i++) -- { -- tree[i] = (char)terminal; -- } -- } -- } -- -- public static String decode(ByteBuffer buffer) throws HpackException.CompressionException -- { -- return decode(buffer, buffer.remaining()); -- } -- -- public static String decode(ByteBuffer buffer, int length) throws HpackException.CompressionException -- { -- Utf8StringBuilder utf8 = new Utf8StringBuilder(length * 2); -- int node = 0; -- int current = 0; -- int bits = 0; -- -- for (int i = 0; i < length; i++) -- { -- int b = buffer.get() & 0xFF; -- current = (current << 8) | b; -- bits += 8; -- while (bits >= 8) -- { -- int c = (current >>> (bits - 8)) & 0xFF; -- node = tree[node * 256 + c]; -- if (rowbits[node] != 0) -- { -- if (rowsym[node] == EOS) -- throw new HpackException.CompressionException("EOS in content"); -- -- // terminal node -- utf8.append((byte)(0xFF & rowsym[node])); -- bits -= rowbits[node]; -- node = 0; -- } -- else -- { -- // non-terminal node -- bits -= 8; -- } -- } -- } -- -- while (bits > 0) -- { -- int c = (current << (8 - bits)) & 0xFF; -- int lastNode = node; -- node = tree[node * 256 + c]; -- -- if (rowbits[node] == 0 || rowbits[node] > bits) -- { -- int requiredPadding = 0; -- for (int i = 0; i < bits; i++) -- { -- requiredPadding = (requiredPadding << 1) | 1; -- } -- -- if ((c >> (8 - bits)) != requiredPadding) -- throw new HpackException.CompressionException("Incorrect padding"); -- -- node = lastNode; -- break; -- } -- -- utf8.append((byte)(0xFF & rowsym[node])); -- bits -= rowbits[node]; -- node = 0; -- } -- -- if (node != 0) -- throw new HpackException.CompressionException("Bad termination"); -- -- return utf8.toString(); -- } -- -- public static int octetsNeeded(String s) -- { -- return octetsNeeded(CODES, s); -- } -- -- public static int octetsNeeded(byte[] b) -- { -- return octetsNeeded(CODES, b); -- } -- -- public static void encode(ByteBuffer buffer, String s) -- { -- encode(CODES, buffer, s); -- } -- -- public static void encode(ByteBuffer buffer, byte[] b) -- { -- encode(CODES, buffer, b); -- } -- -- public static int octetsNeededLC(String s) -- { -- return octetsNeeded(LCCODES, s); -- } -- -- public static void encodeLC(ByteBuffer buffer, String s) -- { -- encode(LCCODES, buffer, s); -- } -- -- private static int octetsNeeded(final int[][] table, String s) -- { -- int needed = 0; -- int len = s.length(); -- for (int i = 0; i < len; i++) -- { -- char c = s.charAt(i); -- if (c >= 128 || c < ' ') -- return -1; -- needed += table[c][1]; -- } -- -- return (needed + 7) / 8; -- } -- -- private static int octetsNeeded(final int[][] table, byte[] b) -- { -- int needed = 0; -- int len = b.length; -- for (int i = 0; i < len; i++) -- { -- int c = 0xFF & b[i]; -- needed += table[c][1]; -- } -- return (needed + 7) / 8; -- } -- -- /** -- * @param table The table to encode by -- * @param buffer The buffer to encode to -- * @param s The string to encode -- */ -- private static void encode(final int[][] table, ByteBuffer buffer, String s) -- { -- long current = 0; -- int n = 0; -- int len = s.length(); -- for (int i = 0; i < len; i++) -- { -- char c = s.charAt(i); -- if (c >= 128 || c < ' ') -- throw new IllegalArgumentException(); -- int code = table[c][0]; -- int bits = table[c][1]; -- -- current <<= bits; -- current |= code; -- n += bits; -- -- while (n >= 8) -- { -- n -= 8; -- buffer.put((byte)(current >> n)); -- } -- } -- -- if (n > 0) -- { -- current <<= (8 - n); -- current |= (0xFF >>> n); -- buffer.put((byte)(current)); -- } -- } -- -- private static void encode(final int[][] table, ByteBuffer buffer, byte[] b) -- { -- long current = 0; -- int n = 0; -- -- int len = b.length; -- for (int i = 0; i < len; i++) -- { -- int c = 0xFF & b[i]; -- int code = table[c][0]; -- int bits = table[c][1]; -- -- current <<= bits; -- current |= code; -- n += bits; -- -- while (n >= 8) -- { -- n -= 8; -- buffer.put((byte)(current >> n)); -- } -- } -- -- if (n > 0) -- { -- current <<= (8 - n); -- current |= (0xFF >>> n); -- buffer.put((byte)(current)); -- } -- } --} -diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java -index df45309..9ed7253 100644 ---- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java -+++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java -@@ -29,7 +29,7 @@ import org.eclipse.jetty.http2.hpack.HpackException.SessionException; - - public class MetaDataBuilder - { -- private final int _maxSize; -+ private int _maxSize; - private int _size; - private Integer _status; - private String _method; -@@ -60,6 +60,11 @@ public class MetaDataBuilder - return _maxSize; - } - -+ public void setMaxSize(int maxSize) -+ { -+ _maxSize = maxSize; -+ } -+ - /** - * Get the size. - * -@@ -70,17 +75,18 @@ public class MetaDataBuilder - return _size; - } - -- public void emit(HttpField field) throws HpackException.SessionException -+ public void emit(HttpField field) throws SessionException - { - HttpHeader header = field.getHeader(); - String name = field.getName(); -- if (name == null || name.length() == 0) -- throw new HpackException.SessionException("Header size 0"); -+ if (name == null || name.isEmpty()) -+ throw new SessionException("Header size 0"); - String value = field.getValue(); - int fieldSize = name.length() + (value == null ? 0 : value.length()); - _size += fieldSize + 32; -- if (_size > _maxSize) -- throw new HpackException.SessionException("Header size %d > %d", _size, _maxSize); -+ int maxSize = getMaxSize(); -+ if (maxSize > 0 && _size > maxSize) -+ throw new SessionException("Header size %d > %d", _size, maxSize); - - if (field instanceof StaticTableHttpField) - { -@@ -89,7 +95,7 @@ public class MetaDataBuilder - { - case C_STATUS: - if (checkPseudoHeader(header, _status)) -- _status = (Integer)staticField.getStaticValue(); -+ _status = staticField.getIntValue(); - _response = true; - break; - -@@ -157,7 +163,7 @@ public class MetaDataBuilder - case C_PATH: - if (checkPseudoHeader(header, _path)) - { -- if (value != null && value.length() > 0) -+ if (value != null && !value.isEmpty()) - _path = value; - else - streamException("No Path"); -@@ -201,7 +207,7 @@ public class MetaDataBuilder - } - } - -- protected void streamException(String messageFormat, Object... args) -+ public void streamException(String messageFormat, Object... args) - { - HpackException.StreamException stream = new HpackException.StreamException(messageFormat, args); - if (_streamException == null) -@@ -267,23 +273,7 @@ public class MetaDataBuilder - _authority = null; - _path = null; - _size = 0; -- _contentLength = Long.MIN_VALUE; -+ _contentLength = -1; - } - } -- -- /** -- * Check that the max size will not be exceeded. -- * -- * @param length the length -- * @param huffman the huffman name -- * @throws SessionException in case of size errors -- */ -- public void checkSize(int length, boolean huffman) throws SessionException -- { -- // Apply a huffman fudge factor -- if (huffman) -- length = (length * 4) / 3; -- if ((_size + length) > _maxSize) -- throw new HpackException.SessionException("Header too large %d > %d", _size + length, _maxSize); -- } - } -diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/NBitInteger.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/NBitInteger.java -deleted file mode 100644 -index bab61bb..0000000 ---- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/NBitInteger.java -+++ /dev/null -@@ -1,151 +0,0 @@ --// --// ======================================================================== --// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. --// ------------------------------------------------------------------------ --// All rights reserved. This program and the accompanying materials --// are made available under the terms of the Eclipse Public License v1.0 --// and Apache License v2.0 which accompanies this distribution. --// --// The Eclipse Public License is available at --// http://www.eclipse.org/legal/epl-v10.html --// --// The Apache License v2.0 is available at --// http://www.opensource.org/licenses/apache2.0.php --// --// You may elect to redistribute this code under either of these licenses. --// ======================================================================== --// -- --package org.eclipse.jetty.http2.hpack; -- --import java.nio.ByteBuffer; -- --public class NBitInteger --{ -- public static int octectsNeeded(int n, int i) -- { -- if (n == 8) -- { -- int nbits = 0xFF; -- i = i - nbits; -- if (i < 0) -- return 1; -- if (i == 0) -- return 2; -- int lz = Integer.numberOfLeadingZeros(i); -- int log = 32 - lz; -- return 1 + (log + 6) / 7; -- } -- -- int nbits = 0xFF >>> (8 - n); -- i = i - nbits; -- if (i < 0) -- return 0; -- if (i == 0) -- return 1; -- int lz = Integer.numberOfLeadingZeros(i); -- int log = 32 - lz; -- return (log + 6) / 7; -- } -- -- public static void encode(ByteBuffer buf, int n, int i) -- { -- if (n == 8) -- { -- if (i < 0xFF) -- { -- buf.put((byte)i); -- } -- else -- { -- buf.put((byte)0xFF); -- -- int length = i - 0xFF; -- while (true) -- { -- if ((length & ~0x7F) == 0) -- { -- buf.put((byte)length); -- return; -- } -- else -- { -- buf.put((byte)((length & 0x7F) | 0x80)); -- length >>>= 7; -- } -- } -- } -- } -- else -- { -- int p = buf.position() - 1; -- int bits = 0xFF >>> (8 - n); -- -- if (i < bits) -- { -- buf.put(p, (byte)((buf.get(p) & ~bits) | i)); -- } -- else -- { -- buf.put(p, (byte)(buf.get(p) | bits)); -- -- int length = i - bits; -- while (true) -- { -- if ((length & ~0x7F) == 0) -- { -- buf.put((byte)length); -- return; -- } -- else -- { -- buf.put((byte)((length & 0x7F) | 0x80)); -- length >>>= 7; -- } -- } -- } -- } -- } -- -- public static int decode(ByteBuffer buffer, int n) -- { -- if (n == 8) -- { -- int nbits = 0xFF; -- -- int i = buffer.get() & 0xff; -- -- if (i == nbits) -- { -- int m = 1; -- int b; -- do -- { -- b = 0xff & buffer.get(); -- i = i + (b & 127) * m; -- m = m * 128; -- } -- while ((b & 128) == 128); -- } -- return i; -- } -- -- int nbits = 0xFF >>> (8 - n); -- -- int i = buffer.get(buffer.position() - 1) & nbits; -- -- if (i == nbits) -- { -- int m = 1; -- int b; -- do -- { -- b = 0xff & buffer.get(); -- i = i + (b & 127) * m; -- m = m * 128; -- } -- while ((b & 128) == 128); -- } -- return i; -- } --} -diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackContextTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackContextTest.java -index ed0d914..a767a51 100644 ---- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackContextTest.java -+++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackContextTest.java -@@ -21,6 +21,9 @@ package org.eclipse.jetty.http2.hpack; - import java.nio.ByteBuffer; - - import org.eclipse.jetty.http.HttpField; -+import org.eclipse.jetty.http.compression.EncodingException; -+import org.eclipse.jetty.http.compression.HuffmanDecoder; -+import org.eclipse.jetty.http.compression.NBitIntegerDecoder; - import org.eclipse.jetty.http2.hpack.HpackContext.Entry; - import org.hamcrest.Matchers; - import org.junit.jupiter.api.Test; -@@ -37,6 +40,32 @@ import static org.junit.jupiter.api.Assertions.assertTrue; - */ - public class HpackContextTest - { -+ public static String decode(ByteBuffer buffer, int length) throws EncodingException -+ { -+ HuffmanDecoder huffmanDecoder = new HuffmanDecoder(); -+ huffmanDecoder.setLength(length); -+ String decoded = huffmanDecoder.decode(buffer); -+ if (decoded == null) -+ throw new EncodingException("invalid string encoding"); -+ -+ huffmanDecoder.reset(); -+ return decoded; -+ } -+ -+ public static int decodeInt(ByteBuffer buffer, int prefix) throws EncodingException -+ { -+ // This is a fix for HPACK as it already takes the first byte of the encoded integer. -+ if (prefix != 8) -+ buffer.position(buffer.position() - 1); -+ -+ NBitIntegerDecoder decoder = new NBitIntegerDecoder(); -+ decoder.setPrefix(prefix); -+ int decodedInt = decoder.decodeInt(buffer); -+ if (decodedInt < 0) -+ throw new EncodingException("invalid integer encoding"); -+ decoder.reset(); -+ return decodedInt; -+ } - - @Test - public void testStaticName() -@@ -428,10 +457,10 @@ public class HpackContextTest - int huff = 0xff & buffer.get(); - assertTrue((0x80 & huff) == 0x80); - -- int len = NBitInteger.decode(buffer, 7); -+ int len = decodeInt(buffer, 7); - - assertEquals(len, buffer.remaining()); -- String value = Huffman.decode(buffer); -+ String value = decode(buffer, buffer.remaining()); - - assertEquals(entry.getHttpField().getValue(), value); - } -diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java -index 4cc50c5..4d1c347 100644 ---- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java -+++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java -@@ -62,7 +62,7 @@ public class HpackDecoderTest - @Test - public void testDecodeD3() throws Exception - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - // First request - String encoded = "828684410f7777772e6578616d706c652e636f6d"; -@@ -110,7 +110,7 @@ public class HpackDecoderTest - @Test - public void testDecodeD4() throws Exception - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - // First request - String encoded = "828684418cf1e3c2e5f23a6ba0ab90f4ff"; -@@ -145,7 +145,7 @@ public class HpackDecoderTest - { - String value = "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; - -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - String encoded = "8682418cF1E3C2E5F23a6bA0Ab90F4Ff841f0822426173696320515778685a475270626a70766347567549484e6c633246745a513d3d"; - byte[] bytes = TypeUtil.fromHexString(encoded); - byte[] array = new byte[bytes.length + 1]; -@@ -167,7 +167,7 @@ public class HpackDecoderTest - @Test - public void testDecodeHuffmanWithArrayOffset() throws Exception - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "8286418cf1e3c2e5f23a6ba0ab90f4ff84"; - byte[] bytes = TypeUtil.fromHexString(encoded); -@@ -191,7 +191,7 @@ public class HpackDecoderTest - String encoded = "886196C361Be940b6a65B6850400B8A00571972e080a62D1Bf5f87497cA589D34d1f9a0f0d0234327690Aa69D29aFcA954D3A5358980Ae112e0f7c880aE152A9A74a6bF3"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - MetaData.Response response = (MetaData.Response)decoder.decode(buffer); - - assertThat(response.getStatus(), is(200)); -@@ -209,7 +209,7 @@ public class HpackDecoderTest - { - String encoded = "203f136687A0E41d139d090760881c6490B2Cd39Ba7f"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - MetaData metaData = decoder.decode(buffer); - assertThat(metaData.getFields().get(HttpHeader.HOST), is("localhost0")); - assertThat(metaData.getFields().get(HttpHeader.COOKIE), is("abcdefghij")); -@@ -231,7 +231,7 @@ public class HpackDecoderTest - - String encoded = "203f136687A0E41d139d090760881c6490B2Cd39Ba7f20"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - try - { - decoder.decode(buffer); -@@ -249,7 +249,8 @@ public class HpackDecoderTest - String encoded = "3f610f17FfEc02Df3990A190A0D4Ee5b3d2940Ec98Aa4a62D127D29e273a0aA20dEcAa190a503b262d8a2671D4A2672a927aA874988a2471D05510750c951139EdA2452a3a548cAa1aA90bE4B228342864A9E0D450A5474a92992a1aA513395448E3A0Aa17B96cFe3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f14E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F353F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F54f"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - -- HpackDecoder decoder = new HpackDecoder(128, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); -+ decoder.setMaxTableCapacity(128); - MetaData metaData = decoder.decode(buffer); - - assertThat(decoder.getHpackContext().getDynamicTableSize(), is(0)); -@@ -262,7 +263,8 @@ public class HpackDecoderTest - String encoded = "BE"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - -- HpackDecoder decoder = new HpackDecoder(128, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); -+ decoder.setMaxTableCapacity(128); - - try - { -@@ -447,7 +449,7 @@ public class HpackDecoderTest - @Test - public void testHuffmanEncodedStandard() throws Exception - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "82868441" + "83" + "49509F"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); -@@ -465,68 +467,68 @@ public class HpackDecoderTest - @Test - public void testHuffmanEncodedExtraPadding() - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "82868441" + "84" + "49509FFF"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer)); -- assertThat(ex.getMessage(), Matchers.containsString("Bad termination")); -+ assertThat(ex.getMessage(), Matchers.containsString("bad_termination")); - } - - /* 5.2.2: Sends a Huffman-encoded string literal representation padded by zero */ - @Test - public void testHuffmanEncodedZeroPadding() - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "82868441" + "83" + "495090"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - - CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer)); -- assertThat(ex.getMessage(), Matchers.containsString("Incorrect padding")); -+ assertThat(ex.getMessage(), Matchers.containsString("incorrect_padding")); - } - - /* 5.2.3: Sends a Huffman-encoded string literal representation containing the EOS symbol */ - @Test - public void testHuffmanEncodedWithEOS() - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "82868441" + "87" + "497FFFFFFF427F"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - - CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer)); -- assertThat(ex.getMessage(), Matchers.containsString("EOS in content")); -+ assertThat(ex.getMessage(), Matchers.containsString("eos_in_content")); - } - - @Test - public void testHuffmanEncodedOneIncompleteOctet() - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "82868441" + "81" + "FE"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - - CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer)); -- assertThat(ex.getMessage(), Matchers.containsString("Bad termination")); -+ assertThat(ex.getMessage(), Matchers.containsString("bad_termination")); - } - - @Test - public void testHuffmanEncodedTwoIncompleteOctet() - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "82868441" + "82" + "FFFE"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - - CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer)); -- assertThat(ex.getMessage(), Matchers.containsString("Bad termination")); -+ assertThat(ex.getMessage(), Matchers.containsString("bad_termination")); - } - - @Test - public void testZeroLengthName() - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "00000130"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); -@@ -537,7 +539,7 @@ public class HpackDecoderTest - @Test - public void testZeroLengthValue() throws Exception - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "00016800"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); -@@ -549,7 +551,7 @@ public class HpackDecoderTest - @Test - public void testUpperCaseName() - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "0001480130"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); -@@ -560,7 +562,7 @@ public class HpackDecoderTest - @Test - public void testWhiteSpaceName() - { -- HpackDecoder decoder = new HpackDecoder(4096, 8192); -+ HpackDecoder decoder = new HpackDecoder(8192); - - String encoded = "0001200130"; - ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); -diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java -index a46f297..d99a20d 100644 ---- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java -+++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java -@@ -38,7 +38,7 @@ public class HpackEncoderTest - @Test - public void testUnknownFieldsContextManagement() throws Exception - { -- HpackEncoder encoder = new HpackEncoder(38 * 5); -+ HpackEncoder encoder = newHpackEncoder(38 * 5); - HttpFields fields = new HttpFields(); - - HttpField[] field = -@@ -149,8 +149,9 @@ public class HpackEncoderTest - @Test - public void testLargeFieldsNotIndexed() - { -- HpackEncoder encoder = new HpackEncoder(38 * 5); -+ HpackEncoder encoder = newHpackEncoder(38 * 5); - HpackContext ctx = encoder.getHpackContext(); -+ ctx.resize(encoder.getMaxTableCapacity()); - - ByteBuffer buffer = BufferUtil.allocate(4096); - -@@ -175,8 +176,9 @@ public class HpackEncoderTest - @Test - public void testIndexContentLength() - { -- HpackEncoder encoder = new HpackEncoder(38 * 5); -+ HpackEncoder encoder = newHpackEncoder(38 * 5); - HpackContext ctx = encoder.getHpackContext(); -+ ctx.resize(encoder.getMaxTableCapacity()); - - ByteBuffer buffer = BufferUtil.allocate(4096); - -@@ -197,7 +199,7 @@ public class HpackEncoderTest - @Test - public void testNeverIndexSetCookie() throws Exception - { -- HpackEncoder encoder = new HpackEncoder(38 * 5); -+ HpackEncoder encoder = newHpackEncoder(38 * 5); - ByteBuffer buffer = BufferUtil.allocate(4096); - - HttpFields fields = new HttpFields(); -@@ -231,20 +233,20 @@ public class HpackEncoderTest - { - HttpFields fields = new HttpFields(); - -- HpackEncoder encoder = new HpackEncoder(128); -+ HpackEncoder encoder = newHpackEncoder(128); - ByteBuffer buffer0 = BufferUtil.allocate(4096); - int pos = BufferUtil.flipToFill(buffer0); - encoder.encode(buffer0, new MetaData(HttpVersion.HTTP_2, fields)); - BufferUtil.flipToFlush(buffer0, pos); - -- encoder = new HpackEncoder(128); -+ encoder = newHpackEncoder(128); - fields.add(new HttpField("user-agent", "jetty/test")); - ByteBuffer buffer1 = BufferUtil.allocate(4096); - pos = BufferUtil.flipToFill(buffer1); - encoder.encode(buffer1, new MetaData(HttpVersion.HTTP_2, fields)); - BufferUtil.flipToFlush(buffer1, pos); - -- encoder = new HpackEncoder(128); -+ encoder = newHpackEncoder(128); - encoder.setValidateEncoding(false); - fields.add(new HttpField(":path", - "This is a very large field, whose size is larger than the dynamic table so it should not be indexed as it will not fit in the table ever!" + -@@ -256,7 +258,7 @@ public class HpackEncoderTest - encoder.encode(buffer2, new MetaData(HttpVersion.HTTP_2, fields)); - BufferUtil.flipToFlush(buffer2, pos); - -- encoder = new HpackEncoder(128); -+ encoder = newHpackEncoder(128); - encoder.setValidateEncoding(false); - fields.add(new HttpField("host", "somehost")); - ByteBuffer buffer = BufferUtil.allocate(4096); -@@ -297,12 +299,12 @@ public class HpackEncoderTest - fields.add("host", "localhost0"); - fields.add("cookie", "abcdefghij"); - -- HpackEncoder encoder = new HpackEncoder(4096); -+ HpackEncoder encoder = newHpackEncoder(4096); - - ByteBuffer buffer = BufferUtil.allocate(4096); - int pos = BufferUtil.flipToFill(buffer); - encoder.encodeMaxDynamicTableSize(buffer, 0); -- encoder.setRemoteMaxDynamicTableSize(50); -+ encoder.setTableCapacity(50); - encoder.encode(buffer, new MetaData(HttpVersion.HTTP_2, fields)); - BufferUtil.flipToFlush(buffer, pos); - -@@ -311,4 +313,12 @@ public class HpackEncoderTest - assertThat(context.getMaxDynamicTableSize(), Matchers.is(50)); - assertThat(context.size(), Matchers.is(1)); - } -+ -+ private static HpackEncoder newHpackEncoder(int tableCapacity) -+ { -+ HpackEncoder encoder = new HpackEncoder(); -+ encoder.setMaxTableCapacity(tableCapacity); -+ encoder.setTableCapacity(tableCapacity); -+ return encoder; -+ } - } -diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java -index e31f5bf..dd51b4b 100644 ---- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java -+++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java -@@ -37,7 +37,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; - - public class HpackPerfTest - { -- int _maxDynamicTableSize = 4 * 1024; -+ int _tableCapacity = 4 * 1024; - int _unencodedSize; - int _encodedSize; - -@@ -51,7 +51,7 @@ public class HpackPerfTest - @AfterEach - public void after() - { -- System.err.printf("dynamictable=%d unencoded=%d encoded=%d p=%3.1f%%%n", _maxDynamicTableSize, _unencodedSize, _encodedSize, 100.0 * _encodedSize / _unencodedSize); -+ System.err.printf("dynamictable=%d unencoded=%d encoded=%d p=%3.1f%%%n", _tableCapacity, _unencodedSize, _encodedSize, 100.0 * _encodedSize / _unencodedSize); - } - - @Test -@@ -68,11 +68,14 @@ public class HpackPerfTest - assertNotNull(files); - - // Parse JSON -- Map[] stories = new Map[files.length]; -+ @SuppressWarnings("unchecked") -+ MapSets the limit for the encoder HPACK dynamic table capacity.
-+ *Setting this value to {@code 0} disables the use of the dynamic table.
-+ * -+ * @param maxEncoderTableCapacity The HPACK encoder dynamic table maximum capacity -+ */ -+ public void setMaxEncoderTableCapacity(int maxEncoderTableCapacity) -+ { -+ this.maxEncoderTableCapacity = maxEncoderTableCapacity; -+ } -+ -+ @ManagedAttribute("The HPACK decoder dynamic table maximum capacity") -+ public int getMaxDecoderTableCapacity() -+ { -+ return maxDecoderTableCapacity; -+ } -+ -+ public void setMaxDecoderTableCapacity(int maxDecoderTableCapacity) -+ { -+ this.maxDecoderTableCapacity = maxDecoderTableCapacity; - } - - @ManagedAttribute("The initial size of session's flow control receive window") -@@ -159,15 +191,28 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne - this.streamIdleTimeout = streamIdleTimeout; - } - -+ @Deprecated - @ManagedAttribute("The max frame length in bytes") - public int getMaxFrameLength() - { -- return maxFrameLength; -+ return getMaxFrameSize(); - } - -+ @Deprecated - public void setMaxFrameLength(int maxFrameLength) - { -- this.maxFrameLength = maxFrameLength; -+ setMaxFrameSize(maxFrameLength); -+ } -+ -+ @ManagedAttribute("The max frame size in bytes") -+ public int getMaxFrameSize() -+ { -+ return maxFrameSize; -+ } -+ -+ public void setMaxFrameSize(int maxFrameSize) -+ { -+ this.maxFrameSize = maxFrameSize; - } - - @ManagedAttribute("The max number of keys in all SETTINGS frames") -@@ -267,37 +312,47 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne - { - ServerSessionListener listener = newSessionListener(connector, endPoint); - -- Generator generator = new Generator(connector.getByteBufferPool(), getMaxDynamicTableSize(), getMaxHeaderBlockFragment()); -+ Generator generator = new Generator(connector.getByteBufferPool(), getMaxHeaderBlockFragment()); - FlowControlStrategy flowControl = getFlowControlStrategyFactory().newFlowControlStrategy(); -- HTTP2ServerSession session = new HTTP2ServerSession(connector.getScheduler(), endPoint, generator, listener, flowControl); -+ -+ ServerParser parser = newServerParser(connector, getRateControlFactory().newRateControl(endPoint)); -+ parser.setMaxFrameSize(getMaxFrameSize()); -+ parser.setMaxSettingsKeys(getMaxSettingsKeys()); -+ -+ HTTP2ServerSession session = new HTTP2ServerSession(connector.getScheduler(), endPoint, parser, generator, listener, flowControl); - session.setMaxLocalStreams(getMaxConcurrentStreams()); - session.setMaxRemoteStreams(getMaxConcurrentStreams()); -+ session.setMaxEncoderTableCapacity(getMaxEncoderTableCapacity()); - // For a single stream in a connection, there will be a race between - // the stream idle timeout and the connection idle timeout. However, - // the typical case is that the connection will be busier and the - // stream idle timeout will expire earlier than the connection's. - long streamIdleTimeout = getStreamIdleTimeout(); -- if (streamIdleTimeout <= 0) -+ if (streamIdleTimeout == 0) - streamIdleTimeout = endPoint.getIdleTimeout(); - session.setStreamIdleTimeout(streamIdleTimeout); - session.setInitialSessionRecvWindow(getInitialSessionRecvWindow()); - session.setWriteThreshold(getHttpConfiguration().getOutputBufferSize()); - -- ServerParser parser = newServerParser(connector, session, getRateControlFactory().newRateControl(endPoint)); -- parser.setMaxFrameLength(getMaxFrameLength()); -- parser.setMaxSettingsKeys(getMaxSettingsKeys()); -- - HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(), -- endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener); -+ endPoint, httpConfiguration, session, getInputBufferSize(), listener); - connection.addListener(sessionContainer); -+ parser.init(connection.wrapParserListener(session)); -+ - return configure(connection, connector, endPoint); - } - - protected abstract ServerSessionListener newSessionListener(Connector connector, EndPoint endPoint); - -+ @Deprecated - protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener, RateControl rateControl) - { -- return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize(), rateControl); -+ return newServerParser(connector, rateControl); -+ } -+ -+ protected ServerParser newServerParser(Connector connector, RateControl rateControl) -+ { -+ return new ServerParser(connector.getByteBufferPool(), getHttpConfiguration().getRequestHeaderSize(), rateControl); - } - - @ManagedObject("The container of HTTP/2 sessions") -diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java -index 3974ee6..11c68d4 100644 ---- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java -+++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java -@@ -89,9 +89,15 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection - private final HttpConfiguration httpConfig; - private boolean recycleHttpChannels = true; - -+ @Deprecated - public HTTP2ServerConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, HttpConfiguration httpConfig, ServerParser parser, ISession session, int inputBufferSize, ServerSessionListener listener) - { -- super(byteBufferPool, executor, endPoint, parser, session, inputBufferSize); -+ this(byteBufferPool, executor, endPoint, httpConfig, session, inputBufferSize, listener); -+ } -+ -+ public HTTP2ServerConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, HttpConfiguration httpConfig, ISession session, int inputBufferSize, ServerSessionListener listener) -+ { -+ super(byteBufferPool, executor, endPoint, session, inputBufferSize); - this.listener = listener; - this.httpConfig = httpConfig; - } -diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerSession.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerSession.java -index c0f24d6..8e405b9 100644 ---- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerSession.java -+++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerSession.java -@@ -37,6 +37,7 @@ import org.eclipse.jetty.http2.frames.PushPromiseFrame; - import org.eclipse.jetty.http2.frames.SettingsFrame; - import org.eclipse.jetty.http2.frames.WindowUpdateFrame; - import org.eclipse.jetty.http2.generator.Generator; -+import org.eclipse.jetty.http2.parser.Parser; - import org.eclipse.jetty.http2.parser.ServerParser; - import org.eclipse.jetty.io.EndPoint; - import org.eclipse.jetty.util.Callback; -@@ -50,9 +51,16 @@ public class HTTP2ServerSession extends HTTP2Session implements ServerParser.Lis - - private final ServerSessionListener listener; - -+ @Deprecated - public HTTP2ServerSession(Scheduler scheduler, EndPoint endPoint, Generator generator, ServerSessionListener listener, FlowControlStrategy flowControl) - { -- super(scheduler, endPoint, generator, listener, flowControl, 2); -+ this(scheduler, endPoint, null, generator, listener, flowControl); -+ throw new UnsupportedOperationException(); -+ } -+ -+ public HTTP2ServerSession(Scheduler scheduler, EndPoint endPoint, Parser parser, Generator generator, ServerSessionListener listener, FlowControlStrategy flowControl) -+ { -+ super(scheduler, endPoint, parser, generator, listener, flowControl, 2); - this.listener = listener; - } - -diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java -index 04b8a28..41321c0 100644 ---- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java -+++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java -@@ -26,7 +26,6 @@ import java.util.HashMap; - import java.util.concurrent.CountDownLatch; - import java.util.concurrent.TimeUnit; - import java.util.concurrent.atomic.AtomicReference; --import java.util.function.UnaryOperator; - - import org.eclipse.jetty.http.HttpFields; - import org.eclipse.jetty.http.HttpVersion; -@@ -92,7 +91,8 @@ public class CloseTest extends AbstractServerTest - output.write(BufferUtil.toArray(buffer)); - } - -- Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter() -+ Parser parser = new Parser(byteBufferPool, 4096); -+ parser.init(new Parser.Listener.Adapter() - { - @Override - public void onHeaders(HeadersFrame frame) -@@ -109,8 +109,7 @@ public class CloseTest extends AbstractServerTest - throw new RuntimeIOException(x); - } - } -- }, 4096, 8192); -- parser.init(UnaryOperator.identity()); -+ }); - - parseResponse(client, parser); - -@@ -157,7 +156,8 @@ public class CloseTest extends AbstractServerTest - // Don't close the connection; the server should close. - - final CountDownLatch responseLatch = new CountDownLatch(1); -- Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter() -+ Parser parser = new Parser(byteBufferPool, 4096); -+ parser.init(new Parser.Listener.Adapter() - { - @Override - public void onHeaders(HeadersFrame frame) -@@ -166,8 +166,7 @@ public class CloseTest extends AbstractServerTest - // HEADERS, the server is able to send us the response. - responseLatch.countDown(); - } -- }, 4096, 8192); -- parser.init(UnaryOperator.identity()); -+ }); - - parseResponse(client, parser); - -@@ -222,7 +221,8 @@ public class CloseTest extends AbstractServerTest - - final CountDownLatch responseLatch = new CountDownLatch(1); - final CountDownLatch closeLatch = new CountDownLatch(1); -- Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter() -+ Parser parser = new Parser(byteBufferPool, 4096); -+ parser.init(new Parser.Listener.Adapter() - { - @Override - public void onHeaders(HeadersFrame frame) -@@ -235,8 +235,7 @@ public class CloseTest extends AbstractServerTest - { - closeLatch.countDown(); - } -- }, 4096, 8192); -- parser.init(UnaryOperator.identity()); -+ }); - - parseResponse(client, parser); - -diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java -index e4853d7..d1d3e72 100644 ---- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java -+++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java -@@ -30,7 +30,6 @@ import java.util.concurrent.CountDownLatch; - import java.util.concurrent.TimeUnit; - import java.util.concurrent.atomic.AtomicLong; - import java.util.concurrent.atomic.AtomicReference; --import java.util.function.UnaryOperator; - - import org.eclipse.jetty.http.HostPortHttpField; - import org.eclipse.jetty.http.HttpFields; -@@ -152,7 +151,8 @@ public class HTTP2CServerTest extends AbstractServerTest - final AtomicReferenceBuild a string from a sequence of bytes and/or characters.
-+ *Implementations of this interface are optimized for processing a mix of calls to already decoded -+ * character based appends (e.g. {@link #append(char)} and calls to undecoded byte methods (e.g. {@link #append(byte)}. -+ * This is particularly useful for decoding % encoded strings that are mostly already decoded but may contain -+ * escaped byte sequences that are not decoded. The standard {@link CharsetDecoder} API is not well suited for this -+ * use-case.
-+ *Any coding errors in the string will be reported by a {@link CharacterCodingException} thrown -+ * from the {@link #build()} method.
-+ * @see Utf8StringBuilder for UTF-8 decoding with replacement of coding errors and/or fast fail behaviour. -+ * @see CharsetDecoder for decoding arbitrary {@link Charset}s with control over {@link CodingErrorAction}. -+ */ -+public interface CharsetStringBuilder -+{ -+ /** -+ * @param b An encoded byte to append -+ */ -+ void append(byte b); -+ -+ /** -+ * @param c A decoded character to append -+ */ -+ void append(char c); -+ -+ /** -+ * @param bytes Array of encoded bytes to append -+ */ -+ default void append(byte[] bytes) -+ { -+ append(bytes, 0, bytes.length); -+ } -+ -+ /** -+ * @param b Array of encoded bytes -+ * @param offset offset into the array -+ * @param length the number of bytes to append from the array. -+ */ -+ default void append(byte[] b, int offset, int length) -+ { -+ int end = offset + length; -+ for (int i = offset; i < end; i++) -+ append(b[i]); -+ } -+ -+ /** -+ * @param chars sequence of decoded characters -+ * @param offset offset into the array -+ * @param length the number of character to append from the sequence. -+ */ -+ default void append(CharSequence chars, int offset, int length) -+ { -+ int end = offset + length; -+ for (int i = offset; i < end; i++) -+ append(chars.charAt(i)); -+ } -+ -+ /** -+ * @param buf Buffer of encoded bytes to append. The bytes are consumed from the buffer. -+ */ -+ default void append(ByteBuffer buf) -+ { -+ int end = buf.position() + buf.remaining(); -+ while (buf.position() < end) -+ append(buf.get()); -+ } -+ -+ /** -+ *Build the completed string and reset the buffer.
-+ * @return The decoded built string which must be complete in regard to any multibyte sequences. -+ * @throws CharacterCodingException If the bytes cannot be correctly decoded or a multibyte sequence is incomplete. -+ */ -+ String build() throws CharacterCodingException; -+ -+ void reset(); -+ -+ /** -+ * @param charset The charset -+ * @return A {@link CharsetStringBuilder} suitable for the charset. -+ */ -+ static CharsetStringBuilder forCharset(Charset charset) -+ { -+ Objects.requireNonNull(charset); -+ if (charset == StandardCharsets.ISO_8859_1) -+ return new Iso88591StringBuilder(); -+ if (charset == StandardCharsets.US_ASCII) -+ return new UsAsciiStringBuilder(); -+ -+ // Use a CharsetDecoder that defaults to CodingErrorAction#REPORT -+ return new DecoderStringBuilder(charset.newDecoder()); -+ } -+ -+ class Iso88591StringBuilder implements CharsetStringBuilder -+ { -+ private final StringBuilder _builder = new StringBuilder(); -+ -+ @Override -+ public void append(byte b) -+ { -+ _builder.append((char)(0xff & b)); -+ } -+ -+ @Override -+ public void append(char c) -+ { -+ _builder.append(c); -+ } -+ -+ @Override -+ public void append(CharSequence chars, int offset, int length) -+ { -+ _builder.append(chars, offset, offset + length); -+ } -+ -+ @Override -+ public String build() -+ { -+ String s = _builder.toString(); -+ _builder.setLength(0); -+ return s; -+ } -+ -+ @Override -+ public void reset() -+ { -+ _builder.setLength(0); -+ } -+ } -+ -+ class UsAsciiStringBuilder implements CharsetStringBuilder -+ { -+ private final StringBuilder _builder = new StringBuilder(); -+ -+ @Override -+ public void append(byte b) -+ { -+ if (b < 0) -+ throw new IllegalArgumentException(); -+ _builder.append((char)b); -+ } -+ -+ @Override -+ public void append(char c) -+ { -+ _builder.append(c); -+ } -+ -+ @Override -+ public void append(CharSequence chars, int offset, int length) -+ { -+ _builder.append(chars, offset, offset + length); -+ } -+ -+ @Override -+ public String build() -+ { -+ String s = _builder.toString(); -+ _builder.setLength(0); -+ return s; -+ } -+ -+ @Override -+ public void reset() -+ { -+ _builder.setLength(0); -+ } -+ } -+ -+ class DecoderStringBuilder implements CharsetStringBuilder -+ { -+ private final CharsetDecoder _decoder; -+ private final StringBuilder _stringBuilder = new StringBuilder(32); -+ private ByteBuffer _buffer = ByteBuffer.allocate(32); -+ -+ public DecoderStringBuilder(CharsetDecoder charsetDecoder) -+ { -+ _decoder = charsetDecoder; -+ } -+ -+ private void ensureSpace(int needed) -+ { -+ int space = _buffer.remaining(); -+ if (space < needed) -+ { -+ int position = _buffer.position(); -+ _buffer = ByteBuffer.wrap(Arrays.copyOf(_buffer.array(), _buffer.capacity() + needed - space + 32)); -+ _buffer.position(position); -+ } -+ } -+ -+ @Override -+ public void append(byte b) -+ { -+ ensureSpace(1); -+ _buffer.put(b); -+ } -+ -+ @Override -+ public void append(char c) -+ { -+ if (_buffer.position() > 0) -+ { -+ try -+ { -+ // Append any data already in the decoder -+ _buffer.flip(); -+ _stringBuilder.append(_decoder.decode(_buffer)); -+ _buffer.clear(); -+ } -+ catch (CharacterCodingException e) -+ { -+ // This will be thrown only if the decoder is configured to REPORT, -+ // otherwise errors will be ignored or replaced and we will not catch here. -+ throw new RuntimeException(e); -+ } -+ } -+ _stringBuilder.append(c); -+ } -+ -+ @Override -+ public void append(CharSequence chars, int offset, int length) -+ { -+ if (_buffer.position() > 0) -+ { -+ try -+ { -+ // Append any data already in the decoder -+ _buffer.flip(); -+ _stringBuilder.append(_decoder.decode(_buffer)); -+ _buffer.clear(); -+ } -+ catch (CharacterCodingException e) -+ { -+ // This will be thrown only if the decoder is configured to REPORT, -+ // otherwise errors will be ignored or replaced and we will not catch here. -+ throw new RuntimeException(e); -+ } -+ } -+ _stringBuilder.append(chars, offset, offset + length); -+ } -+ -+ @Override -+ public void append(byte[] b, int offset, int length) -+ { -+ ensureSpace(length); -+ _buffer.put(b, offset, length); -+ } -+ -+ @Override -+ public void append(ByteBuffer buf) -+ { -+ ensureSpace(buf.remaining()); -+ _buffer.put(buf); -+ } -+ -+ @Override -+ public String build() throws CharacterCodingException -+ { -+ try -+ { -+ if (_buffer.position() > 0) -+ { -+ _buffer.flip(); -+ CharSequence decoded = _decoder.decode(_buffer); -+ _buffer.clear(); -+ if (_stringBuilder.length() == 0) -+ return decoded.toString(); -+ _stringBuilder.append(decoded); -+ } -+ return _stringBuilder.toString(); -+ } -+ finally -+ { -+ _stringBuilder.setLength(0); -+ } -+ } -+ -+ @Override -+ public void reset() -+ { -+ _stringBuilder.setLength(0); -+ } -+ } -+} -diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java -index 0bdb229..9d46b48 100644 ---- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java -+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java -@@ -107,6 +107,27 @@ public class StringUtil - '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177' - }; - -+ // @checkstyle-disable-check : IllegalTokenTextCheck -+ private static final char[] uppercases = -+ { -+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', -+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', -+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', -+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', -+ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', -+ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', -+ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', -+ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', -+ '\100', '\101', '\102', '\103', '\104', '\105', '\106', '\107', -+ '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', -+ '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', -+ '\130', '\131', '\132', '\133', '\134', '\135', '\136', '\137', -+ '\140', '\101', '\102', '\103', '\104', '\105', '\106', '\107', -+ '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', -+ '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', -+ '\130', '\131', '\132', '\173', '\174', '\175', '\176', '\177' -+ }; -+ - /** - * fast lower case conversion. Only works on ascii (not unicode) - * -@@ -144,6 +165,42 @@ public class StringUtil - return c == null ? s : new String(c); - } - -+ /** -+ * fast upper case conversion. Only works on ascii (not unicode) -+ * -+ * @param s the string to convert -+ * @return a lower case version of s -+ */ -+ public static String asciiToUpperCase(String s) -+ { -+ if (s == null) -+ return null; -+ -+ char[] c = null; -+ int i = s.length(); -+ // look for first conversion -+ while (i-- > 0) -+ { -+ char c1 = s.charAt(i); -+ if (c1 <= 127) -+ { -+ char c2 = uppercases[c1]; -+ if (c1 != c2) -+ { -+ c = s.toCharArray(); -+ c[i] = c2; -+ break; -+ } -+ } -+ } -+ while (i-- > 0) -+ { -+ if (c[i] <= 127) -+ c[i] = uppercases[c[i]]; -+ } -+ return c == null ? s : new String(c); -+ } -+ - /** - * Replace all characters from input string that are known to have - * special meaning in various filesystems. -@@ -453,6 +510,22 @@ public class StringUtil - } - } - -+ /** -+ * Generate a string from another string repeated n times. -+ * -+ * @param s the string to use -+ * @param n the number of times this string should be appended -+ */ -+ public static String stringFrom(String s, int n) -+ { -+ StringBuilder stringBuilder = new StringBuilder(s.length() * n); -+ for (int i = 0; i < n; i++) -+ { -+ stringBuilder.append(s); -+ } -+ return stringBuilder.toString(); -+ } -+ - /** - * Return a non null string. - * diff -Nru jetty9-9.4.50/debian/patches/CVE-2023-36479.patch jetty9-9.4.57/debian/patches/CVE-2023-36479.patch --- jetty9-9.4.50/debian/patches/CVE-2023-36479.patch 2024-04-07 20:26:26.000000000 +0000 +++ jetty9-9.4.57/debian/patches/CVE-2023-36479.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -From: Markus Koschany+ * field-vchar = VCHAR / obs-text + * obs-text = %x80-FF + * VCHAR = %x21-7E + *+ * @param c the character to test. + * @return the original character or the replacement character ' ' or '?', + * the return value is guaranteed to be a valid ISO-8859-1 character. + */ + public static char sanitizeFieldVchar(char c) + { + switch (c) + { + // A recipient of CR, LF, or NUL within a field value MUST either reject the message + // or replace each of those characters with SP before further processing + case '\r': + case '\n': + case 0x00: + return ' '; + + default: + if (isIllegalFieldVchar(c)) + return '?'; + } + return c; + } + + /** + * Checks whether this is an invalid VCHAR based on RFC9110. + * If this not a valid ISO-8859-1 character or a control character + * we say that it is illegal. + * + * @param c the character to test. + * @return true if this is invalid VCHAR. + */ + public static boolean isIllegalFieldVchar(char c) + { + return (c >= 256 || c < ' '); + } } diff -Nru jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java --- jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java 2024-12-19 21:51:26.000000000 +0000 @@ -122,7 +122,11 @@ /** * Non standard UTF-16 encoding eg {@code /foo%u2192bar}. */ - UTF16("Non standard UTF-16 encoding"); + UTF16("Non standard UTF-16 encoding"), + /** + * User info in authority + */ + USER_INFO("User info in Authority"); private final String _message; @@ -155,6 +159,84 @@ __ambiguousSegments.put("%u002e%u002e", Boolean.TRUE); } + private static final boolean[] __unreservedPctEncodedSubDelims; + + private static boolean isDigit(char c) + { + return (c >= '0') && (c <= '9'); + } + + private static boolean isHexDigit(char c) + { + return (((c >= 'a') && (c <= 'f')) || // ALPHA (lower) + ((c >= 'A') && (c <= 'F')) || // ALPHA (upper) + ((c >= '0') && (c <= '9'))); + } + + private static boolean isUnreserved(char c) + { + return (((c >= 'a') && (c <= 'z')) || // ALPHA (lower) + ((c >= 'A') && (c <= 'Z')) || // ALPHA (upper) + ((c >= '0') && (c <= '9')) || // DIGIT + (c == '-') || (c == '.') || (c == '_') || (c == '~')); + } + + private static boolean isSubDelim(char c) + { + return c == '!' || c == '$' || c == '&' || c == '\'' || c == '(' || c == ')' || c == '*' || c == '+' || c == ',' || c == ';' || c == '='; + } + + static boolean isUnreservedPctEncodedOrSubDelim(char c) + { + return c < __unreservedPctEncodedSubDelims.length && __unreservedPctEncodedSubDelims[c]; + } + + static + { + // Establish allowed and disallowed characters per the path rules of + // https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 + // ABNF + // path = path-abempty ; begins with "/" or is empty + // / path-absolute ; begins with "/" but not "//" + // / path-noscheme ; begins with a non-colon segment + // / path-rootless ; begins with a segment + // / path-empty ; zero characters + // path-abempty = *( "/" segment ) + // path-absolute = "/" [ segment-nz *( "/" segment ) ] + // path-noscheme = segment-nz-nc *( "/" segment ) + // path-rootless = segment-nz *( "/" segment ) + // path-empty = 0
Used to decoded Huffman encoded strings.
+ * + *Characters which are illegal field-vchar values are replaced with + * either ' ' or '?' as described in RFC9110
+ */ +public class HuffmanDecoder +{ + private final CharsetStringBuilder.Iso88591StringBuilder _builder = new CharsetStringBuilder.Iso88591StringBuilder(); + private int _length = 0; + private int _count = 0; + private int _node = 0; + private int _current = 0; + private int _bits = 0; + + /** + * @param length in bytes of the huffman data. + */ + public void setLength(int length) + { + if (_count != 0) + throw new IllegalStateException(); + _length = length; + } + + /** + * @param buffer the buffer containing the Huffman encoded bytes. + * @return the decoded String. + * @throws EncodingException if the huffman encoding is invalid. + */ + public String decode(ByteBuffer buffer) throws EncodingException + { + for (; _count < _length; _count++) + { + if (!buffer.hasRemaining()) + return null; + + int b = buffer.get() & 0xFF; + _current = (_current << 8) | b; + _bits += 8; + while (_bits >= 8) + { + int i = (_current >>> (_bits - 8)) & 0xFF; + _node = Huffman.tree[_node * 256 + i]; + if (rowbits[_node] != 0) + { + if (rowsym[_node] == Huffman.EOS) + { + reset(); + throw new EncodingException("eos_in_content"); + } + + // terminal node + char c = rowsym[_node]; + c = HttpTokens.sanitizeFieldVchar(c); + _builder.append((byte)c); + _bits -= rowbits[_node]; + _node = 0; + } + else + { + // non-terminal node + _bits -= 8; + } + } + } + + while (_bits > 0) + { + int i = (_current << (8 - _bits)) & 0xFF; + int lastNode = _node; + _node = Huffman.tree[_node * 256 + i]; + + if (rowbits[_node] == 0 || rowbits[_node] > _bits) + { + int requiredPadding = 0; + for (int j = 0; j < _bits; j++) + { + requiredPadding = (requiredPadding << 1) | 1; + } + + if ((i >> (8 - _bits)) != requiredPadding) + throw new EncodingException("incorrect_padding"); + + _node = lastNode; + break; + } + + char c = rowsym[_node]; + c = HttpTokens.sanitizeFieldVchar(c); + _builder.append((byte)c); + _bits -= rowbits[_node]; + _node = 0; + } + + if (_node != 0) + { + reset(); + throw new EncodingException("bad_termination"); + } + + String value = _builder.build(); + reset(); + return value; + } + + public void reset() + { + _builder.reset(); + _count = 0; + _current = 0; + _node = 0; + _bits = 0; + } +} diff -Nru jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanEncoder.java jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanEncoder.java --- jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanEncoder.java 1970-01-01 00:00:00.000000000 +0000 +++ jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanEncoder.java 2024-12-19 21:51:26.000000000 +0000 @@ -0,0 +1,142 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.http.compression; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.http.HttpTokens; + +import static org.eclipse.jetty.http.compression.Huffman.CODES; +import static org.eclipse.jetty.http.compression.Huffman.LCCODES; + +/** + *Used to encode strings Huffman encoding.
+ * + *Characters are encoded with ISO-8859-1, if any multi-byte characters or + * control characters are present the encoder will throw {@link EncodingException}.
+ */ +public class HuffmanEncoder +{ + private HuffmanEncoder() + { + } + + /** + * @param s the string to encode. + * @return the number of octets needed to encode the string, or -1 if it cannot be encoded. + */ + public static int octetsNeeded(String s) + { + return octetsNeeded(CODES, s); + } + + /** + * @param b the byte array to encode. + * @return the number of octets needed to encode the bytes, or -1 if it cannot be encoded. + */ + public static int octetsNeeded(byte[] b) + { + int needed = 0; + for (byte value : b) + { + int c = 0xFF & value; + needed += CODES[c][1]; + } + return (needed + 7) / 8; + } + + /** + * @param buffer the buffer to encode into. + * @param s the string to encode. + */ + public static void encode(ByteBuffer buffer, String s) + { + encode(CODES, buffer, s); + } + + /** + * @param s the string to encode in lowercase. + * @return the number of octets needed to encode the string, or -1 if it cannot be encoded. + */ + public static int octetsNeededLowerCase(String s) + { + return octetsNeeded(LCCODES, s); + } + + /** + * @param buffer the buffer to encode into in lowercase. + * @param s the string to encode. + */ + public static void encodeLowerCase(ByteBuffer buffer, String s) + { + encode(LCCODES, buffer, s); + } + + private static int octetsNeeded(final int[][] table, String s) + { + int needed = 0; + int len = s.length(); + for (int i = 0; i < len; i++) + { + char c = s.charAt(i); + if (HttpTokens.isIllegalFieldVchar(c)) + return -1; + needed += table[c][1]; + } + + return (needed + 7) / 8; + } + + /** + * @param table The table to encode by + * @param buffer The buffer to encode to + * @param s The string to encode + */ + private static void encode(final int[][] table, ByteBuffer buffer, String s) + { + long current = 0; + int n = 0; + int len = s.length(); + for (int i = 0; i < len; i++) + { + char c = s.charAt(i); + if (HttpTokens.isIllegalFieldVchar(c)) + throw new IllegalArgumentException(); + int code = table[c][0]; + int bits = table[c][1]; + + current <<= bits; + current |= code; + n += bits; + + while (n >= 8) + { + n -= 8; + buffer.put((byte)(current >> n)); + } + } + + if (n > 0) + { + current <<= (8 - n); + current |= (0xFF >>> n); + buffer.put((byte)(current)); + } + } +} diff -Nru jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitIntegerDecoder.java jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitIntegerDecoder.java --- jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitIntegerDecoder.java 1970-01-01 00:00:00.000000000 +0000 +++ jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitIntegerDecoder.java 2024-12-19 21:51:26.000000000 +0000 @@ -0,0 +1,113 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.http.compression; + +import java.nio.ByteBuffer; + +/** + * Used to decode integers as described in RFC7541. + */ +public class NBitIntegerDecoder +{ + private int _prefix; + private long _total; + private long _multiplier; + private boolean _started; + + /** + * Set the prefix length in of the integer representation in bits. + * A prefix of 6 means the integer representation starts after the first 2 bits. + * @param prefix the number of bits in the integer prefix. + */ + public void setPrefix(int prefix) + { + if (_started) + throw new IllegalStateException(); + _prefix = prefix; + } + + /** + * Decode an integer from the buffer. If the buffer does not contain the complete integer representation + * a value of -1 is returned to indicate that more data is needed to complete parsing. + * This should be only after the prefix has been set with {@link #setPrefix(int)}. + * @param buffer the buffer containing the encoded integer. + * @return the decoded integer or -1 to indicate that more data is needed. + * @throws ArithmeticException if the value overflows a int. + */ + public int decodeInt(ByteBuffer buffer) + { + return Math.toIntExact(decodeLong(buffer)); + } + + /** + * Decode a long from the buffer. If the buffer does not contain the complete integer representation + * a value of -1 is returned to indicate that more data is needed to complete parsing. + * This should be only after the prefix has been set with {@link #setPrefix(int)}. + * @param buffer the buffer containing the encoded integer. + * @return the decoded long or -1 to indicate that more data is needed. + * @throws ArithmeticException if the value overflows a long. + */ + public long decodeLong(ByteBuffer buffer) + { + if (!_started) + { + if (!buffer.hasRemaining()) + return -1; + + _started = true; + _multiplier = 1; + int nbits = 0xFF >>> (8 - _prefix); + _total = buffer.get() & nbits; + if (_total < nbits) + { + long total = _total; + reset(); + return total; + } + } + + while (true) + { + // If we have no more remaining we return -1 to indicate that more data is needed to continue parsing. + if (!buffer.hasRemaining()) + return -1; + + int b = buffer.get() & 0xFF; + _total = Math.addExact(_total, (b & 127) * _multiplier); + _multiplier = Math.multiplyExact(_multiplier, 128); + if ((b & 128) == 0) + { + long total = _total; + reset(); + return total; + } + } + } + + /** + * Reset the internal state of the parser. + */ + public void reset() + { + _prefix = 0; + _total = 0; + _multiplier = 1; + _started = false; + } +} diff -Nru jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitIntegerEncoder.java jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitIntegerEncoder.java --- jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitIntegerEncoder.java 1970-01-01 00:00:00.000000000 +0000 +++ jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitIntegerEncoder.java 2024-12-19 21:51:26.000000000 +0000 @@ -0,0 +1,96 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.http.compression; + +import java.nio.ByteBuffer; + +/** + * Used to encode integers as described in RFC7541. + */ +public class NBitIntegerEncoder +{ + private NBitIntegerEncoder() + { + } + + /** + * @param prefix the prefix used to encode this long. + * @param value the integer to encode. + * @return the number of octets it would take to encode the long. + */ + public static int octetsNeeded(int prefix, long value) + { + if (prefix <= 0 || prefix > 8) + throw new IllegalArgumentException(); + + int nbits = 0xFF >>> (8 - prefix); + value = value - nbits; + if (value < 0) + return 1; + if (value == 0) + return 2; + int lz = Long.numberOfLeadingZeros(value); + int log = 64 - lz; + + // The return value is 1 for the prefix + the number of 7-bit groups necessary to encode the value. + return 1 + (log + 6) / 7; + } + + /** + * + * @param buffer the buffer to encode into. + * @param prefix the prefix used to encode this long. + * @param value the long to encode into the buffer. + */ + public static void encode(ByteBuffer buffer, int prefix, long value) + { + if (prefix <= 0 || prefix > 8) + throw new IllegalArgumentException(); + + // If prefix is 8 we add an empty byte as we initially modify last byte from the buffer. + if (prefix == 8) + buffer.put((byte)0x00); + + int bits = 0xFF >>> (8 - prefix); + int p = buffer.position() - 1; + if (value < bits) + { + buffer.put(p, (byte)((buffer.get(p) & ~bits) | value)); + } + else + { + buffer.put(p, (byte)(buffer.get(p) | bits)); + long length = value - bits; + while (true) + { + // The value of ~0x7F is different to 0x80 because of all the 1s from the MSB. + if ((length & ~0x7FL) == 0) + { + buffer.put((byte)length); + return; + } + else + { + buffer.put((byte)((length & 0x7F) | 0x80)); + length >>>= 7; + } + } + } + } +} diff -Nru jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitStringDecoder.java jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitStringDecoder.java --- jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitStringDecoder.java 1970-01-01 00:00:00.000000000 +0000 +++ jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitStringDecoder.java 2024-12-19 21:51:26.000000000 +0000 @@ -0,0 +1,138 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.http.compression; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.util.CharsetStringBuilder; + +/** + *Used to decode string literals as described in RFC7541.
+ * + *The string literal representation consists of a single bit to indicate whether huffman encoding is used, + * followed by the string byte length encoded with the n-bit integer representation also from RFC7541, and + * the bytes of the string are directly after this.
+ * + *Characters which are illegal field-vchar values are replaced with + * either ' ' or '?' as described in RFC9110
+ */ +public class NBitStringDecoder +{ + private final NBitIntegerDecoder _integerDecoder; + private final HuffmanDecoder _huffmanBuilder; + private final CharsetStringBuilder.Iso88591StringBuilder _builder; + private boolean _huffman; + private int _count; + private int _length; + private int _prefix; + + private State _state = State.PARSING; + + private enum State + { + PARSING, + LENGTH, + VALUE + } + + public NBitStringDecoder() + { + _integerDecoder = new NBitIntegerDecoder(); + _huffmanBuilder = new HuffmanDecoder(); + _builder = new CharsetStringBuilder.Iso88591StringBuilder(); + } + + /** + * Set the prefix length in of the string representation in bits. + * A prefix of 6 means the string representation starts after the first 2 bits. + * @param prefix the number of bits in the string prefix. + */ + public void setPrefix(int prefix) + { + if (_state != State.PARSING) + throw new IllegalStateException(); + _prefix = prefix; + } + + /** + * Decode a string from the buffer. If the buffer does not contain the complete string representation + * then a value of null is returned to indicate that more data is needed to complete parsing. + * This should be only after the prefix has been set with {@link #setPrefix(int)}. + * @param buffer the buffer containing the encoded string. + * @return the decoded string or null to indicate that more data is needed. + * @throws ArithmeticException if the string length value overflows a int. + * @throws EncodingException if the string encoding is invalid. + */ + public String decode(ByteBuffer buffer) throws EncodingException + { + while (true) + { + switch (_state) + { + case PARSING: + byte firstByte = buffer.get(buffer.position()); + _huffman = ((0x80 >>> (8 - _prefix)) & firstByte) != 0; + _state = State.LENGTH; + _integerDecoder.setPrefix(_prefix - 1); + continue; + + case LENGTH: + _length = _integerDecoder.decodeInt(buffer); + if (_length < 0) + return null; + _state = State.VALUE; + _huffmanBuilder.setLength(_length); + continue; + + case VALUE: + String value = _huffman ? _huffmanBuilder.decode(buffer) : stringDecode(buffer); + if (value != null) + reset(); + return value; + + default: + throw new IllegalStateException(_state.name()); + } + } + } + + private String stringDecode(ByteBuffer buffer) + { + for (; _count < _length; _count++) + { + if (!buffer.hasRemaining()) + return null; + _builder.append(buffer.get()); + } + + return _builder.build(); + } + + public void reset() + { + _state = State.PARSING; + _integerDecoder.reset(); + _huffmanBuilder.reset(); + _builder.reset(); + _prefix = 0; + _count = 0; + _length = 0; + _huffman = false; + } +} diff -Nru jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitStringEncoder.java jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitStringEncoder.java --- jetty9-9.4.50/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitStringEncoder.java 1970-01-01 00:00:00.000000000 +0000 +++ jetty9-9.4.57/jetty-http/src/main/java/org/eclipse/jetty/http/compression/NBitStringEncoder.java 2024-12-19 21:51:26.000000000 +0000 @@ -0,0 +1,82 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.http.compression; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.http.HttpTokens; + +public class NBitStringEncoder +{ + private NBitStringEncoder() + { + } + + public static int octetsNeeded(int prefix, String value, boolean huffman) + { + if (prefix <= 0 || prefix > 8) + throw new IllegalArgumentException(); + + int contentPrefix = (prefix == 1) ? 8 : prefix - 1; + int encodedValueSize = huffman ? HuffmanEncoder.octetsNeeded(value) : value.length(); + int encodedLengthSize = NBitIntegerEncoder.octetsNeeded(contentPrefix, encodedValueSize); + + // If prefix was 1, then we count an extra byte needed for the prefix. + return encodedLengthSize + encodedValueSize + (prefix == 1 ? 1 : 0); + } + + public static void encode(ByteBuffer buffer, int prefix, String value, boolean huffman) + { + if (prefix <= 0 || prefix > 8) + throw new IllegalArgumentException(); + + byte huffmanFlag = huffman ? (byte)(0x01 << (prefix - 1)) : (byte)0x00; + if (prefix == 8) + { + buffer.put(huffmanFlag); + } + else + { + int p = buffer.position() - 1; + buffer.put(p, (byte)(buffer.get(p) | huffmanFlag)); + } + + // Start encoding size & content in rest of prefix. + // If prefix was 1 we set it back to 8 to indicate to start on a new byte. + prefix = (prefix == 1) ? 8 : prefix - 1; + + if (huffman) + { + int encodedValueSize = HuffmanEncoder.octetsNeeded(value); + NBitIntegerEncoder.encode(buffer, prefix, encodedValueSize); + HuffmanEncoder.encode(buffer, value); + } + else + { + int encodedValueSize = value.length(); + NBitIntegerEncoder.encode(buffer, prefix, encodedValueSize); + for (int i = 0; i < encodedValueSize; i++) + { + char c = value.charAt(i); + c = HttpTokens.sanitizeFieldVchar(c); + buffer.put((byte)c); + } + } + } +} diff -Nru jetty9-9.4.50/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java jetty9-9.4.57/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java --- jetty9-9.4.50/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java 2024-12-19 21:51:26.000000000 +0000 @@ -41,6 +41,7 @@ import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -1672,7 +1673,7 @@ } @Test - public void testUnknownReponseVersion() + public void testUnknownResponseVersion() { ByteBuffer buffer = BufferUtil.toBuffer( "HPPT/7.7 200 OK\r\n" + @@ -1815,65 +1816,31 @@ assertEquals(HttpParser.State.CLOSED, parser.getState()); } - @Test - public void testBadContentLength0() - { - ByteBuffer buffer = BufferUtil.toBuffer( - "GET / HTTP/1.0\r\n" + - "Content-Length: abc\r\n" + - "Connection: close\r\n" + - "\r\n"); - - HttpParser.RequestHandler handler = new Handler(); - HttpParser parser = new HttpParser(handler); - - parser.parseNext(buffer); - assertEquals("GET", _methodOrVersion); - assertEquals("Invalid Content-Length Value", _bad); - assertFalse(buffer.hasRemaining()); - assertEquals(HttpParser.State.CLOSE, parser.getState()); - parser.atEOF(); - parser.parseNext(BufferUtil.EMPTY_BUFFER); - assertEquals(HttpParser.State.CLOSED, parser.getState()); - } - - @Test - public void testBadContentLength1() - { - ByteBuffer buffer = BufferUtil.toBuffer( - "GET / HTTP/1.0\r\n" + - "Content-Length: 9999999999999999999999999999999999999999999999\r\n" + - "Connection: close\r\n" + - "\r\n"); - - HttpParser.RequestHandler handler = new Handler(); - HttpParser parser = new HttpParser(handler); - - parser.parseNext(buffer); - assertEquals("GET", _methodOrVersion); - assertEquals("Invalid Content-Length Value", _bad); - assertFalse(buffer.hasRemaining()); - assertEquals(HttpParser.State.CLOSE, parser.getState()); - parser.atEOF(); - parser.parseNext(BufferUtil.EMPTY_BUFFER); - assertEquals(HttpParser.State.CLOSED, parser.getState()); - } - - @Test - public void testBadContentLength2() + @ParameterizedTest + @ValueSource(strings = { + "abc", + "1.5", + "9999999999999999999999999999999999999999999999", + "-10", + "+10", + "1.0", + "1,0", + "10," + }) + public void testBadContentLengths(String contentLength) { ByteBuffer buffer = BufferUtil.toBuffer( - "GET / HTTP/1.0\r\n" + - "Content-Length: 1.5\r\n" + - "Connection: close\r\n" + - "\r\n"); + "GET /test HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Content-Length: " + contentLength + "\r\n" + + "\r\n" + + "1234567890\r\n"); HttpParser.RequestHandler handler = new Handler(); - HttpParser parser = new HttpParser(handler); + HttpParser parser = new HttpParser(handler, HttpCompliance.RFC2616_LEGACY); + parseAll(parser, buffer); - parser.parseNext(buffer); - assertEquals("GET", _methodOrVersion); - assertEquals("Invalid Content-Length Value", _bad); + assertThat(_bad, notNullValue()); assertFalse(buffer.hasRemaining()); assertEquals(HttpParser.State.CLOSE, parser.getState()); parser.atEOF(); @@ -2084,7 +2051,7 @@ @Test public void testBadIPv6Host() { - try (StacklessLogging s = new StacklessLogging(HttpParser.class)) + try (StacklessLogging ignored = new StacklessLogging(HttpParser.class)) { ByteBuffer buffer = BufferUtil.toBuffer( "GET / HTTP/1.1\r\n" + @@ -2930,8 +2897,8 @@ private String _methodOrVersion; private String _uriOrStatus; private String _versionOrReason; - private ListSets the limit for the encoder HPACK dynamic table capacity.
+ *Setting this value to {@code 0} disables the use of the dynamic table.
+ * + * @param maxEncoderTableCapacity The HPACK encoder dynamic table maximum capacity + */ + public void setMaxEncoderTableCapacity(int maxEncoderTableCapacity) + { + this.maxEncoderTableCapacity = maxEncoderTableCapacity; + } + + @ManagedAttribute("The HPACK decoder dynamic table maximum capacity") + public int getMaxDecoderTableCapacity() + { + return maxDecoderTableCapacity; + } + + public void setMaxDecoderTableCapacity(int maxDecoderTableCapacity) + { + this.maxDecoderTableCapacity = maxDecoderTableCapacity; + } + + @Deprecated @ManagedAttribute("The HPACK dynamic table maximum size") public int getMaxDynamicTableSize() { - return maxDynamicTableSize; + return getMaxDecoderTableCapacity(); } + @Deprecated public void setMaxDynamicTableSize(int maxDynamicTableSize) { - this.maxDynamicTableSize = maxDynamicTableSize; + setMaxDecoderTableCapacity(maxDynamicTableSize); } @ManagedAttribute("The max size of header block fragments") @@ -407,6 +465,17 @@ this.maxHeaderBlockFragment = maxHeaderBlockFragment; } + @ManagedAttribute("The max size of response headers") + public int getMaxResponseHeadersSize() + { + return maxResponseHeadersSize; + } + + public void setMaxResponseHeadersSize(int maxResponseHeadersSize) + { + this.maxResponseHeadersSize = maxResponseHeadersSize; + } + public void connect(InetSocketAddress address, Session.Listener listener, PromiseThe HTTP/2 specification requires that stream ids are monotonically increasing, - * see https://tools.ietf.org/html/rfc7540#section-5.1.1.
+ * see RFC 7540, 5.1.1. *This implementation uses a queue to atomically reserve a stream id and claim * a slot in the queue; the slot is then assigned the entries to write.
*Concurrent threads push slots in the queue but only one thread flushes * the slots, up to the slot that has a non-null entries to write, therefore * guaranteeing that frames are sent strictly in their stream id order.
*This class also coordinates the creation of streams with the close of - * the session, see https://tools.ietf.org/html/rfc7540#section-6.8.
+ * the session, see + * RFC 7540, 6.8. */ private class StreamsState { @@ -1772,6 +1824,7 @@ { String reason = "idle_timeout"; boolean notify = false; + boolean terminate = false; boolean sendGoAway = false; GoAwayFrame goAwayFrame = null; Throwable cause = null; @@ -1815,11 +1868,22 @@ { if (LOG.isDebugEnabled()) LOG.debug("Already closed, ignored idle timeout for {}", HTTP2Session.this); - return false; + // Writes may be TCP congested, so termination never happened. + terminate = true; + goAwayFrame = goAwaySent; + if (goAwayFrame == null) + goAwayFrame = goAwayRecv; + break; } } } + if (terminate) + { + terminate(goAwayFrame); + return false; + } + if (notify) { boolean confirmed = notifyIdleTimeout(HTTP2Session.this); @@ -2036,14 +2100,15 @@ private boolean newRemoteStream(int streamId) { + boolean created = false; try (Locker.Lock l = lock.lock()) { switch (closed) { case NOT_CLOSED: { - HTTP2Session.this.onStreamCreated(streamId); - return true; + created = true; + break; } case LOCALLY_CLOSED: { @@ -2051,15 +2116,17 @@ if (streamId <= goAwaySent.getLastStreamId()) { // Allow creation of streams that may have been in-flight. - HTTP2Session.this.onStreamCreated(streamId); - return true; + created = true; } - return false; + break; } default: - return false; + break; } } + if (created) + HTTP2Session.this.onStreamCreated(streamId); + return created; } private void push(PushPromiseFrame frame, PromiseSets the limit for the capacity of the dynamic header table.
+ *This value acts as a limit for the values received from the + * remote peer via the HPACK dynamic table size update instruction.
+ *After calling this method, a SETTINGS frame must be sent to the other + * peer, containing the {@code SETTINGS_HEADER_TABLE_SIZE} setting with + * the value passed as argument to this method.
+ * + * @param maxTableCapacity the limit for capacity of the dynamic header table + */ + public void setMaxTableCapacity(int maxTableCapacity) + { + _maxTableCapacity = maxTableCapacity; + } + + /** + * @param maxTableSizeLimit the local dynamic table max size + * @deprecated use {@link #setMaxTableCapacity(int)} instead + */ + @Deprecated + public void setLocalMaxDynamicTableSize(int maxTableSizeLimit) { - _localMaxDynamicTableSize = localMaxdynamciTableSize; + setMaxTableCapacity(maxTableSizeLimit); + } + + public int getMaxHeaderListSize() + { + return _builder.getMaxSize(); + } + + public void setMaxHeaderListSize(int maxHeaderListSize) + { + _builder.setMaxSize(maxHeaderListSize); } public MetaData decode(ByteBuffer buffer) throws HpackException.SessionException, HpackException.StreamException @@ -69,27 +118,22 @@ if (LOG.isDebugEnabled()) LOG.debug(String.format("CtxTbl[%x] decoding %d octets", _context.hashCode(), buffer.remaining())); - // If the buffer is big, don't even think about decoding it - if (buffer.remaining() > _builder.getMaxSize()) - throw new HpackException.SessionException("431 Request Header Fields too large"); + // If the buffer is larger than the max headers size, don't even start decoding it. + int maxSize = _builder.getMaxSize(); + if (maxSize > 0 && buffer.remaining() > maxSize) + throw new HpackException.SessionException("Header fields size too large"); boolean emitted = false; - while (buffer.hasRemaining()) { - if (LOG.isDebugEnabled() && buffer.hasArray()) - { - int l = Math.min(buffer.remaining(), 32); - LOG.debug("decode {}{}", - TypeUtil.toHexString(buffer.array(), buffer.arrayOffset() + buffer.position(), l), - l < buffer.remaining() ? "..." : ""); - } + if (LOG.isDebugEnabled()) + LOG.debug("decode {}", BufferUtil.toHexString(buffer)); byte b = buffer.get(); if (b < 0) { // 7.1 indexed if the high bit is set - int index = NBitInteger.decode(buffer, 7); + int index = integerDecode(buffer, 7); Entry entry = _context.get(index); if (entry == null) throw new HpackException.SessionException("Unknown index %d", index); @@ -130,11 +174,11 @@ case 2: // 7.3 case 3: // 7.3 // change table size - int size = NBitInteger.decode(buffer, 5); + int size = integerDecode(buffer, 5); if (LOG.isDebugEnabled()) - LOG.debug("decode resize=" + size); - if (size > _localMaxDynamicTableSize) - throw new IllegalArgumentException(); + LOG.debug("decode resize={}", size); + if (size > getMaxTableCapacity()) + throw new HpackException.CompressionException("Dynamic table resize exceeded max limit"); if (emitted) throw new HpackException.CompressionException("Dynamic table resize after fields"); _context.resize(size); @@ -143,7 +187,7 @@ case 0: // 7.2.2 case 1: // 7.2.3 indexed = false; - nameIndex = NBitInteger.decode(buffer, 4); + nameIndex = integerDecode(buffer, 4); break; case 4: // 7.2.1 @@ -151,7 +195,7 @@ case 6: // 7.2.1 case 7: // 7.2.1 indexed = true; - nameIndex = NBitInteger.decode(buffer, 6); + nameIndex = integerDecode(buffer, 6); break; default: @@ -170,12 +214,11 @@ else { huffmanName = (buffer.get() & 0x80) == 0x80; - int length = NBitInteger.decode(buffer, 7); - _builder.checkSize(length, huffmanName); + int length = integerDecode(buffer, 7); if (huffmanName) - name = Huffman.decode(buffer, length); + name = huffmanDecode(buffer, length); else - name = toASCIIString(buffer, length); + name = toISO88591String(buffer, length); check: for (int i = name.length(); i-- > 0; ) { @@ -211,12 +254,11 @@ // decode the value boolean huffmanValue = (buffer.get() & 0x80) == 0x80; - int length = NBitInteger.decode(buffer, 7); - _builder.checkSize(length, huffmanValue); + int length = integerDecode(buffer, 7); if (huffmanValue) - value = Huffman.decode(buffer, length); + value = huffmanDecode(buffer, length); else - value = toASCIIString(buffer, length); + value = toISO88591String(buffer, length); // Make the new field HttpField field; @@ -277,19 +319,61 @@ return _builder.build(); } - public static String toASCIIString(ByteBuffer buffer, int length) + private int integerDecode(ByteBuffer buffer, int prefix) throws HpackException.CompressionException + { + try + { + if (prefix != 8) + buffer.position(buffer.position() - 1); + + _integerDecoder.setPrefix(prefix); + int decodedInt = _integerDecoder.decodeInt(buffer); + if (decodedInt < 0) + throw new EncodingException("invalid integer encoding"); + return decodedInt; + } + catch (EncodingException e) + { + HpackException.CompressionException compressionException = new HpackException.CompressionException(e.getMessage()); + compressionException.initCause(e); + throw compressionException; + } + finally + { + _integerDecoder.reset(); + } + } + + private String huffmanDecode(ByteBuffer buffer, int length) throws HpackException.CompressionException + { + try + { + _huffmanDecoder.setLength(length); + String decoded = _huffmanDecoder.decode(buffer); + if (decoded == null) + throw new HpackException.CompressionException("invalid string encoding"); + return decoded; + } + catch (EncodingException e) + { + HpackException.CompressionException compressionException = new HpackException.CompressionException(e.getMessage()); + compressionException.initCause(e); + throw compressionException; + } + finally + { + _huffmanDecoder.reset(); + } + } + + public static String toISO88591String(ByteBuffer buffer, int length) { - StringBuilder builder = new StringBuilder(length); - int position = buffer.position(); - int start = buffer.arrayOffset() + position; - int end = start + length; - buffer.position(position + length); - byte[] array = buffer.array(); - for (int i = start; i < end; i++) + CharsetStringBuilder.Iso88591StringBuilder builder = new CharsetStringBuilder.Iso88591StringBuilder(); + for (int i = 0; i < length; ++i) { - builder.append((char)(0x7f & array[i])); + builder.append(HttpTokens.sanitizeFieldVchar((char)buffer.get())); } - return builder.toString(); + return builder.build(); } @Override diff -Nru jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java --- jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java 2024-12-19 21:51:26.000000000 +0000 @@ -19,7 +19,6 @@ package org.eclipse.jetty.http2.hpack; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.util.EnumMap; import java.util.EnumSet; import java.util.HashSet; @@ -34,10 +33,13 @@ import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.PreEncodedHttpField; +import org.eclipse.jetty.http.compression.HuffmanEncoder; +import org.eclipse.jetty.http.compression.NBitIntegerEncoder; +import org.eclipse.jetty.http.compression.NBitStringEncoder; import org.eclipse.jetty.http2.hpack.HpackContext.Entry; import org.eclipse.jetty.http2.hpack.HpackContext.StaticEntry; +import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -97,34 +99,79 @@ private final HpackContext _context; private final boolean _debug; - private int _remoteMaxDynamicTableSize; - private int _localMaxDynamicTableSize; + private int _maxTableCapacity; + private int _tableCapacity; private int _maxHeaderListSize; private int _headerListSize; private boolean _validateEncoding = true; + private boolean _maxDynamicTableSizeSent = false; - public HpackEncoder() - { - this(4096, 4096, -1); - } - + @Deprecated public HpackEncoder(int localMaxDynamicTableSize) { this(localMaxDynamicTableSize, 4096, -1); } + @Deprecated public HpackEncoder(int localMaxDynamicTableSize, int remoteMaxDynamicTableSize) { this(localMaxDynamicTableSize, remoteMaxDynamicTableSize, -1); } + @Deprecated public HpackEncoder(int localMaxDynamicTableSize, int remoteMaxDynamicTableSize, int maxHeaderListSize) { - _context = new HpackContext(remoteMaxDynamicTableSize); - _remoteMaxDynamicTableSize = remoteMaxDynamicTableSize; - _localMaxDynamicTableSize = localMaxDynamicTableSize; - _maxHeaderListSize = maxHeaderListSize; + this(); + setLocalMaxDynamicTableSize(localMaxDynamicTableSize); + setRemoteMaxDynamicTableSize(remoteMaxDynamicTableSize); + setMaxHeaderListSize(maxHeaderListSize); + } + + public HpackEncoder() + { + _context = new HpackContext(HpackContext.DEFAULT_MAX_TABLE_CAPACITY); _debug = LOG.isDebugEnabled(); + setMaxTableCapacity(HpackContext.DEFAULT_MAX_TABLE_CAPACITY); + setTableCapacity(HpackContext.DEFAULT_MAX_TABLE_CAPACITY); + } + + public int getMaxTableCapacity() + { + return _maxTableCapacity; + } + + /** + *Sets the limit for the capacity of the dynamic header table.
+ *This value is set by the remote peer via the + * {@code SETTINGS_HEADER_TABLE_SIZE} setting.
+ * + * @param maxTableSizeLimit the limit for capacity of the dynamic header table + */ + public void setMaxTableCapacity(int maxTableSizeLimit) + { + _maxTableCapacity = maxTableSizeLimit; + } + + public int getTableCapacity() + { + return _tableCapacity; + } + + /** + *Sets the capacity of the dynamic header table.
+ *The value of the capacity may be changed from {@code 0} + * up to {@link #getMaxTableCapacity()}. + * An HPACK instruction with the new capacity value will + * be sent to the decoder when the next call to + * {@link #encode(ByteBuffer, MetaData)} is made.
+ * + * @param tableCapacity the capacity of the dynamic header table + */ + public void setTableCapacity(int tableCapacity) + { + if (tableCapacity > getMaxTableCapacity()) + throw new IllegalArgumentException("Max table capacity exceeded"); + _tableCapacity = tableCapacity; } public int getMaxHeaderListSize() @@ -142,14 +189,16 @@ return _context; } - public void setRemoteMaxDynamicTableSize(int remoteMaxDynamicTableSize) + @Deprecated + public void setRemoteMaxDynamicTableSize(int maxTableSize) { - _remoteMaxDynamicTableSize = remoteMaxDynamicTableSize; + setTableCapacity(maxTableSize); } - public void setLocalMaxDynamicTableSize(int localMaxDynamicTableSize) + @Deprecated + public void setLocalMaxDynamicTableSize(int maxTableSizeLimit) { - _localMaxDynamicTableSize = localMaxDynamicTableSize; + setMaxTableCapacity(maxTableSizeLimit); } public boolean isValidateEncoding() @@ -185,10 +234,13 @@ _headerListSize = 0; int pos = buffer.position(); - // Check the dynamic table sizes! - int maxDynamicTableSize = Math.min(_remoteMaxDynamicTableSize, _localMaxDynamicTableSize); - if (maxDynamicTableSize != _context.getMaxDynamicTableSize()) - encodeMaxDynamicTableSize(buffer, maxDynamicTableSize); + // If max table size changed, send the correspondent instruction. + int tableCapacity = getTableCapacity(); + if (!_maxDynamicTableSizeSent || tableCapacity != _context.getMaxDynamicTableSize()) + { + _maxDynamicTableSizeSent = true; + encodeMaxDynamicTableSize(buffer, tableCapacity); + } // Add Request/response meta fields if (metadata.isRequest()) @@ -255,13 +307,9 @@ } } - // Check size - if (_maxHeaderListSize > 0 && _headerListSize > _maxHeaderListSize) - { - LOG.warn("Header list size too large {} > {} for {}", _headerListSize, _maxHeaderListSize); - if (LOG.isDebugEnabled()) - LOG.debug("metadata={}", metadata); - } + int maxHeaderListSize = getMaxHeaderListSize(); + if (maxHeaderListSize > 0 && _headerListSize > maxHeaderListSize) + throw new HpackException.SessionException("Header size %d > %d", _headerListSize, maxHeaderListSize); if (LOG.isDebugEnabled()) LOG.debug(String.format("CtxTbl[%x] encoded %d octets", _context.hashCode(), buffer.position() - pos)); @@ -278,13 +326,11 @@ } } - public void encodeMaxDynamicTableSize(ByteBuffer buffer, int maxDynamicTableSize) + public void encodeMaxDynamicTableSize(ByteBuffer buffer, int maxTableSize) { - if (maxDynamicTableSize > _remoteMaxDynamicTableSize) - throw new IllegalArgumentException(); buffer.put((byte)0x20); - NBitInteger.encode(buffer, 5, maxDynamicTableSize); - _context.resize(maxDynamicTableSize); + NBitIntegerEncoder.encode(buffer, 5, maxTableSize); + _context.resize(maxTableSize); } public void encode(ByteBuffer buffer, HttpField field) @@ -295,8 +341,6 @@ int fieldSize = field.getName().length() + field.getValue().length(); _headerListSize += fieldSize + 32; - final int p = _debug ? buffer.position() : -1; - String encoding = null; // Is there an index entry for the field? @@ -314,9 +358,9 @@ { int index = _context.index(entry); buffer.put((byte)0x80); - NBitInteger.encode(buffer, 7, index); + NBitIntegerEncoder.encode(buffer, 7, index); if (_debug) - encoding = "IdxField" + (entry.isStatic() ? "S" : "") + (1 + NBitInteger.octectsNeeded(7, index)); + encoding = "IdxField" + (entry.isStatic() ? "S" : "") + NBitIntegerEncoder.octetsNeeded(7, index); } } else @@ -390,19 +434,19 @@ if (_debug) encoding = "Lit" + - ((name == null) ? "HuffN" : ("IdxN" + (name.isStatic() ? "S" : "") + (1 + NBitInteger.octectsNeeded(4, _context.index(name))))) + + ((name == null) ? "HuffN" : ("IdxN" + (name.isStatic() ? "S" : "") + (1 + NBitIntegerEncoder.octetsNeeded(4, _context.index(name))))) + (huffman ? "HuffV" : "LitV") + (neverIndex ? "!!Idx" : "!Idx"); } else if (fieldSize >= _context.getMaxDynamicTableSize() || header == HttpHeader.CONTENT_LENGTH && !"0".equals(field.getValue())) { - // The field is too large or a non zero content length, so do not index. + // The field is too large or a non-zero content length, so do not index. indexed = false; encodeName(buffer, (byte)0x00, 4, header.asString(), name); encodeValue(buffer, true, field.getValue()); if (_debug) encoding = "Lit" + - ((name == null) ? "HuffN" : "IdxNS" + (1 + NBitInteger.octectsNeeded(4, _context.index(name)))) + + ((name == null) ? "HuffN" : "IdxNS" + (1 + NBitIntegerEncoder.octetsNeeded(4, _context.index(name)))) + "HuffV!Idx"; } else @@ -413,7 +457,7 @@ encodeName(buffer, (byte)0x40, 6, header.asString(), name); encodeValue(buffer, huffman, field.getValue()); if (_debug) - encoding = ((name == null) ? "LitHuffN" : ("LitIdxN" + (name.isStatic() ? "S" : "") + (1 + NBitInteger.octectsNeeded(6, _context.index(name))))) + + encoding = ((name == null) ? "LitHuffN" : ("LitIdxN" + (name.isStatic() ? "S" : "") + (1 + NBitIntegerEncoder.octetsNeeded(6, _context.index(name))))) + (huffman ? "HuffVIdx" : "LitVIdx"); } } @@ -425,10 +469,8 @@ if (_debug) { - byte[] bytes = new byte[buffer.position() - p]; - buffer.position(p); - buffer.get(bytes); - LOG.debug("encode {}:'{}' to '{}'", encoding, field, TypeUtil.toHexString(bytes)); + if (LOG.isDebugEnabled()) + LOG.debug("encode {}:'{}' to '{}'", encoding, field, BufferUtil.toHexString((ByteBuffer)buffer.duplicate().flip())); } } @@ -440,55 +482,17 @@ // leave name index bits as 0 // Encode the name always with lowercase huffman buffer.put((byte)0x80); - NBitInteger.encode(buffer, 7, Huffman.octetsNeededLC(name)); - Huffman.encodeLC(buffer, name); + NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeededLowerCase(name)); + HuffmanEncoder.encodeLowerCase(buffer, name); } else { - NBitInteger.encode(buffer, bits, _context.index(entry)); + NBitIntegerEncoder.encode(buffer, bits, _context.index(entry)); } } static void encodeValue(ByteBuffer buffer, boolean huffman, String value) { - if (huffman) - { - // huffman literal value - buffer.put((byte)0x80); - - int needed = Huffman.octetsNeeded(value); - if (needed >= 0) - { - NBitInteger.encode(buffer, 7, needed); - Huffman.encode(buffer, value); - } - else - { - // Not iso_8859_1 - byte[] bytes = value.getBytes(StandardCharsets.UTF_8); - NBitInteger.encode(buffer, 7, Huffman.octetsNeeded(bytes)); - Huffman.encode(buffer, bytes); - } - } - else - { - // add literal assuming iso_8859_1 - buffer.put((byte)0x00).mark(); - NBitInteger.encode(buffer, 7, value.length()); - for (int i = 0; i < value.length(); i++) - { - char c = value.charAt(i); - if (c < ' ' || c > 127) - { - // Not iso_8859_1, so re-encode as UTF-8 - buffer.reset(); - byte[] bytes = value.getBytes(StandardCharsets.UTF_8); - NBitInteger.encode(buffer, 7, bytes.length); - buffer.put(bytes, 0, bytes.length); - return; - } - buffer.put((byte)c); - } - } + NBitStringEncoder.encode(buffer, 8, value, huffman); } } diff -Nru jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackException.java jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackException.java --- jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackException.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackException.java 2024-12-19 21:51:26.000000000 +0000 @@ -18,7 +18,6 @@ package org.eclipse.jetty.http2.hpack; -@SuppressWarnings("serial") public abstract class HpackException extends Exception { HpackException(String messageFormat, Object... args) @@ -35,7 +34,7 @@ */ public static class StreamException extends HpackException { - StreamException(String messageFormat, Object... args) + public StreamException(String messageFormat, Object... args) { super(messageFormat, args); } @@ -48,7 +47,7 @@ */ public static class SessionException extends HpackException { - SessionException(String messageFormat, Object... args) + public SessionException(String messageFormat, Object... args) { super(messageFormat, args); } diff -Nru jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java --- jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java 2024-12-19 21:51:26.000000000 +0000 @@ -23,6 +23,8 @@ import org.eclipse.jetty.http.HttpFieldPreEncoder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.http.compression.HuffmanEncoder; +import org.eclipse.jetty.http.compression.NBitIntegerEncoder; import org.eclipse.jetty.util.BufferUtil; /** @@ -31,18 +33,12 @@ public class HpackFieldPreEncoder implements HttpFieldPreEncoder { - /** - * @see org.eclipse.jetty.http.HttpFieldPreEncoder#getHttpVersion() - */ @Override public HttpVersion getHttpVersion() { return HttpVersion.HTTP_2; } - /** - * @see org.eclipse.jetty.http.HttpFieldPreEncoder#getEncodedField(org.eclipse.jetty.http.HttpHeader, java.lang.String, java.lang.String) - */ @Override public byte[] getEncodedField(HttpHeader header, String name, String value) { @@ -78,12 +74,12 @@ int nameIdx = HpackContext.staticIndex(header); if (nameIdx > 0) - NBitInteger.encode(buffer, bits, nameIdx); + NBitIntegerEncoder.encode(buffer, bits, nameIdx); else { buffer.put((byte)0x80); - NBitInteger.encode(buffer, 7, Huffman.octetsNeededLC(name)); - Huffman.encodeLC(buffer, name); + NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeededLowerCase(name)); + HuffmanEncoder.encodeLowerCase(buffer, name); } HpackEncoder.encodeValue(buffer, huffman, value); diff -Nru jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java --- jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,551 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.http2.hpack; - -import java.nio.ByteBuffer; - -import org.eclipse.jetty.util.Utf8StringBuilder; - -public class Huffman -{ - - // Appendix C: Huffman Codes - // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#appendix-C - static final int[][] CODES = - { - /* ( 0) |11111111|11000 */ {0x1ff8, 13}, - /* ( 1) |11111111|11111111|1011000 */ {0x7fffd8, 23}, - /* ( 2) |11111111|11111111|11111110|0010 */ {0xfffffe2, 28}, - /* ( 3) |11111111|11111111|11111110|0011 */ {0xfffffe3, 28}, - /* ( 4) |11111111|11111111|11111110|0100 */ {0xfffffe4, 28}, - /* ( 5) |11111111|11111111|11111110|0101 */ {0xfffffe5, 28}, - /* ( 6) |11111111|11111111|11111110|0110 */ {0xfffffe6, 28}, - /* ( 7) |11111111|11111111|11111110|0111 */ {0xfffffe7, 28}, - /* ( 8) |11111111|11111111|11111110|1000 */ {0xfffffe8, 28}, - /* ( 9) |11111111|11111111|11101010 */ {0xffffea, 24}, - /* ( 10) |11111111|11111111|11111111|111100 */ {0x3ffffffc, 30}, - /* ( 11) |11111111|11111111|11111110|1001 */ {0xfffffe9, 28}, - /* ( 12) |11111111|11111111|11111110|1010 */ {0xfffffea, 28}, - /* ( 13) |11111111|11111111|11111111|111101 */ {0x3ffffffd, 30}, - /* ( 14) |11111111|11111111|11111110|1011 */ {0xfffffeb, 28}, - /* ( 15) |11111111|11111111|11111110|1100 */ {0xfffffec, 28}, - /* ( 16) |11111111|11111111|11111110|1101 */ {0xfffffed, 28}, - /* ( 17) |11111111|11111111|11111110|1110 */ {0xfffffee, 28}, - /* ( 18) |11111111|11111111|11111110|1111 */ {0xfffffef, 28}, - /* ( 19) |11111111|11111111|11111111|0000 */ {0xffffff0, 28}, - /* ( 20) |11111111|11111111|11111111|0001 */ {0xffffff1, 28}, - /* ( 21) |11111111|11111111|11111111|0010 */ {0xffffff2, 28}, - /* ( 22) |11111111|11111111|11111111|111110 */ {0x3ffffffe, 30}, - /* ( 23) |11111111|11111111|11111111|0011 */ {0xffffff3, 28}, - /* ( 24) |11111111|11111111|11111111|0100 */ {0xffffff4, 28}, - /* ( 25) |11111111|11111111|11111111|0101 */ {0xffffff5, 28}, - /* ( 26) |11111111|11111111|11111111|0110 */ {0xffffff6, 28}, - /* ( 27) |11111111|11111111|11111111|0111 */ {0xffffff7, 28}, - /* ( 28) |11111111|11111111|11111111|1000 */ {0xffffff8, 28}, - /* ( 29) |11111111|11111111|11111111|1001 */ {0xffffff9, 28}, - /* ( 30) |11111111|11111111|11111111|1010 */ {0xffffffa, 28}, - /* ( 31) |11111111|11111111|11111111|1011 */ {0xffffffb, 28}, - /*' ' ( 32) |010100 */ {0x14, 6}, - /*'!' ( 33) |11111110|00 */ {0x3f8, 10}, - /*'"' ( 34) |11111110|01 */ {0x3f9, 10}, - /*'#' ( 35) |11111111|1010 */ {0xffa, 12}, - /*'$' ( 36) |11111111|11001 */ {0x1ff9, 13}, - /*'%' ( 37) |010101 */ {0x15, 6}, - /*'&' ( 38) |11111000 */ {0xf8, 8}, - /*''' ( 39) |11111111|010 */ {0x7fa, 11}, - /*'(' ( 40) |11111110|10 */ {0x3fa, 10}, - /*')' ( 41) |11111110|11 */ {0x3fb, 10}, - /*'*' ( 42) |11111001 */ {0xf9, 8}, - /*'+' ( 43) |11111111|011 */ {0x7fb, 11}, - /*',' ( 44) |11111010 */ {0xfa, 8}, - /*'-' ( 45) |010110 */ {0x16, 6}, - /*'.' ( 46) |010111 */ {0x17, 6}, - /*'/' ( 47) |011000 */ {0x18, 6}, - /*'0' ( 48) |00000 */ {0x0, 5}, - /*'1' ( 49) |00001 */ {0x1, 5}, - /*'2' ( 50) |00010 */ {0x2, 5}, - /*'3' ( 51) |011001 */ {0x19, 6}, - /*'4' ( 52) |011010 */ {0x1a, 6}, - /*'5' ( 53) |011011 */ {0x1b, 6}, - /*'6' ( 54) |011100 */ {0x1c, 6}, - /*'7' ( 55) |011101 */ {0x1d, 6}, - /*'8' ( 56) |011110 */ {0x1e, 6}, - /*'9' ( 57) |011111 */ {0x1f, 6}, - /*':' ( 58) |1011100 */ {0x5c, 7}, - /*';' ( 59) |11111011 */ {0xfb, 8}, - /*'<' ( 60) |11111111|1111100 */ {0x7ffc, 15}, - /*'=' ( 61) |100000 */ {0x20, 6}, - /*'>' ( 62) |11111111|1011 */ {0xffb, 12}, - /*'?' ( 63) |11111111|00 */ {0x3fc, 10}, - /*'@' ( 64) |11111111|11010 */ {0x1ffa, 13}, - /*'A' ( 65) |100001 */ {0x21, 6}, - /*'B' ( 66) |1011101 */ {0x5d, 7}, - /*'C' ( 67) |1011110 */ {0x5e, 7}, - /*'D' ( 68) |1011111 */ {0x5f, 7}, - /*'E' ( 69) |1100000 */ {0x60, 7}, - /*'F' ( 70) |1100001 */ {0x61, 7}, - /*'G' ( 71) |1100010 */ {0x62, 7}, - /*'H' ( 72) |1100011 */ {0x63, 7}, - /*'I' ( 73) |1100100 */ {0x64, 7}, - /*'J' ( 74) |1100101 */ {0x65, 7}, - /*'K' ( 75) |1100110 */ {0x66, 7}, - /*'L' ( 76) |1100111 */ {0x67, 7}, - /*'M' ( 77) |1101000 */ {0x68, 7}, - /*'N' ( 78) |1101001 */ {0x69, 7}, - /*'O' ( 79) |1101010 */ {0x6a, 7}, - /*'P' ( 80) |1101011 */ {0x6b, 7}, - /*'Q' ( 81) |1101100 */ {0x6c, 7}, - /*'R' ( 82) |1101101 */ {0x6d, 7}, - /*'S' ( 83) |1101110 */ {0x6e, 7}, - /*'T' ( 84) |1101111 */ {0x6f, 7}, - /*'U' ( 85) |1110000 */ {0x70, 7}, - /*'V' ( 86) |1110001 */ {0x71, 7}, - /*'W' ( 87) |1110010 */ {0x72, 7}, - /*'X' ( 88) |11111100 */ {0xfc, 8}, - /*'Y' ( 89) |1110011 */ {0x73, 7}, - /*'Z' ( 90) |11111101 */ {0xfd, 8}, - /*'[' ( 91) |11111111|11011 */ {0x1ffb, 13}, - /*'\' ( 92) |11111111|11111110|000 */ {0x7fff0, 19}, - /*']' ( 93) |11111111|11100 */ {0x1ffc, 13}, - /*'^' ( 94) |11111111|111100 */ {0x3ffc, 14}, - /*'_' ( 95) |100010 */ {0x22, 6}, - /*'`' ( 96) |11111111|1111101 */ {0x7ffd, 15}, - /*'a' ( 97) |00011 */ {0x3, 5}, - /*'b' ( 98) |100011 */ {0x23, 6}, - /*'c' ( 99) |00100 */ {0x4, 5}, - /*'d' (100) |100100 */ {0x24, 6}, - /*'e' (101) |00101 */ {0x5, 5}, - /*'f' (102) |100101 */ {0x25, 6}, - /*'g' (103) |100110 */ {0x26, 6}, - /*'h' (104) |100111 */ {0x27, 6}, - /*'i' (105) |00110 */ {0x6, 5}, - /*'j' (106) |1110100 */ {0x74, 7}, - /*'k' (107) |1110101 */ {0x75, 7}, - /*'l' (108) |101000 */ {0x28, 6}, - /*'m' (109) |101001 */ {0x29, 6}, - /*'n' (110) |101010 */ {0x2a, 6}, - /*'o' (111) |00111 */ {0x7, 5}, - /*'p' (112) |101011 */ {0x2b, 6}, - /*'q' (113) |1110110 */ {0x76, 7}, - /*'r' (114) |101100 */ {0x2c, 6}, - /*'s' (115) |01000 */ {0x8, 5}, - /*'t' (116) |01001 */ {0x9, 5}, - /*'u' (117) |101101 */ {0x2d, 6}, - /*'v' (118) |1110111 */ {0x77, 7}, - /*'w' (119) |1111000 */ {0x78, 7}, - /*'x' (120) |1111001 */ {0x79, 7}, - /*'y' (121) |1111010 */ {0x7a, 7}, - /*'z' (122) |1111011 */ {0x7b, 7}, - /*'{' (123) |11111111|1111110 */ {0x7ffe, 15}, - /*'|' (124) |11111111|100 */ {0x7fc, 11}, - /*'}' (125) |11111111|111101 */ {0x3ffd, 14}, - /*'~' (126) |11111111|11101 */ {0x1ffd, 13}, - /* (127) |11111111|11111111|11111111|1100 */ {0xffffffc, 28}, - /* (128) |11111111|11111110|0110 */ {0xfffe6, 20}, - /* (129) |11111111|11111111|010010 */ {0x3fffd2, 22}, - /* (130) |11111111|11111110|0111 */ {0xfffe7, 20}, - /* (131) |11111111|11111110|1000 */ {0xfffe8, 20}, - /* (132) |11111111|11111111|010011 */ {0x3fffd3, 22}, - /* (133) |11111111|11111111|010100 */ {0x3fffd4, 22}, - /* (134) |11111111|11111111|010101 */ {0x3fffd5, 22}, - /* (135) |11111111|11111111|1011001 */ {0x7fffd9, 23}, - /* (136) |11111111|11111111|010110 */ {0x3fffd6, 22}, - /* (137) |11111111|11111111|1011010 */ {0x7fffda, 23}, - /* (138) |11111111|11111111|1011011 */ {0x7fffdb, 23}, - /* (139) |11111111|11111111|1011100 */ {0x7fffdc, 23}, - /* (140) |11111111|11111111|1011101 */ {0x7fffdd, 23}, - /* (141) |11111111|11111111|1011110 */ {0x7fffde, 23}, - /* (142) |11111111|11111111|11101011 */ {0xffffeb, 24}, - /* (143) |11111111|11111111|1011111 */ {0x7fffdf, 23}, - /* (144) |11111111|11111111|11101100 */ {0xffffec, 24}, - /* (145) |11111111|11111111|11101101 */ {0xffffed, 24}, - /* (146) |11111111|11111111|010111 */ {0x3fffd7, 22}, - /* (147) |11111111|11111111|1100000 */ {0x7fffe0, 23}, - /* (148) |11111111|11111111|11101110 */ {0xffffee, 24}, - /* (149) |11111111|11111111|1100001 */ {0x7fffe1, 23}, - /* (150) |11111111|11111111|1100010 */ {0x7fffe2, 23}, - /* (151) |11111111|11111111|1100011 */ {0x7fffe3, 23}, - /* (152) |11111111|11111111|1100100 */ {0x7fffe4, 23}, - /* (153) |11111111|11111110|11100 */ {0x1fffdc, 21}, - /* (154) |11111111|11111111|011000 */ {0x3fffd8, 22}, - /* (155) |11111111|11111111|1100101 */ {0x7fffe5, 23}, - /* (156) |11111111|11111111|011001 */ {0x3fffd9, 22}, - /* (157) |11111111|11111111|1100110 */ {0x7fffe6, 23}, - /* (158) |11111111|11111111|1100111 */ {0x7fffe7, 23}, - /* (159) |11111111|11111111|11101111 */ {0xffffef, 24}, - /* (160) |11111111|11111111|011010 */ {0x3fffda, 22}, - /* (161) |11111111|11111110|11101 */ {0x1fffdd, 21}, - /* (162) |11111111|11111110|1001 */ {0xfffe9, 20}, - /* (163) |11111111|11111111|011011 */ {0x3fffdb, 22}, - /* (164) |11111111|11111111|011100 */ {0x3fffdc, 22}, - /* (165) |11111111|11111111|1101000 */ {0x7fffe8, 23}, - /* (166) |11111111|11111111|1101001 */ {0x7fffe9, 23}, - /* (167) |11111111|11111110|11110 */ {0x1fffde, 21}, - /* (168) |11111111|11111111|1101010 */ {0x7fffea, 23}, - /* (169) |11111111|11111111|011101 */ {0x3fffdd, 22}, - /* (170) |11111111|11111111|011110 */ {0x3fffde, 22}, - /* (171) |11111111|11111111|11110000 */ {0xfffff0, 24}, - /* (172) |11111111|11111110|11111 */ {0x1fffdf, 21}, - /* (173) |11111111|11111111|011111 */ {0x3fffdf, 22}, - /* (174) |11111111|11111111|1101011 */ {0x7fffeb, 23}, - /* (175) |11111111|11111111|1101100 */ {0x7fffec, 23}, - /* (176) |11111111|11111111|00000 */ {0x1fffe0, 21}, - /* (177) |11111111|11111111|00001 */ {0x1fffe1, 21}, - /* (178) |11111111|11111111|100000 */ {0x3fffe0, 22}, - /* (179) |11111111|11111111|00010 */ {0x1fffe2, 21}, - /* (180) |11111111|11111111|1101101 */ {0x7fffed, 23}, - /* (181) |11111111|11111111|100001 */ {0x3fffe1, 22}, - /* (182) |11111111|11111111|1101110 */ {0x7fffee, 23}, - /* (183) |11111111|11111111|1101111 */ {0x7fffef, 23}, - /* (184) |11111111|11111110|1010 */ {0xfffea, 20}, - /* (185) |11111111|11111111|100010 */ {0x3fffe2, 22}, - /* (186) |11111111|11111111|100011 */ {0x3fffe3, 22}, - /* (187) |11111111|11111111|100100 */ {0x3fffe4, 22}, - /* (188) |11111111|11111111|1110000 */ {0x7ffff0, 23}, - /* (189) |11111111|11111111|100101 */ {0x3fffe5, 22}, - /* (190) |11111111|11111111|100110 */ {0x3fffe6, 22}, - /* (191) |11111111|11111111|1110001 */ {0x7ffff1, 23}, - /* (192) |11111111|11111111|11111000|00 */ {0x3ffffe0, 26}, - /* (193) |11111111|11111111|11111000|01 */ {0x3ffffe1, 26}, - /* (194) |11111111|11111110|1011 */ {0xfffeb, 20}, - /* (195) |11111111|11111110|001 */ {0x7fff1, 19}, - /* (196) |11111111|11111111|100111 */ {0x3fffe7, 22}, - /* (197) |11111111|11111111|1110010 */ {0x7ffff2, 23}, - /* (198) |11111111|11111111|101000 */ {0x3fffe8, 22}, - /* (199) |11111111|11111111|11110110|0 */ {0x1ffffec, 25}, - /* (200) |11111111|11111111|11111000|10 */ {0x3ffffe2, 26}, - /* (201) |11111111|11111111|11111000|11 */ {0x3ffffe3, 26}, - /* (202) |11111111|11111111|11111001|00 */ {0x3ffffe4, 26}, - /* (203) |11111111|11111111|11111011|110 */ {0x7ffffde, 27}, - /* (204) |11111111|11111111|11111011|111 */ {0x7ffffdf, 27}, - /* (205) |11111111|11111111|11111001|01 */ {0x3ffffe5, 26}, - /* (206) |11111111|11111111|11110001 */ {0xfffff1, 24}, - /* (207) |11111111|11111111|11110110|1 */ {0x1ffffed, 25}, - /* (208) |11111111|11111110|010 */ {0x7fff2, 19}, - /* (209) |11111111|11111111|00011 */ {0x1fffe3, 21}, - /* (210) |11111111|11111111|11111001|10 */ {0x3ffffe6, 26}, - /* (211) |11111111|11111111|11111100|000 */ {0x7ffffe0, 27}, - /* (212) |11111111|11111111|11111100|001 */ {0x7ffffe1, 27}, - /* (213) |11111111|11111111|11111001|11 */ {0x3ffffe7, 26}, - /* (214) |11111111|11111111|11111100|010 */ {0x7ffffe2, 27}, - /* (215) |11111111|11111111|11110010 */ {0xfffff2, 24}, - /* (216) |11111111|11111111|00100 */ {0x1fffe4, 21}, - /* (217) |11111111|11111111|00101 */ {0x1fffe5, 21}, - /* (218) |11111111|11111111|11111010|00 */ {0x3ffffe8, 26}, - /* (219) |11111111|11111111|11111010|01 */ {0x3ffffe9, 26}, - /* (220) |11111111|11111111|11111111|1101 */ {0xffffffd, 28}, - /* (221) |11111111|11111111|11111100|011 */ {0x7ffffe3, 27}, - /* (222) |11111111|11111111|11111100|100 */ {0x7ffffe4, 27}, - /* (223) |11111111|11111111|11111100|101 */ {0x7ffffe5, 27}, - /* (224) |11111111|11111110|1100 */ {0xfffec, 20}, - /* (225) |11111111|11111111|11110011 */ {0xfffff3, 24}, - /* (226) |11111111|11111110|1101 */ {0xfffed, 20}, - /* (227) |11111111|11111111|00110 */ {0x1fffe6, 21}, - /* (228) |11111111|11111111|101001 */ {0x3fffe9, 22}, - /* (229) |11111111|11111111|00111 */ {0x1fffe7, 21}, - /* (230) |11111111|11111111|01000 */ {0x1fffe8, 21}, - /* (231) |11111111|11111111|1110011 */ {0x7ffff3, 23}, - /* (232) |11111111|11111111|101010 */ {0x3fffea, 22}, - /* (233) |11111111|11111111|101011 */ {0x3fffeb, 22}, - /* (234) |11111111|11111111|11110111|0 */ {0x1ffffee, 25}, - /* (235) |11111111|11111111|11110111|1 */ {0x1ffffef, 25}, - /* (236) |11111111|11111111|11110100 */ {0xfffff4, 24}, - /* (237) |11111111|11111111|11110101 */ {0xfffff5, 24}, - /* (238) |11111111|11111111|11111010|10 */ {0x3ffffea, 26}, - /* (239) |11111111|11111111|1110100 */ {0x7ffff4, 23}, - /* (240) |11111111|11111111|11111010|11 */ {0x3ffffeb, 26}, - /* (241) |11111111|11111111|11111100|110 */ {0x7ffffe6, 27}, - /* (242) |11111111|11111111|11111011|00 */ {0x3ffffec, 26}, - /* (243) |11111111|11111111|11111011|01 */ {0x3ffffed, 26}, - /* (244) |11111111|11111111|11111100|111 */ {0x7ffffe7, 27}, - /* (245) |11111111|11111111|11111101|000 */ {0x7ffffe8, 27}, - /* (246) |11111111|11111111|11111101|001 */ {0x7ffffe9, 27}, - /* (247) |11111111|11111111|11111101|010 */ {0x7ffffea, 27}, - /* (248) |11111111|11111111|11111101|011 */ {0x7ffffeb, 27}, - /* (249) |11111111|11111111|11111111|1110 */ {0xffffffe, 28}, - /* (250) |11111111|11111111|11111101|100 */ {0x7ffffec, 27}, - /* (251) |11111111|11111111|11111101|101 */ {0x7ffffed, 27}, - /* (252) |11111111|11111111|11111101|110 */ {0x7ffffee, 27}, - /* (253) |11111111|11111111|11111101|111 */ {0x7ffffef, 27}, - /* (254) |11111111|11111111|11111110|000 */ {0x7fffff0, 27}, - /* (255) |11111111|11111111|11111011|10 */ {0x3ffffee, 26}, - /*EOS (256) |11111111|11111111|11111111|111111 */ {0x3fffffff, 30} - }; - - static final int[][] LCCODES = new int[CODES.length][]; - static final char EOS = 256; - - // Huffman decode tree stored in a flattened char array for good - // locality of reference. - static final char[] tree; - static final char[] rowsym; - static final byte[] rowbits; - - // Build the Huffman lookup tree and LC TABLE - static - { - System.arraycopy(CODES, 0, LCCODES, 0, CODES.length); - for (int i = 'A'; i <= 'Z'; i++) - { - LCCODES[i] = LCCODES['a' + i - 'A']; - } - - int r = 0; - for (int i = 0; i < CODES.length; i++) - { - r += (CODES[i][1] + 7) / 8; - } - tree = new char[r * 256]; - rowsym = new char[r]; - rowbits = new byte[r]; - - r = 0; - for (int sym = 0; sym < CODES.length; sym++) - { - int code = CODES[sym][0]; - int len = CODES[sym][1]; - - int current = 0; - - while (len > 8) - { - len -= 8; - int i = ((code >>> len) & 0xFF); - - int t = current * 256 + i; - current = tree[t]; - if (current == 0) - { - tree[t] = (char)++r; - current = r; - } - } - - int terminal = ++r; - rowsym[r] = (char)sym; - int b = len & 0x07; - int terminalBits = b == 0 ? 8 : b; - - rowbits[r] = (byte)terminalBits; - int shift = 8 - len; - int start = current * 256 + ((code << shift) & 0xFF); - int end = start + (1 << shift); - for (int i = start; i < end; i++) - { - tree[i] = (char)terminal; - } - } - } - - public static String decode(ByteBuffer buffer) throws HpackException.CompressionException - { - return decode(buffer, buffer.remaining()); - } - - public static String decode(ByteBuffer buffer, int length) throws HpackException.CompressionException - { - Utf8StringBuilder utf8 = new Utf8StringBuilder(length * 2); - int node = 0; - int current = 0; - int bits = 0; - - for (int i = 0; i < length; i++) - { - int b = buffer.get() & 0xFF; - current = (current << 8) | b; - bits += 8; - while (bits >= 8) - { - int c = (current >>> (bits - 8)) & 0xFF; - node = tree[node * 256 + c]; - if (rowbits[node] != 0) - { - if (rowsym[node] == EOS) - throw new HpackException.CompressionException("EOS in content"); - - // terminal node - utf8.append((byte)(0xFF & rowsym[node])); - bits -= rowbits[node]; - node = 0; - } - else - { - // non-terminal node - bits -= 8; - } - } - } - - while (bits > 0) - { - int c = (current << (8 - bits)) & 0xFF; - int lastNode = node; - node = tree[node * 256 + c]; - - if (rowbits[node] == 0 || rowbits[node] > bits) - { - int requiredPadding = 0; - for (int i = 0; i < bits; i++) - { - requiredPadding = (requiredPadding << 1) | 1; - } - - if ((c >> (8 - bits)) != requiredPadding) - throw new HpackException.CompressionException("Incorrect padding"); - - node = lastNode; - break; - } - - utf8.append((byte)(0xFF & rowsym[node])); - bits -= rowbits[node]; - node = 0; - } - - if (node != 0) - throw new HpackException.CompressionException("Bad termination"); - - return utf8.toString(); - } - - public static int octetsNeeded(String s) - { - return octetsNeeded(CODES, s); - } - - public static int octetsNeeded(byte[] b) - { - return octetsNeeded(CODES, b); - } - - public static void encode(ByteBuffer buffer, String s) - { - encode(CODES, buffer, s); - } - - public static void encode(ByteBuffer buffer, byte[] b) - { - encode(CODES, buffer, b); - } - - public static int octetsNeededLC(String s) - { - return octetsNeeded(LCCODES, s); - } - - public static void encodeLC(ByteBuffer buffer, String s) - { - encode(LCCODES, buffer, s); - } - - private static int octetsNeeded(final int[][] table, String s) - { - int needed = 0; - int len = s.length(); - for (int i = 0; i < len; i++) - { - char c = s.charAt(i); - if (c >= 128 || c < ' ') - return -1; - needed += table[c][1]; - } - - return (needed + 7) / 8; - } - - private static int octetsNeeded(final int[][] table, byte[] b) - { - int needed = 0; - int len = b.length; - for (int i = 0; i < len; i++) - { - int c = 0xFF & b[i]; - needed += table[c][1]; - } - return (needed + 7) / 8; - } - - /** - * @param table The table to encode by - * @param buffer The buffer to encode to - * @param s The string to encode - */ - private static void encode(final int[][] table, ByteBuffer buffer, String s) - { - long current = 0; - int n = 0; - int len = s.length(); - for (int i = 0; i < len; i++) - { - char c = s.charAt(i); - if (c >= 128 || c < ' ') - throw new IllegalArgumentException(); - int code = table[c][0]; - int bits = table[c][1]; - - current <<= bits; - current |= code; - n += bits; - - while (n >= 8) - { - n -= 8; - buffer.put((byte)(current >> n)); - } - } - - if (n > 0) - { - current <<= (8 - n); - current |= (0xFF >>> n); - buffer.put((byte)(current)); - } - } - - private static void encode(final int[][] table, ByteBuffer buffer, byte[] b) - { - long current = 0; - int n = 0; - - int len = b.length; - for (int i = 0; i < len; i++) - { - int c = 0xFF & b[i]; - int code = table[c][0]; - int bits = table[c][1]; - - current <<= bits; - current |= code; - n += bits; - - while (n >= 8) - { - n -= 8; - buffer.put((byte)(current >> n)); - } - } - - if (n > 0) - { - current <<= (8 - n); - current |= (0xFF >>> n); - buffer.put((byte)(current)); - } - } -} diff -Nru jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java --- jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java 2024-12-19 21:51:26.000000000 +0000 @@ -29,7 +29,7 @@ public class MetaDataBuilder { - private final int _maxSize; + private int _maxSize; private int _size; private Integer _status; private String _method; @@ -60,6 +60,11 @@ return _maxSize; } + public void setMaxSize(int maxSize) + { + _maxSize = maxSize; + } + /** * Get the size. * @@ -70,17 +75,18 @@ return _size; } - public void emit(HttpField field) throws HpackException.SessionException + public void emit(HttpField field) throws SessionException { HttpHeader header = field.getHeader(); String name = field.getName(); - if (name == null || name.length() == 0) - throw new HpackException.SessionException("Header size 0"); + if (name == null || name.isEmpty()) + throw new SessionException("Header size 0"); String value = field.getValue(); int fieldSize = name.length() + (value == null ? 0 : value.length()); _size += fieldSize + 32; - if (_size > _maxSize) - throw new HpackException.SessionException("Header size %d > %d", _size, _maxSize); + int maxSize = getMaxSize(); + if (maxSize > 0 && _size > maxSize) + throw new SessionException("Header size %d > %d", _size, maxSize); if (field instanceof StaticTableHttpField) { @@ -89,7 +95,7 @@ { case C_STATUS: if (checkPseudoHeader(header, _status)) - _status = (Integer)staticField.getStaticValue(); + _status = staticField.getIntValue(); _response = true; break; @@ -157,7 +163,7 @@ case C_PATH: if (checkPseudoHeader(header, _path)) { - if (value != null && value.length() > 0) + if (value != null && !value.isEmpty()) _path = value; else streamException("No Path"); @@ -201,7 +207,7 @@ } } - protected void streamException(String messageFormat, Object... args) + public void streamException(String messageFormat, Object... args) { HpackException.StreamException stream = new HpackException.StreamException(messageFormat, args); if (_streamException == null) @@ -267,23 +273,7 @@ _authority = null; _path = null; _size = 0; - _contentLength = Long.MIN_VALUE; + _contentLength = -1; } } - - /** - * Check that the max size will not be exceeded. - * - * @param length the length - * @param huffman the huffman name - * @throws SessionException in case of size errors - */ - public void checkSize(int length, boolean huffman) throws SessionException - { - // Apply a huffman fudge factor - if (huffman) - length = (length * 4) / 3; - if ((_size + length) > _maxSize) - throw new HpackException.SessionException("Header too large %d > %d", _size + length, _maxSize); - } } diff -Nru jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/NBitInteger.java jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/NBitInteger.java --- jetty9-9.4.50/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/NBitInteger.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/NBitInteger.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.http2.hpack; - -import java.nio.ByteBuffer; - -public class NBitInteger -{ - public static int octectsNeeded(int n, int i) - { - if (n == 8) - { - int nbits = 0xFF; - i = i - nbits; - if (i < 0) - return 1; - if (i == 0) - return 2; - int lz = Integer.numberOfLeadingZeros(i); - int log = 32 - lz; - return 1 + (log + 6) / 7; - } - - int nbits = 0xFF >>> (8 - n); - i = i - nbits; - if (i < 0) - return 0; - if (i == 0) - return 1; - int lz = Integer.numberOfLeadingZeros(i); - int log = 32 - lz; - return (log + 6) / 7; - } - - public static void encode(ByteBuffer buf, int n, int i) - { - if (n == 8) - { - if (i < 0xFF) - { - buf.put((byte)i); - } - else - { - buf.put((byte)0xFF); - - int length = i - 0xFF; - while (true) - { - if ((length & ~0x7F) == 0) - { - buf.put((byte)length); - return; - } - else - { - buf.put((byte)((length & 0x7F) | 0x80)); - length >>>= 7; - } - } - } - } - else - { - int p = buf.position() - 1; - int bits = 0xFF >>> (8 - n); - - if (i < bits) - { - buf.put(p, (byte)((buf.get(p) & ~bits) | i)); - } - else - { - buf.put(p, (byte)(buf.get(p) | bits)); - - int length = i - bits; - while (true) - { - if ((length & ~0x7F) == 0) - { - buf.put((byte)length); - return; - } - else - { - buf.put((byte)((length & 0x7F) | 0x80)); - length >>>= 7; - } - } - } - } - } - - public static int decode(ByteBuffer buffer, int n) - { - if (n == 8) - { - int nbits = 0xFF; - - int i = buffer.get() & 0xff; - - if (i == nbits) - { - int m = 1; - int b; - do - { - b = 0xff & buffer.get(); - i = i + (b & 127) * m; - m = m * 128; - } - while ((b & 128) == 128); - } - return i; - } - - int nbits = 0xFF >>> (8 - n); - - int i = buffer.get(buffer.position() - 1) & nbits; - - if (i == nbits) - { - int m = 1; - int b; - do - { - b = 0xff & buffer.get(); - i = i + (b & 127) * m; - m = m * 128; - } - while ((b & 128) == 128); - } - return i; - } -} diff -Nru jetty9-9.4.50/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackContextTest.java jetty9-9.4.57/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackContextTest.java --- jetty9-9.4.50/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackContextTest.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackContextTest.java 2024-12-19 21:51:26.000000000 +0000 @@ -21,6 +21,9 @@ import java.nio.ByteBuffer; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.compression.EncodingException; +import org.eclipse.jetty.http.compression.HuffmanDecoder; +import org.eclipse.jetty.http.compression.NBitIntegerDecoder; import org.eclipse.jetty.http2.hpack.HpackContext.Entry; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; @@ -37,6 +40,32 @@ */ public class HpackContextTest { + public static String decode(ByteBuffer buffer, int length) throws EncodingException + { + HuffmanDecoder huffmanDecoder = new HuffmanDecoder(); + huffmanDecoder.setLength(length); + String decoded = huffmanDecoder.decode(buffer); + if (decoded == null) + throw new EncodingException("invalid string encoding"); + + huffmanDecoder.reset(); + return decoded; + } + + public static int decodeInt(ByteBuffer buffer, int prefix) throws EncodingException + { + // This is a fix for HPACK as it already takes the first byte of the encoded integer. + if (prefix != 8) + buffer.position(buffer.position() - 1); + + NBitIntegerDecoder decoder = new NBitIntegerDecoder(); + decoder.setPrefix(prefix); + int decodedInt = decoder.decodeInt(buffer); + if (decodedInt < 0) + throw new EncodingException("invalid integer encoding"); + decoder.reset(); + return decodedInt; + } @Test public void testStaticName() @@ -428,10 +457,10 @@ int huff = 0xff & buffer.get(); assertTrue((0x80 & huff) == 0x80); - int len = NBitInteger.decode(buffer, 7); + int len = decodeInt(buffer, 7); assertEquals(len, buffer.remaining()); - String value = Huffman.decode(buffer); + String value = decode(buffer, buffer.remaining()); assertEquals(entry.getHttpField().getValue(), value); } diff -Nru jetty9-9.4.50/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java jetty9-9.4.57/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java --- jetty9-9.4.50/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java 2024-12-19 21:51:26.000000000 +0000 @@ -62,7 +62,7 @@ @Test public void testDecodeD3() throws Exception { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); // First request String encoded = "828684410f7777772e6578616d706c652e636f6d"; @@ -110,7 +110,7 @@ @Test public void testDecodeD4() throws Exception { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); // First request String encoded = "828684418cf1e3c2e5f23a6ba0ab90f4ff"; @@ -145,7 +145,7 @@ { String value = "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "8682418cF1E3C2E5F23a6bA0Ab90F4Ff841f0822426173696320515778685a475270626a70766347567549484e6c633246745a513d3d"; byte[] bytes = TypeUtil.fromHexString(encoded); byte[] array = new byte[bytes.length + 1]; @@ -167,7 +167,7 @@ @Test public void testDecodeHuffmanWithArrayOffset() throws Exception { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "8286418cf1e3c2e5f23a6ba0ab90f4ff84"; byte[] bytes = TypeUtil.fromHexString(encoded); @@ -191,7 +191,7 @@ String encoded = "886196C361Be940b6a65B6850400B8A00571972e080a62D1Bf5f87497cA589D34d1f9a0f0d0234327690Aa69D29aFcA954D3A5358980Ae112e0f7c880aE152A9A74a6bF3"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); MetaData.Response response = (MetaData.Response)decoder.decode(buffer); assertThat(response.getStatus(), is(200)); @@ -209,7 +209,7 @@ { String encoded = "203f136687A0E41d139d090760881c6490B2Cd39Ba7f"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); MetaData metaData = decoder.decode(buffer); assertThat(metaData.getFields().get(HttpHeader.HOST), is("localhost0")); assertThat(metaData.getFields().get(HttpHeader.COOKIE), is("abcdefghij")); @@ -231,7 +231,7 @@ String encoded = "203f136687A0E41d139d090760881c6490B2Cd39Ba7f20"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); try { decoder.decode(buffer); @@ -249,7 +249,8 @@ String encoded = "3f610f17FfEc02Df3990A190A0D4Ee5b3d2940Ec98Aa4a62D127D29e273a0aA20dEcAa190a503b262d8a2671D4A2672a927aA874988a2471D05510750c951139EdA2452a3a548cAa1aA90bE4B228342864A9E0D450A5474a92992a1aA513395448E3A0Aa17B96cFe3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f14E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F3E7Cf9f3e7cF9F353F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F54f"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - HpackDecoder decoder = new HpackDecoder(128, 8192); + HpackDecoder decoder = new HpackDecoder(8192); + decoder.setMaxTableCapacity(128); MetaData metaData = decoder.decode(buffer); assertThat(decoder.getHpackContext().getDynamicTableSize(), is(0)); @@ -262,7 +263,8 @@ String encoded = "BE"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); - HpackDecoder decoder = new HpackDecoder(128, 8192); + HpackDecoder decoder = new HpackDecoder(8192); + decoder.setMaxTableCapacity(128); try { @@ -447,7 +449,7 @@ @Test public void testHuffmanEncodedStandard() throws Exception { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "82868441" + "83" + "49509F"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); @@ -465,68 +467,68 @@ @Test public void testHuffmanEncodedExtraPadding() { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "82868441" + "84" + "49509FFF"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer)); - assertThat(ex.getMessage(), Matchers.containsString("Bad termination")); + assertThat(ex.getMessage(), Matchers.containsString("bad_termination")); } /* 5.2.2: Sends a Huffman-encoded string literal representation padded by zero */ @Test public void testHuffmanEncodedZeroPadding() { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "82868441" + "83" + "495090"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer)); - assertThat(ex.getMessage(), Matchers.containsString("Incorrect padding")); + assertThat(ex.getMessage(), Matchers.containsString("incorrect_padding")); } /* 5.2.3: Sends a Huffman-encoded string literal representation containing the EOS symbol */ @Test public void testHuffmanEncodedWithEOS() { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "82868441" + "87" + "497FFFFFFF427F"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer)); - assertThat(ex.getMessage(), Matchers.containsString("EOS in content")); + assertThat(ex.getMessage(), Matchers.containsString("eos_in_content")); } @Test public void testHuffmanEncodedOneIncompleteOctet() { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "82868441" + "81" + "FE"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer)); - assertThat(ex.getMessage(), Matchers.containsString("Bad termination")); + assertThat(ex.getMessage(), Matchers.containsString("bad_termination")); } @Test public void testHuffmanEncodedTwoIncompleteOctet() { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "82868441" + "82" + "FFFE"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer)); - assertThat(ex.getMessage(), Matchers.containsString("Bad termination")); + assertThat(ex.getMessage(), Matchers.containsString("bad_termination")); } @Test public void testZeroLengthName() { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "00000130"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); @@ -537,7 +539,7 @@ @Test public void testZeroLengthValue() throws Exception { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "00016800"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); @@ -549,7 +551,7 @@ @Test public void testUpperCaseName() { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "0001480130"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); @@ -560,7 +562,7 @@ @Test public void testWhiteSpaceName() { - HpackDecoder decoder = new HpackDecoder(4096, 8192); + HpackDecoder decoder = new HpackDecoder(8192); String encoded = "0001200130"; ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); diff -Nru jetty9-9.4.50/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java jetty9-9.4.57/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java --- jetty9-9.4.50/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java 2024-12-19 21:51:26.000000000 +0000 @@ -38,7 +38,7 @@ @Test public void testUnknownFieldsContextManagement() throws Exception { - HpackEncoder encoder = new HpackEncoder(38 * 5); + HpackEncoder encoder = newHpackEncoder(38 * 5); HttpFields fields = new HttpFields(); HttpField[] field = @@ -149,8 +149,9 @@ @Test public void testLargeFieldsNotIndexed() { - HpackEncoder encoder = new HpackEncoder(38 * 5); + HpackEncoder encoder = newHpackEncoder(38 * 5); HpackContext ctx = encoder.getHpackContext(); + ctx.resize(encoder.getMaxTableCapacity()); ByteBuffer buffer = BufferUtil.allocate(4096); @@ -175,8 +176,9 @@ @Test public void testIndexContentLength() { - HpackEncoder encoder = new HpackEncoder(38 * 5); + HpackEncoder encoder = newHpackEncoder(38 * 5); HpackContext ctx = encoder.getHpackContext(); + ctx.resize(encoder.getMaxTableCapacity()); ByteBuffer buffer = BufferUtil.allocate(4096); @@ -197,7 +199,7 @@ @Test public void testNeverIndexSetCookie() throws Exception { - HpackEncoder encoder = new HpackEncoder(38 * 5); + HpackEncoder encoder = newHpackEncoder(38 * 5); ByteBuffer buffer = BufferUtil.allocate(4096); HttpFields fields = new HttpFields(); @@ -231,20 +233,20 @@ { HttpFields fields = new HttpFields(); - HpackEncoder encoder = new HpackEncoder(128); + HpackEncoder encoder = newHpackEncoder(128); ByteBuffer buffer0 = BufferUtil.allocate(4096); int pos = BufferUtil.flipToFill(buffer0); encoder.encode(buffer0, new MetaData(HttpVersion.HTTP_2, fields)); BufferUtil.flipToFlush(buffer0, pos); - encoder = new HpackEncoder(128); + encoder = newHpackEncoder(128); fields.add(new HttpField("user-agent", "jetty/test")); ByteBuffer buffer1 = BufferUtil.allocate(4096); pos = BufferUtil.flipToFill(buffer1); encoder.encode(buffer1, new MetaData(HttpVersion.HTTP_2, fields)); BufferUtil.flipToFlush(buffer1, pos); - encoder = new HpackEncoder(128); + encoder = newHpackEncoder(128); encoder.setValidateEncoding(false); fields.add(new HttpField(":path", "This is a very large field, whose size is larger than the dynamic table so it should not be indexed as it will not fit in the table ever!" + @@ -256,7 +258,7 @@ encoder.encode(buffer2, new MetaData(HttpVersion.HTTP_2, fields)); BufferUtil.flipToFlush(buffer2, pos); - encoder = new HpackEncoder(128); + encoder = newHpackEncoder(128); encoder.setValidateEncoding(false); fields.add(new HttpField("host", "somehost")); ByteBuffer buffer = BufferUtil.allocate(4096); @@ -297,12 +299,12 @@ fields.add("host", "localhost0"); fields.add("cookie", "abcdefghij"); - HpackEncoder encoder = new HpackEncoder(4096); + HpackEncoder encoder = newHpackEncoder(4096); ByteBuffer buffer = BufferUtil.allocate(4096); int pos = BufferUtil.flipToFill(buffer); encoder.encodeMaxDynamicTableSize(buffer, 0); - encoder.setRemoteMaxDynamicTableSize(50); + encoder.setTableCapacity(50); encoder.encode(buffer, new MetaData(HttpVersion.HTTP_2, fields)); BufferUtil.flipToFlush(buffer, pos); @@ -311,4 +313,12 @@ assertThat(context.getMaxDynamicTableSize(), Matchers.is(50)); assertThat(context.size(), Matchers.is(1)); } + + private static HpackEncoder newHpackEncoder(int tableCapacity) + { + HpackEncoder encoder = new HpackEncoder(); + encoder.setMaxTableCapacity(tableCapacity); + encoder.setTableCapacity(tableCapacity); + return encoder; + } } diff -Nru jetty9-9.4.50/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java jetty9-9.4.57/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java --- jetty9-9.4.50/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java 2024-12-19 21:51:26.000000000 +0000 @@ -37,7 +37,7 @@ public class HpackPerfTest { - int _maxDynamicTableSize = 4 * 1024; + int _tableCapacity = 4 * 1024; int _unencodedSize; int _encodedSize; @@ -51,7 +51,7 @@ @AfterEach public void after() { - System.err.printf("dynamictable=%d unencoded=%d encoded=%d p=%3.1f%%%n", _maxDynamicTableSize, _unencodedSize, _encodedSize, 100.0 * _encodedSize / _unencodedSize); + System.err.printf("dynamictable=%d unencoded=%d encoded=%d p=%3.1f%%%n", _tableCapacity, _unencodedSize, _encodedSize, 100.0 * _encodedSize / _unencodedSize); } @Test @@ -68,11 +68,14 @@ assertNotNull(files); // Parse JSON - Map[] stories = new Map[files.length]; + @SuppressWarnings("unchecked") + MapSets the limit for the encoder HPACK dynamic table capacity.
+ *Setting this value to {@code 0} disables the use of the dynamic table.
+ * + * @param maxEncoderTableCapacity The HPACK encoder dynamic table maximum capacity + */ + public void setMaxEncoderTableCapacity(int maxEncoderTableCapacity) + { + this.maxEncoderTableCapacity = maxEncoderTableCapacity; + } + + @ManagedAttribute("The HPACK decoder dynamic table maximum capacity") + public int getMaxDecoderTableCapacity() + { + return maxDecoderTableCapacity; + } + + public void setMaxDecoderTableCapacity(int maxDecoderTableCapacity) + { + this.maxDecoderTableCapacity = maxDecoderTableCapacity; } @ManagedAttribute("The initial size of session's flow control receive window") @@ -159,15 +191,28 @@ this.streamIdleTimeout = streamIdleTimeout; } + @Deprecated @ManagedAttribute("The max frame length in bytes") public int getMaxFrameLength() { - return maxFrameLength; + return getMaxFrameSize(); } + @Deprecated public void setMaxFrameLength(int maxFrameLength) { - this.maxFrameLength = maxFrameLength; + setMaxFrameSize(maxFrameLength); + } + + @ManagedAttribute("The max frame size in bytes") + public int getMaxFrameSize() + { + return maxFrameSize; + } + + public void setMaxFrameSize(int maxFrameSize) + { + this.maxFrameSize = maxFrameSize; } @ManagedAttribute("The max number of keys in all SETTINGS frames") @@ -267,37 +312,47 @@ { ServerSessionListener listener = newSessionListener(connector, endPoint); - Generator generator = new Generator(connector.getByteBufferPool(), getMaxDynamicTableSize(), getMaxHeaderBlockFragment()); + Generator generator = new Generator(connector.getByteBufferPool(), getMaxHeaderBlockFragment()); FlowControlStrategy flowControl = getFlowControlStrategyFactory().newFlowControlStrategy(); - HTTP2ServerSession session = new HTTP2ServerSession(connector.getScheduler(), endPoint, generator, listener, flowControl); + + ServerParser parser = newServerParser(connector, getRateControlFactory().newRateControl(endPoint)); + parser.setMaxFrameSize(getMaxFrameSize()); + parser.setMaxSettingsKeys(getMaxSettingsKeys()); + + HTTP2ServerSession session = new HTTP2ServerSession(connector.getScheduler(), endPoint, parser, generator, listener, flowControl); session.setMaxLocalStreams(getMaxConcurrentStreams()); session.setMaxRemoteStreams(getMaxConcurrentStreams()); + session.setMaxEncoderTableCapacity(getMaxEncoderTableCapacity()); // For a single stream in a connection, there will be a race between // the stream idle timeout and the connection idle timeout. However, // the typical case is that the connection will be busier and the // stream idle timeout will expire earlier than the connection's. long streamIdleTimeout = getStreamIdleTimeout(); - if (streamIdleTimeout <= 0) + if (streamIdleTimeout == 0) streamIdleTimeout = endPoint.getIdleTimeout(); session.setStreamIdleTimeout(streamIdleTimeout); session.setInitialSessionRecvWindow(getInitialSessionRecvWindow()); session.setWriteThreshold(getHttpConfiguration().getOutputBufferSize()); - ServerParser parser = newServerParser(connector, session, getRateControlFactory().newRateControl(endPoint)); - parser.setMaxFrameLength(getMaxFrameLength()); - parser.setMaxSettingsKeys(getMaxSettingsKeys()); - HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(), - endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener); + endPoint, httpConfiguration, session, getInputBufferSize(), listener); connection.addListener(sessionContainer); + parser.init(connection.wrapParserListener(session)); + return configure(connection, connector, endPoint); } protected abstract ServerSessionListener newSessionListener(Connector connector, EndPoint endPoint); + @Deprecated protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener, RateControl rateControl) { - return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize(), rateControl); + return newServerParser(connector, rateControl); + } + + protected ServerParser newServerParser(Connector connector, RateControl rateControl) + { + return new ServerParser(connector.getByteBufferPool(), getHttpConfiguration().getRequestHeaderSize(), rateControl); } @ManagedObject("The container of HTTP/2 sessions") diff -Nru jetty9-9.4.50/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java jetty9-9.4.57/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java --- jetty9-9.4.50/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java 2024-12-19 21:51:26.000000000 +0000 @@ -89,9 +89,15 @@ private final HttpConfiguration httpConfig; private boolean recycleHttpChannels = true; + @Deprecated public HTTP2ServerConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, HttpConfiguration httpConfig, ServerParser parser, ISession session, int inputBufferSize, ServerSessionListener listener) { - super(byteBufferPool, executor, endPoint, parser, session, inputBufferSize); + this(byteBufferPool, executor, endPoint, httpConfig, session, inputBufferSize, listener); + } + + public HTTP2ServerConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, HttpConfiguration httpConfig, ISession session, int inputBufferSize, ServerSessionListener listener) + { + super(byteBufferPool, executor, endPoint, session, inputBufferSize); this.listener = listener; this.httpConfig = httpConfig; } diff -Nru jetty9-9.4.50/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerSession.java jetty9-9.4.57/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerSession.java --- jetty9-9.4.50/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerSession.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerSession.java 2024-12-19 21:51:26.000000000 +0000 @@ -37,6 +37,7 @@ import org.eclipse.jetty.http2.frames.SettingsFrame; import org.eclipse.jetty.http2.frames.WindowUpdateFrame; import org.eclipse.jetty.http2.generator.Generator; +import org.eclipse.jetty.http2.parser.Parser; import org.eclipse.jetty.http2.parser.ServerParser; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.Callback; @@ -50,9 +51,16 @@ private final ServerSessionListener listener; + @Deprecated public HTTP2ServerSession(Scheduler scheduler, EndPoint endPoint, Generator generator, ServerSessionListener listener, FlowControlStrategy flowControl) { - super(scheduler, endPoint, generator, listener, flowControl, 2); + this(scheduler, endPoint, null, generator, listener, flowControl); + throw new UnsupportedOperationException(); + } + + public HTTP2ServerSession(Scheduler scheduler, EndPoint endPoint, Parser parser, Generator generator, ServerSessionListener listener, FlowControlStrategy flowControl) + { + super(scheduler, endPoint, parser, generator, listener, flowControl, 2); this.listener = listener; } @@ -104,10 +112,11 @@ { onStreamOpened(stream); stream.process(frame, Callback.NOOP); - if (stream.updateClose(frame.isEndStream(), CloseState.Event.RECEIVED)) - removeStream(stream); + boolean closed = stream.updateClose(frame.isEndStream(), CloseState.Event.RECEIVED); Stream.Listener listener = notifyNewStream(stream, frame); stream.setListener(listener); + if (closed) + removeStream(stream); } } } @@ -126,9 +135,10 @@ if (stream != null) { stream.process(frame, Callback.NOOP); - if (stream.updateClose(frame.isEndStream(), CloseState.Event.RECEIVED)) - removeStream(stream); + boolean closed = stream.updateClose(frame.isEndStream(), CloseState.Event.RECEIVED); notifyHeaders(stream, frame); + if (closed) + removeStream(stream); } else { diff -Nru jetty9-9.4.50/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java jetty9-9.4.57/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java --- jetty9-9.4.50/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java 2024-12-19 21:51:26.000000000 +0000 @@ -26,7 +26,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.UnaryOperator; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; @@ -92,7 +91,8 @@ output.write(BufferUtil.toArray(buffer)); } - Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter() + Parser parser = new Parser(byteBufferPool, 4096); + parser.init(new Parser.Listener.Adapter() { @Override public void onHeaders(HeadersFrame frame) @@ -109,8 +109,7 @@ throw new RuntimeIOException(x); } } - }, 4096, 8192); - parser.init(UnaryOperator.identity()); + }); parseResponse(client, parser); @@ -157,7 +156,8 @@ // Don't close the connection; the server should close. final CountDownLatch responseLatch = new CountDownLatch(1); - Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter() + Parser parser = new Parser(byteBufferPool, 4096); + parser.init(new Parser.Listener.Adapter() { @Override public void onHeaders(HeadersFrame frame) @@ -166,8 +166,7 @@ // HEADERS, the server is able to send us the response. responseLatch.countDown(); } - }, 4096, 8192); - parser.init(UnaryOperator.identity()); + }); parseResponse(client, parser); @@ -222,7 +221,8 @@ final CountDownLatch responseLatch = new CountDownLatch(1); final CountDownLatch closeLatch = new CountDownLatch(1); - Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter() + Parser parser = new Parser(byteBufferPool, 4096); + parser.init(new Parser.Listener.Adapter() { @Override public void onHeaders(HeadersFrame frame) @@ -235,8 +235,7 @@ { closeLatch.countDown(); } - }, 4096, 8192); - parser.init(UnaryOperator.identity()); + }); parseResponse(client, parser); diff -Nru jetty9-9.4.50/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java jetty9-9.4.57/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java --- jetty9-9.4.50/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java 2024-12-19 21:51:26.000000000 +0000 @@ -30,7 +30,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.UnaryOperator; import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpFields; @@ -152,7 +151,8 @@ final AtomicReference* See Usage + * href="https://jetty.org/docs/9/jetty-jspc-maven-plugin.html">Usage * Guide for instructions on using this plugin. *
* Runs jspc compiler to produce .java and .class files diff -Nru jetty9-9.4.50/jetty-jspc-maven-plugin/src/site/site.xml jetty9-9.4.57/jetty-jspc-maven-plugin/src/site/site.xml --- jetty9-9.4.50/jetty-jspc-maven-plugin/src/site/site.xml 2022-11-07 20:40:40.000000000 +0000 +++ jetty9-9.4.57/jetty-jspc-maven-plugin/src/site/site.xml 2024-12-19 21:51:26.000000000 +0000 @@ -6,8 +6,8 @@