5 Star 0 Fork 16

src-openEuler/jetty

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
CVE-2020-27223.patch 40.69 KB
一键复制 编辑 原始数据 按行查看 历史
emancipator 提交于 2022-09-14 10:23 . CVE-2019-10241
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196
From: Markus Koschany <apo@debian.org>
Date: Sat, 31 Jul 2021 17:21:57 +0200
Subject: CVE-2020-27223
---
.../java/org/eclipse/jetty/http/QuotedCSV.java | 280 ++-----------------
.../org/eclipse/jetty/http/QuotedCSVParser.java | 303 +++++++++++++++++++++
.../org/eclipse/jetty/http/QuotedQualityCSV.java | 140 ++++++----
.../eclipse/jetty/http/QuotedQualityCSVTest.java | 143 +++++-----
4 files changed, 479 insertions(+), 387 deletions(-)
create mode 100644 jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSVParser.java
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSV.java b/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSV.java
index 9ca7dbe..a356213 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSV.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSV.java
@@ -1,6 +1,6 @@
//
// ========================================================================
-// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
+// Copyright (c) 1995-2021 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
@@ -22,236 +22,36 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-import org.eclipse.jetty.util.QuotedStringTokenizer;
-
-/* ------------------------------------------------------------ */
/**
* Implements a quoted comma separated list of values
* in accordance with RFC7230.
* OWS is removed and quoted characters ignored for parsing.
+ *
* @see "https://tools.ietf.org/html/rfc7230#section-3.2.6"
* @see "https://tools.ietf.org/html/rfc7230#section-7"
*/
-public class QuotedCSV implements Iterable<String>
-{
- private enum State { VALUE, PARAM_NAME, PARAM_VALUE};
-
+public class QuotedCSV extends QuotedCSVParser implements Iterable<String>
+{
protected final List<String> _values = new ArrayList<>();
- protected final boolean _keepQuotes;
-
- /* ------------------------------------------------------------ */
+
public QuotedCSV(String... values)
{
- this(true,values);
+ this(true, values);
}
-
- /* ------------------------------------------------------------ */
- public QuotedCSV(boolean keepQuotes,String... values)
- {
- _keepQuotes=keepQuotes;
- for (String v:values)
- addValue(v);
- }
-
- /* ------------------------------------------------------------ */
- /** Add and parse a value string(s)
- * @param value A value that may contain one or more Quoted CSV items.
- */
- public void addValue(String value)
+
+ public QuotedCSV(boolean keepQuotes, String... values)
{
- if (value == null)
- return;
-
- StringBuffer buffer = new StringBuffer();
-
- int l=value.length();
- State state=State.VALUE;
- boolean quoted=false;
- boolean sloshed=false;
- int nws_length=0;
- int last_length=0;
- int value_length=-1;
- int param_name=-1;
- int param_value=-1;
-
- for (int i=0;i<=l;i++)
+ super(keepQuotes);
+ for (String v : values)
{
- char c=i==l?0:value.charAt(i);
-
- // Handle quoting https://tools.ietf.org/html/rfc7230#section-3.2.6
- if (quoted && c!=0)
- {
- if (sloshed)
- sloshed=false;
- else
- {
- switch(c)
- {
- case '\\':
- sloshed=true;
- if (!_keepQuotes)
- continue;
- break;
- case '"':
- quoted=false;
- if (!_keepQuotes)
- continue;
- break;
- }
- }
-
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- // Handle common cases
- switch(c)
- {
- case ' ':
- case '\t':
- if (buffer.length()>last_length) // not leading OWS
- buffer.append(c);
- continue;
-
- case '"':
- quoted=true;
- if (_keepQuotes)
- {
- if (state==State.PARAM_VALUE && param_value<0)
- param_value=nws_length;
- buffer.append(c);
- }
- else if (state==State.PARAM_VALUE && param_value<0)
- param_value=nws_length;
- nws_length=buffer.length();
- continue;
-
- case ';':
- buffer.setLength(nws_length); // trim following OWS
- if (state==State.VALUE)
- {
- parsedValue(buffer);
- value_length=buffer.length();
- }
- else
- parsedParam(buffer,value_length,param_name,param_value);
- nws_length=buffer.length();
- param_name=param_value=-1;
- buffer.append(c);
- last_length=++nws_length;
- state=State.PARAM_NAME;
- continue;
-
- case ',':
- case 0:
- if (nws_length>0)
- {
- buffer.setLength(nws_length); // trim following OWS
- switch(state)
- {
- case VALUE:
- parsedValue(buffer);
- value_length=buffer.length();
- break;
- case PARAM_NAME:
- case PARAM_VALUE:
- parsedParam(buffer,value_length,param_name,param_value);
- break;
- }
- _values.add(buffer.toString());
- }
- buffer.setLength(0);
- last_length=0;
- nws_length=0;
- value_length=param_name=param_value=-1;
- state=State.VALUE;
- continue;
-
- case '=':
- switch (state)
- {
- case VALUE:
- // It wasn't really a value, it was a param name
- value_length=param_name=0;
- buffer.setLength(nws_length); // trim following OWS
- String param = buffer.toString();
- buffer.setLength(0);
- parsedValue(buffer);
- value_length=buffer.length();
- buffer.append(param);
- buffer.append(c);
- last_length=++nws_length;
- state=State.PARAM_VALUE;
- continue;
-
- case PARAM_NAME:
- buffer.setLength(nws_length); // trim following OWS
- buffer.append(c);
- last_length=++nws_length;
- state=State.PARAM_VALUE;
- continue;
-
- case PARAM_VALUE:
- if (param_value<0)
- param_value=nws_length;
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
- continue;
-
- default:
- {
- switch (state)
- {
- case VALUE:
- {
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- case PARAM_NAME:
- {
- if (param_name<0)
- param_name=nws_length;
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- case PARAM_VALUE:
- {
- if (param_value<0)
- param_value=nws_length;
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
- }
- }
- }
+ addValue(v);
}
}
- /**
- * Called when a value has been parsed
- * @param buffer Containing the trimmed value, which may be mutated
- */
- protected void parsedValue(StringBuffer buffer)
- {
- }
-
- /**
- * Called when a parameter has been parsed
- * @param buffer Containing the trimmed value and all parameters, which may be mutated
- * @param valueLength The length of the value
- * @param paramName The index of the start of the parameter just parsed
- * @param paramValue The index of the start of the parameter value just parsed, or -1
- */
- protected void parsedParam(StringBuffer buffer, int valueLength, int paramName, int paramValue)
+ @Override
+ protected void parsedValueAndParams(StringBuffer buffer)
{
+ _values.add(buffer.toString());
}
public int size()
@@ -268,67 +68,21 @@ public class QuotedCSV implements Iterable<String>
{
return _values;
}
-
+
@Override
public Iterator<String> iterator()
{
return _values.iterator();
}
-
- public static String unquote(String s)
- {
- // handle trivial cases
- int l=s.length();
- if (s==null || l==0)
- return s;
-
- // Look for any quotes
- int i=0;
- for (;i<l;i++)
- {
- char c=s.charAt(i);
- if (c=='"')
- break;
- }
- if (i==l)
- return s;
- boolean quoted=true;
- boolean sloshed=false;
- StringBuffer buffer = new StringBuffer();
- buffer.append(s,0,i);
- i++;
- for (;i<l;i++)
- {
- char c=s.charAt(i);
- if (quoted)
- {
- if (sloshed)
- {
- buffer.append(c);
- sloshed=false;
- }
- else if (c=='"')
- quoted=false;
- else if (c=='\\')
- sloshed=true;
- else
- buffer.append(c);
- }
- else if (c=='"')
- quoted=true;
- else
- buffer.append(c);
- }
- return buffer.toString();
- }
-
@Override
public String toString()
{
List<String> list = new ArrayList<>();
for (String s : this)
+ {
list.add(s);
+ }
return list.toString();
}
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSVParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSVParser.java
new file mode 100644
index 0000000..7aefcf7
--- /dev/null
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSVParser.java
@@ -0,0 +1,303 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2021 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;
+
+/**
+ * Implements a quoted comma separated list parser
+ * in accordance with RFC7230.
+ * OWS is removed and quoted characters ignored for parsing.
+ *
+ * @see "https://tools.ietf.org/html/rfc7230#section-3.2.6"
+ * @see "https://tools.ietf.org/html/rfc7230#section-7"
+ */
+public abstract class QuotedCSVParser
+{
+ private enum State
+ {
+ VALUE, PARAM_NAME, PARAM_VALUE
+ }
+
+ protected final boolean _keepQuotes;
+
+ public QuotedCSVParser(boolean keepQuotes)
+ {
+ _keepQuotes = keepQuotes;
+ }
+
+ public static String unquote(String s)
+ {
+ // handle trivial cases
+ int l = s.length();
+ if (s == null || l == 0)
+ return s;
+
+ // Look for any quotes
+ int i = 0;
+ for (; i < l; i++)
+ {
+ char c = s.charAt(i);
+ if (c == '"')
+ break;
+ }
+ if (i == l)
+ return s;
+
+ boolean quoted = true;
+ boolean sloshed = false;
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(s, 0, i);
+ i++;
+ for (; i < l; i++)
+ {
+ char c = s.charAt(i);
+ if (quoted)
+ {
+ if (sloshed)
+ {
+ buffer.append(c);
+ sloshed = false;
+ }
+ else if (c == '"')
+ quoted = false;
+ else if (c == '\\')
+ sloshed = true;
+ else
+ buffer.append(c);
+ }
+ else if (c == '"')
+ quoted = true;
+ else
+ buffer.append(c);
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Add and parse a value string(s)
+ *
+ * @param value A value that may contain one or more Quoted CSV items.
+ */
+ public void addValue(String value)
+ {
+ if (value == null)
+ return;
+
+ StringBuffer buffer = new StringBuffer();
+
+ int l = value.length();
+ State state = State.VALUE;
+ boolean quoted = false;
+ boolean sloshed = false;
+ int nwsLength = 0;
+ int lastLength = 0;
+ int valueLength = -1;
+ int paramName = -1;
+ int paramValue = -1;
+
+ for (int i = 0; i <= l; i++)
+ {
+ char c = i == l ? 0 : value.charAt(i);
+
+ // Handle quoting https://tools.ietf.org/html/rfc7230#section-3.2.6
+ if (quoted && c != 0)
+ {
+ if (sloshed)
+ sloshed = false;
+ else
+ {
+ switch (c)
+ {
+ case '\\':
+ sloshed = true;
+ if (!_keepQuotes)
+ continue;
+ break;
+ case '"':
+ quoted = false;
+ if (!_keepQuotes)
+ continue;
+ break;
+ }
+ }
+
+ buffer.append(c);
+ nwsLength = buffer.length();
+ continue;
+ }
+
+ // Handle common cases
+ switch (c)
+ {
+ case ' ':
+ case '\t':
+ if (buffer.length() > lastLength) // not leading OWS
+ buffer.append(c);
+ continue;
+
+ case '"':
+ quoted = true;
+ if (_keepQuotes)
+ {
+ if (state == State.PARAM_VALUE && paramValue < 0)
+ paramValue = nwsLength;
+ buffer.append(c);
+ }
+ else if (state == State.PARAM_VALUE && paramValue < 0)
+ paramValue = nwsLength;
+ nwsLength = buffer.length();
+ continue;
+
+ case ';':
+ buffer.setLength(nwsLength); // trim following OWS
+ if (state == State.VALUE)
+ {
+ parsedValue(buffer);
+ valueLength = buffer.length();
+ }
+ else
+ parsedParam(buffer, valueLength, paramName, paramValue);
+ nwsLength = buffer.length();
+ paramName = paramValue = -1;
+ buffer.append(c);
+ lastLength = ++nwsLength;
+ state = State.PARAM_NAME;
+ continue;
+
+ case ',':
+ case 0:
+ if (nwsLength > 0)
+ {
+ buffer.setLength(nwsLength); // trim following OWS
+ switch (state)
+ {
+ case VALUE:
+ parsedValue(buffer);
+ valueLength = buffer.length();
+ break;
+ case PARAM_NAME:
+ case PARAM_VALUE:
+ parsedParam(buffer, valueLength, paramName, paramValue);
+ break;
+ }
+ parsedValueAndParams(buffer);
+ }
+ buffer.setLength(0);
+ lastLength = 0;
+ nwsLength = 0;
+ valueLength = paramName = paramValue = -1;
+ state = State.VALUE;
+ continue;
+
+ case '=':
+ switch (state)
+ {
+ case VALUE:
+ // It wasn't really a value, it was a param name
+ valueLength = paramName = 0;
+ buffer.setLength(nwsLength); // trim following OWS
+ String param = buffer.toString();
+ buffer.setLength(0);
+ parsedValue(buffer);
+ valueLength = buffer.length();
+ buffer.append(param);
+ buffer.append(c);
+ lastLength = ++nwsLength;
+ state = State.PARAM_VALUE;
+ continue;
+
+ case PARAM_NAME:
+ buffer.setLength(nwsLength); // trim following OWS
+ buffer.append(c);
+ lastLength = ++nwsLength;
+ state = State.PARAM_VALUE;
+ continue;
+
+ case PARAM_VALUE:
+ if (paramValue < 0)
+ paramValue = nwsLength;
+ buffer.append(c);
+ nwsLength = buffer.length();
+ continue;
+ }
+ continue;
+
+ default:
+ {
+ switch (state)
+ {
+ case VALUE:
+ {
+ buffer.append(c);
+ nwsLength = buffer.length();
+ continue;
+ }
+
+ case PARAM_NAME:
+ {
+ if (paramName < 0)
+ paramName = nwsLength;
+ buffer.append(c);
+ nwsLength = buffer.length();
+ continue;
+ }
+
+ case PARAM_VALUE:
+ {
+ if (paramValue < 0)
+ paramValue = nwsLength;
+ buffer.append(c);
+ nwsLength = buffer.length();
+ continue;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when a value and it's parameters has been parsed
+ *
+ * @param buffer Containing the trimmed value and parameters
+ */
+ protected void parsedValueAndParams(StringBuffer buffer)
+ {
+ }
+
+ /**
+ * Called when a value has been parsed (prior to any parameters)
+ *
+ * @param buffer Containing the trimmed value, which may be mutated
+ */
+ protected void parsedValue(StringBuffer buffer)
+ {
+ }
+
+ /**
+ * Called when a parameter has been parsed
+ *
+ * @param buffer Containing the trimmed value and all parameters, which may be mutated
+ * @param valueLength The length of the value
+ * @param paramName The index of the start of the parameter just parsed
+ * @param paramValue The index of the start of the parameter value just parsed, or -1
+ */
+ protected void parsedParam(StringBuffer buffer, int valueLength, int paramName, int paramValue)
+ {
+ }
+}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedQualityCSV.java b/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedQualityCSV.java
index d148d9e..5bc9985 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedQualityCSV.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedQualityCSV.java
@@ -1,6 +1,6 @@
//
// ========================================================================
-// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
+// Copyright (c) 1995-2021 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
@@ -21,14 +21,12 @@ package org.eclipse.jetty.http;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.function.ToIntFunction;
+import java.util.stream.Collectors;
import org.eclipse.jetty.util.log.Log;
-import static java.lang.Integer.MIN_VALUE;
-
-/* ------------------------------------------------------------ */
-
/**
* Implements a quoted comma separated list of quality values
* in accordance with RFC7230 and RFC7231.
@@ -57,22 +55,19 @@ public class QuotedQualityCSV extends QuotedCSV implements Iterable<String>
return 3;
};
- private final List<Double> _quality = new ArrayList<>();
+ private final List<QualityValue> _qualities = new ArrayList<>();
+ private QualityValue _lastQuality;
private boolean _sorted = false;
private final ToIntFunction<String> _secondaryOrdering;
- /* ------------------------------------------------------------ */
-
/**
* Sorts values with equal quality according to the length of the value String.
*/
public QuotedQualityCSV()
{
- this((ToIntFunction)null);
+ this((ToIntFunction<String>)null);
}
- /* ------------------------------------------------------------ */
-
/**
* Sorts values with equal quality according to given order.
*
@@ -83,57 +78,71 @@ public class QuotedQualityCSV extends QuotedCSV implements Iterable<String>
this((s) ->
{
for (int i = 0; i < preferredOrder.length; ++i)
+ {
if (preferredOrder[i].equals(s))
return preferredOrder.length - i;
+ }
if ("*".equals(s))
return preferredOrder.length;
- return MIN_VALUE;
+ return 0;
});
}
- /* ------------------------------------------------------------ */
-
/**
* Orders values with equal quality with the given function.
*
- * @param secondaryOrdering Function to apply an ordering other than specified by quality
+ * @param secondaryOrdering Function to apply an ordering other than specified by quality, highest values are sorted first.
*/
public QuotedQualityCSV(ToIntFunction<String> secondaryOrdering)
{
this._secondaryOrdering = secondaryOrdering == null ? s -> 0 : secondaryOrdering;
}
- /* ------------------------------------------------------------ */
+ @Override
+ protected void parsedValueAndParams(StringBuffer buffer)
+ {
+ super.parsedValueAndParams(buffer);
+
+ // Collect full value with parameters
+ _lastQuality = new QualityValue(_lastQuality._quality, buffer.toString(), _lastQuality._index);
+ _qualities.set(_lastQuality._index, _lastQuality);
+ }
+
@Override
protected void parsedValue(StringBuffer buffer)
{
super.parsedValue(buffer);
+ _sorted = false;
+
+ // This is the just the value, without parameters.
// Assume a quality of ONE
- _quality.add(1.0D);
+ _lastQuality = new QualityValue(1.0D, buffer.toString(), _qualities.size());
+ _qualities.add(_lastQuality);
}
- /* ------------------------------------------------------------ */
@Override
protected void parsedParam(StringBuffer buffer, int valueLength, int paramName, int paramValue)
{
+ _sorted = false;
+
if (paramName < 0)
{
if (buffer.charAt(buffer.length() - 1) == ';')
buffer.setLength(buffer.length() - 1);
}
else if (paramValue >= 0 &&
- buffer.charAt(paramName) == 'q' && paramValue > paramName &&
- buffer.length() >= paramName && buffer.charAt(paramName + 1) == '=')
+ buffer.charAt(paramName) == 'q' && paramValue > paramName &&
+ buffer.length() >= paramName && buffer.charAt(paramName + 1) == '=')
{
- Double q;
+ double q;
try
{
q = (_keepQuotes && buffer.charAt(paramValue) == '"')
- ? Double.valueOf(buffer.substring(paramValue + 1, buffer.length() - 1))
- : Double.valueOf(buffer.substring(paramValue));
+ ? Double.valueOf(buffer.substring(paramValue + 1, buffer.length() - 1))
+ : Double.valueOf(buffer.substring(paramValue));
}
catch (Exception e)
{
@@ -143,8 +152,10 @@ public class QuotedQualityCSV extends QuotedCSV implements Iterable<String>
buffer.setLength(Math.max(0, paramName - 1));
if (q != 1.0D)
- // replace assumed quality
- _quality.set(_quality.size() - 1, q);
+ {
+ _lastQuality = new QualityValue(q, buffer.toString(), _lastQuality._index);
+ _qualities.set(_lastQuality._index, _lastQuality);
+ }
}
}
@@ -166,38 +177,73 @@ public class QuotedQualityCSV extends QuotedCSV implements Iterable<String>
protected void sort()
{
+ _values.clear();
+ _qualities.stream()
+ .filter((qv) -> qv._quality != 0.0D)
+ .sorted()
+ .map(QualityValue::getValue)
+ .collect(Collectors.toCollection(() -> _values));
_sorted = true;
+ }
+
+ private class QualityValue implements Comparable<QualityValue>
+ {
+ private final double _quality;
+ private final String _value;
+ private final int _index;
- Double last = 0.0D;
- int lastSecondaryOrder = Integer.MIN_VALUE;
+ private QualityValue(double quality, String value, int index)
+ {
+ _quality = quality;
+ _value = value;
+ _index = index;
+ }
- for (int i = _values.size(); i-- > 0; )
+ @Override
+ public int hashCode()
{
- String v = _values.get(i);
- Double q = _quality.get(i);
+ return Double.hashCode(_quality) ^ Objects.hash(_value, _index);
+ }
- int compare = last.compareTo(q);
- if (compare > 0 || (compare == 0 && _secondaryOrdering.applyAsInt(v) < lastSecondaryOrder))
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof QualityValue))
+ return false;
+ QualityValue qv = (QualityValue)obj;
+ return _quality == qv._quality && Objects.equals(_value, qv._value) && Objects.equals(_index, qv._index);
+ }
+
+ private String getValue()
+ {
+ return _value;
+ }
+
+ @Override
+ public int compareTo(QualityValue o)
+ {
+ // sort highest quality first
+ int compare = Double.compare(o._quality, _quality);
+ if (compare == 0)
{
- _values.set(i, _values.get(i + 1));
- _values.set(i + 1, v);
- _quality.set(i, _quality.get(i + 1));
- _quality.set(i + 1, q);
- last = 0.0D;
- lastSecondaryOrder = 0;
- i = _values.size();
- continue;
+ // then sort secondary order highest first
+ compare = Integer.compare(_secondaryOrdering.applyAsInt(o._value), _secondaryOrdering.applyAsInt(_value));
+ if (compare == 0)
+ // then sort index lowest first
+ compare = -Integer.compare(o._index, _index);
}
-
- last = q;
- lastSecondaryOrder = _secondaryOrdering.applyAsInt(v);
+ return compare;
}
- int last_element = _quality.size();
- while (last_element > 0 && _quality.get(--last_element).equals(0.0D))
+ @Override
+ public String toString()
{
- _quality.remove(last_element);
- _values.remove(last_element);
+ return String.format("%s@%x[%s,q=%f,i=%d]",
+ getClass().getSimpleName(),
+ hashCode(),
+ _value,
+ _quality,
+ _index);
}
}
}
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/QuotedQualityCSVTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/QuotedQualityCSVTest.java
index f03657b..b941e95 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/QuotedQualityCSVTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/QuotedQualityCSVTest.java
@@ -1,6 +1,6 @@
//
// ========================================================================
-// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
+// Copyright (c) 1995-2021 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
@@ -18,13 +18,12 @@
package org.eclipse.jetty.http;
+import java.util.ArrayList;
+import java.util.List;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
-import java.util.ArrayList;
-import java.util.List;
-
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
@@ -32,58 +31,58 @@ public class QuotedQualityCSVTest
{
@Test
- public void test7231_5_3_2_example1()
+ public void test7231Sec532Example1()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue(" audio/*; q=0.2, audio/basic");
- assertThat(values,Matchers.contains("audio/basic","audio/*"));
+ assertThat(values, Matchers.contains("audio/basic", "audio/*"));
}
@Test
- public void test7231_5_3_2_example2()
+ public void test7231Sec532Example2()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue("text/plain; q=0.5, text/html,");
values.addValue("text/x-dvi; q=0.8, text/x-c");
- assertThat(values,Matchers.contains("text/html","text/x-c","text/x-dvi","text/plain"));
+ assertThat(values, Matchers.contains("text/html", "text/x-c", "text/x-dvi", "text/plain"));
}
-
+
@Test
- public void test7231_5_3_2_example3()
+ public void test7231Sec532Example3()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue("text/*, text/plain, text/plain;format=flowed, */*");
-
+
// Note this sort is only on quality and not the most specific type as per 5.3.2
- assertThat(values,Matchers.contains("text/*","text/plain","text/plain;format=flowed","*/*"));
+ assertThat(values, Matchers.contains("text/*", "text/plain", "text/plain;format=flowed", "*/*"));
}
-
+
@Test
- public void test7231_5_3_2_example3_most_specific()
+ public void test7231532Example3MostSpecific()
{
QuotedQualityCSV values = new QuotedQualityCSV(QuotedQualityCSV.MOST_SPECIFIC_MIME_ORDERING);
values.addValue("text/*, text/plain, text/plain;format=flowed, */*");
-
- assertThat(values,Matchers.contains("text/plain;format=flowed","text/plain","text/*","*/*"));
+
+ assertThat(values, Matchers.contains("text/plain;format=flowed", "text/plain", "text/*", "*/*"));
}
-
+
@Test
- public void test7231_5_3_2_example4()
+ public void test7231Sec532Example4()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue("text/*;q=0.3, text/html;q=0.7, text/html;level=1,");
values.addValue("text/html;level=2;q=0.4, */*;q=0.5");
- assertThat(values,Matchers.contains(
- "text/html;level=1",
- "text/html",
- "*/*",
- "text/html;level=2",
- "text/*"
- ));
+ assertThat(values, Matchers.contains(
+ "text/html;level=1",
+ "text/html",
+ "*/*",
+ "text/html;level=2",
+ "text/*"
+ ));
}
-
+
@Test
- public void test7231_5_3_4_example1()
+ public void test7231Sec534Example1()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue("compress, gzip");
@@ -91,16 +90,16 @@ public class QuotedQualityCSVTest
values.addValue("*");
values.addValue("compress;q=0.5, gzip;q=1.0");
values.addValue("gzip;q=1.0, identity; q=0.5, *;q=0");
-
- assertThat(values,Matchers.contains(
- "compress",
- "gzip",
- "*",
- "gzip",
- "gzip",
- "compress",
- "identity"
- ));
+
+ assertThat(values, Matchers.contains(
+ "compress",
+ "gzip",
+ "*",
+ "gzip",
+ "gzip",
+ "compress",
+ "identity"
+ ));
}
@Test
@@ -108,66 +107,65 @@ public class QuotedQualityCSVTest
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue(" value 0.5 ; p = v ; q =0.5 , value 1.0 ");
- assertThat(values,Matchers.contains(
- "value 1.0",
- "value 0.5;p=v"));
+ assertThat(values, Matchers.contains(
+ "value 1.0",
+ "value 0.5;p=v"));
}
-
+
@Test
public void testEmpty()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue(",aaaa, , bbbb ,,cccc,");
- assertThat(values,Matchers.contains(
- "aaaa",
- "bbbb",
- "cccc"));
+ assertThat(values, Matchers.contains(
+ "aaaa",
+ "bbbb",
+ "cccc"));
}
-
+
@Test
public void testQuoted()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue(" value 0.5 ; p = \"v ; q = \\\"0.5\\\" , value 1.0 \" ");
- assertThat(values,Matchers.contains(
- "value 0.5;p=\"v ; q = \\\"0.5\\\" , value 1.0 \""));
+ assertThat(values, Matchers.contains(
+ "value 0.5;p=\"v ; q = \\\"0.5\\\" , value 1.0 \""));
}
-
+
@Test
public void testOpenQuote()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue("value;p=\"v");
- assertThat(values,Matchers.contains(
- "value;p=\"v"));
+ assertThat(values, Matchers.contains(
+ "value;p=\"v"));
}
-
+
@Test
public void testQuotedQuality()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue(" value 0.5 ; p = v ; q = \"0.5\" , value 1.0 ");
- assertThat(values,Matchers.contains(
- "value 1.0",
- "value 0.5;p=v"));
+ assertThat(values, Matchers.contains(
+ "value 1.0",
+ "value 0.5;p=v"));
}
-
+
@Test
public void testBadQuality()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue("value0.5;p=v;q=0.5,value1.0,valueBad;q=X");
- assertThat(values,Matchers.contains(
- "value1.0",
- "value0.5;p=v"));
+ assertThat(values, Matchers.contains(
+ "value1.0",
+ "value0.5;p=v"));
}
-
+
@Test
public void testBad()
{
QuotedQualityCSV values = new QuotedQualityCSV();
-
// None of these should throw exceptions
values.addValue(null);
values.addValue("");
@@ -223,13 +221,10 @@ public class QuotedQualityCSVTest
values.addValue("q=");
values.addValue("q=,");
values.addValue("q=;");
-
}
- /* ------------------------------------------------------------ */
-
- private static final String[] preferBrotli = {"br","gzip"};
- private static final String[] preferGzip = {"gzip","br"};
+ private static final String[] preferBrotli = {"br", "gzip"};
+ private static final String[] preferGzip = {"gzip", "br"};
private static final String[] noFormats = {};
@Test
@@ -295,14 +290,13 @@ public class QuotedQualityCSVTest
values.addValue("gzip, *");
assertThat(values, contains("*", "gzip"));
}
-
@Test
public void testSameQuality()
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue("one;q=0.5,two;q=0.5,three;q=0.5");
- assertThat(values.getValues(),Matchers.contains("one","two","three"));
+ assertThat(values.getValues(), Matchers.contains("one", "two", "three"));
}
@Test
@@ -310,10 +304,9 @@ public class QuotedQualityCSVTest
{
QuotedQualityCSV values = new QuotedQualityCSV();
values.addValue("one,two;,three;x=y");
- assertThat(values.getValues(),Matchers.contains("one","two","three;x=y"));
+ assertThat(values.getValues(), Matchers.contains("one", "two", "three;x=y"));
}
-
@Test
public void testQuality()
{
@@ -339,19 +332,15 @@ public class QuotedQualityCSVTest
}
};
-
// The provided string is not legal according to some RFCs ( not a token because of = and not a parameter because not preceded by ; )
// The string is legal according to RFC7239 which allows for just parameters (called forwarded-pairs)
values.addValue("p=0.5,q=0.5");
-
// The QuotedCSV implementation is lenient and adopts the later interpretation and thus sees q=0.5 and p=0.5 both as parameters
- assertThat(results,contains("parsedValue: ", "parsedParam: p=0.5",
- "parsedValue: ", "parsedParam: q=0.5"));
-
+ assertThat(results, contains("parsedValue: ", "parsedParam: p=0.5",
+ "parsedValue: ", "parsedParam: q=0.5"));
// However the QuotedQualityCSV only handles the q parameter and that is consumed from the parameter string.
- assertThat(values,contains("p=0.5", ""));
-
+ assertThat(values, contains("p=0.5", ""));
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/src-openeuler/jetty.git
git@gitee.com:src-openeuler/jetty.git
src-openeuler
jetty
jetty
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385