de.mklinger.qetcher.client.jetty.http.QuotedCSV Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of qetcher-client-bundle Show documentation
Show all versions of qetcher-client-bundle Show documentation
Qetcher Java client, OSGi bundle, minimal dependencies
//
// ========================================================================
// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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;
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
{
private enum State { VALUE, PARAM_NAME, PARAM_VALUE};
protected final List _values = new ArrayList<>();
protected final boolean _keepQuotes;
/* ------------------------------------------------------------ */
public QuotedCSV(String... 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)
{
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++)
{
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;
}
}
}
}
}
}
/**
* 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 int size()
{
return _values.size();
}
public boolean isEmpty()
{
return _values.isEmpty();
}
public List getValues()
{
return _values;
}
@Override
public Iterator 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 list = new ArrayList<>();
for (String s : this)
list.add(s);
return list.toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy