int nameEnd;
int valueStart;
int valueEnd;
int version = 0;
Cookie cookie = null;
boolean isSpecial;
boolean isQuoted;
while (pos < end) {
isSpecial = false;
isQuoted = false;
// Skip whitespace and non-token characters (separators)
while (pos < end
&& (isSeparator(cookiesStr.charAt(pos)) || isWhiteSpace(cookiesStr.charAt(pos)))) {
pos++;
}
if (pos >= end) {
return;
}
// Detect Special cookies
if (cookiesStr.charAt(pos) == '$') {
isSpecial = true;
pos++;
}
// Get the cookie name. This must be a token
nameStart = pos;
pos = nameEnd = getTokenEndPosition(cookiesStr, pos, end);
// Skip whitespace
while (pos < end && isWhiteSpace(cookiesStr.charAt(pos))) {
pos++;
}
// Check for an '=' -- This could also be a name-only
// cookie at the end of the cookie header, so if we
// are past the end of the header, but we have a name
// skip to the name-only part.
if (pos < end && cookiesStr.charAt(pos) == '=') {
// Skip whitespace
do {
pos++;
} while (pos < end && isWhiteSpace(cookiesStr.charAt(pos)));
if (pos >= end) {
return;
}
// Determine what type of value this is, quoted value,
// token, name-only with an '=', or other (bad)
switch (cookiesStr.charAt(pos)) {
case '"':
// Quoted Value
isQuoted = true;
valueStart = pos + 1; // strip "
// getQuotedValue returns the position before
// at the last qoute. This must be dealt with
// when the bytes are copied into the cookie
valueEnd = getQuotedValueEndPosition(cookiesStr,
valueStart, end);
// We need pos to advance
pos = valueEnd;
// Handles cases where the quoted value is
// unterminated and at the end of the header,
// e.g. [myname="value]
if (pos >= end) {
return;
}
break;
case ';':
case ',':
// Name-only cookie with an '=' after the name token
// This may not be RFC compliant
valueStart = valueEnd = -1;
// The position is OK (On a delimiter)
break;
default:
if (!isSeparator(cookiesStr.charAt(pos), versionOneStrictCompliance)) {
// Token
// Token
valueStart = pos;
// getToken returns the position at the delimeter
// or other non-token character
valueEnd = getTokenEndPosition(cookiesStr, valueStart, end,
versionOneStrictCompliance);
// We need pos to advance
pos = valueEnd;
} else {
// INVALID COOKIE, advance to next delimiter
// The starting character of the cookie value was
// not valid.
LOGGER.fine("Invalid cookie. Value not a token or quoted value");
while (pos < end && cookiesStr.charAt(pos) != ';'
&& cookiesStr.charAt(pos) != ',') {
pos++;
}
pos++;
// Make sure no special avpairs can be attributed to
// the previous cookie by setting the current cookie
// to null
cookie = null;
continue;
}
}
} else {
// Name only cookie
valueStart = valueEnd = -1;
pos = nameEnd;
}
// We should have an avpair or name-only cookie at this
// point. Perform some basic checks to make sure we are
// in a good state.
// Skip whitespace
while (pos < end && isWhiteSpace(cookiesStr.charAt(pos))) {
pos++;
}
// Make sure that after the cookie we have a separator. This
// is only important if this is not the last cookie pair
while (pos < end && cookiesStr.charAt(pos) != ';' && cookiesStr.charAt(pos) != ',') {
pos++;
}
pos++;
// All checks passed. Add the cookie, start with the
// special avpairs first
if (isSpecial) {
isSpecial = false;
// $Version must be the first avpair in the cookie header
// (sc must be null)
if (CookieUtils.equals("Version", cookiesStr, nameStart, nameEnd)
&& cookie == null) {
if (rfc6265Enabled) {
continue;
}
// Set version
if (cookiesStr.charAt(valueStart) == '1'
&& valueEnd == (valueStart + 1)) {
version = 1;
} else {
// unknown version (Versioning is not very strict)
}
continue;
}
// We need an active cookie for Path/Port/etc.
if (cookie == null) {
continue;
}
// Domain is more common, so it goes first
if (CookieUtils.equals("Domain", cookiesStr, nameStart, nameEnd)) {
cookie.setDomain(cookiesStr.substring(valueStart, valueEnd));
continue;
}
if (CookieUtils.equals("Path", cookiesStr, nameStart, nameEnd)) {
cookie.setPath(cookiesStr.substring(valueStart, valueEnd));
continue;
}
// Unknown cookie, complain
LOGGER.fine("Unknown Special Cookie");
} else { // Normal Cookie
String name = cookiesStr.substring(nameStart, nameEnd);
String value;
if (valueStart != -1) { // Normal AVPair
if (isQuoted) {
// We know this is a byte value so this is safe
value = unescapeDoubleQuotes(cookiesStr, valueStart, valueEnd - valueStart);
} else {
value = cookiesStr.substring(valueStart, valueEnd);
}
} else {
// Name Only
value = "";
}
cookie = cookies.getNextUnusedCookie();
cookie.setName(name);
cookie.setValue(value);
if (!rfc6265Enabled && !cookie.isVersionSet()) {
cookie.setVersion(version);
}
}
}
}