Skip to content

Commit

Permalink
Issue #185 Implement RFC 7239
Browse files Browse the repository at this point in the history
Also handle legacy Https headers for #834
  • Loading branch information
gregw committed Aug 11, 2016
1 parent c033a37 commit b45af1a
Show file tree
Hide file tree
Showing 6 changed files with 637 additions and 226 deletions.
96 changes: 85 additions & 11 deletions jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSV.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ public class QuotedCSV implements Iterable<String>
{
private enum State { VALUE, PARAM_NAME, PARAM_VALUE};

private final List<String> _values = new ArrayList<>();
private final boolean _keepQuotes;
protected final List<String> _values = new ArrayList<>();
protected final boolean _keepQuotes;

/* ------------------------------------------------------------ */
public QuotedCSV(String... values)
Expand All @@ -62,6 +62,10 @@ public void addValue(String value)
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++)
{
char c=i==l?0:value.charAt(i);
Expand Down Expand Up @@ -105,12 +109,27 @@ public void addValue(String value)
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;
Expand All @@ -121,14 +140,54 @@ public void addValue(String value)
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
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)
Expand All @@ -142,22 +201,17 @@ public void addValue(String value)

case PARAM_NAME:
{
if (c=='=')
{
buffer.setLength(nws_length); // trim following OWS
buffer.append(c);
last_length=++nws_length;
state=State.PARAM_VALUE;
continue;
}
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;
Expand All @@ -168,6 +222,26 @@ public void addValue(String value)
}
}

/**
* 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)
{
}


public List<String> getValues()
{
return _values;
Expand Down
186 changes: 38 additions & 148 deletions jetty-http/src/main/java/org/eclipse/jetty/http/QuotedQualityCSV.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@
* @see "https://tools.ietf.org/html/rfc7230#section-7"
* @see "https://tools.ietf.org/html/rfc7231#section-5.3.1"
*/
public class QuotedQualityCSV implements Iterable<String>
public class QuotedQualityCSV extends QuotedCSV implements Iterable<String>
{
private final static Double ZERO=new Double(0.0);
private final static Double ONE=new Double(1.0);
private enum State { VALUE, PARAM_NAME, PARAM_VALUE, Q_VALUE};

private final List<String> _values = new ArrayList<>();
private final List<Double> _quality = new ArrayList<>();
private boolean _sorted = false;

Expand All @@ -53,154 +51,40 @@ public QuotedQualityCSV(String... values)
/* ------------------------------------------------------------ */
public void addValue(String value)
{
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;
Double q=ONE;
for (int i=0;i<=l;i++)
super.addValue(value);
while(_quality.size()<_values.size())
_quality.add(ONE);
}

/* ------------------------------------------------------------ */
@Override
protected void parsedValue(StringBuffer buffer)
{
super.parsedValue(buffer);
}

/* ------------------------------------------------------------ */
@Override
protected void parsedParam(StringBuffer buffer, int valueLength, int paramName, int paramValue)
{
if (buffer.charAt(paramName)=='q' && paramValue>paramName && buffer.charAt(paramName+1)=='=')
{
char c=i==l?0:value.charAt(i);

// Handle quoting https://tools.ietf.org/html/rfc7230#section-3.2.6
if (quoted && c!=0)
Double q;
try
{
if (sloshed)
sloshed=false;
else
{
switch(c)
{
case '\\':
sloshed=true;
break;
case '"':
quoted=false;
if (state==State.Q_VALUE)
continue;
break;
}
}

buffer.append(c);
nws_length=buffer.length();
continue;
q=(_keepQuotes && buffer.charAt(paramValue)=='"')
?new Double(buffer.substring(paramValue+1,buffer.length()-1))
:new Double(buffer.substring(paramValue));
}

// Handle common cases
switch(c)
catch(Exception e)
{
case ' ':
case '\t':
if (buffer.length()>last_length) // not leading OWS
buffer.append(c);
continue;

case '"':
quoted=true;
if (state==State.Q_VALUE)
continue;

buffer.append(c);
nws_length=buffer.length();
continue;

case ';':
if (state==State.Q_VALUE)
{
try
{
q=new Double(buffer.substring(last_length));
}
catch(Exception e)
{
q=ZERO;
}
nws_length=last_length;
}

buffer.setLength(nws_length); // trim following OWS
buffer.append(c);
last_length=++nws_length;
state=State.PARAM_NAME;
continue;

case ',':
case 0:
if (state==State.Q_VALUE)
{
try
{
q=new Double(buffer.substring(last_length));
}
catch(Exception e)
{
q=ZERO;
}
nws_length=last_length;
}
buffer.setLength(nws_length); // trim following OWS
if (q>0.0 && nws_length>0)
{
_values.add(buffer.toString());
_quality.add(q);
_sorted=false;
}
buffer.setLength(0);
last_length=0;
nws_length=0;
q=ONE;
state=State.VALUE;
continue;

default:
{
switch (state)
{
case VALUE:
{
buffer.append(c);
nws_length=buffer.length();
continue;
}

case PARAM_NAME:
{
if (c=='=')
{
buffer.setLength(nws_length); // trim following OWS
if (nws_length-last_length==1 && Character.toLowerCase(buffer.charAt(last_length))=='q')
{
buffer.setLength(last_length-1);
nws_length=buffer.length();
last_length=nws_length;
state=State.Q_VALUE;
continue;
}
buffer.append(c);
last_length=++nws_length;
state=State.PARAM_VALUE;
continue;
}
buffer.append(c);
nws_length=buffer.length();
continue;
}

case PARAM_VALUE:
case Q_VALUE:
{
buffer.append(c);
nws_length=buffer.length();
continue;
}
}
}
}
q=ZERO;
}
buffer.setLength(paramName-1);

while(_quality.size()<_values.size())
_quality.add(ONE);
_quality.add(q);
}
}

Expand Down Expand Up @@ -246,7 +130,13 @@ protected void sort()

last=q;
len=v.length();

}

int last_element=_quality.size();
while(last_element>0 && _quality.get(--last_element).equals(ZERO))
{
_quality.remove(last_element);
_values.remove(last_element);
}
}
}
Loading

0 comments on commit b45af1a

Please sign in to comment.