int nameEnd;
int valueStart;
int valueEnd;
Cookie cookie = null;
LazyCookieState lazyCookie = null;
boolean isQuoted;
while (pos < end) {
isQuoted = false;
// Skip whitespace and non-token characters (separators)
while (pos < end
&& (isSeparator(buffer.get(pos)) || isWhiteSpace(buffer.get(pos)))) {
pos++;
}
if (pos >= end) {
return;
}
// Get the cookie name. This must be a token
nameStart = pos;
pos = nameEnd = getTokenEndPosition(buffer, pos, end);
// Skip whitespace
while (pos < end && isWhiteSpace(buffer.get(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 && buffer.get(pos) == '=') {
// Skip whitespace
do {
pos++;
} while (pos < end && isWhiteSpace(buffer.get(pos)));
if (pos >= end) {
return;
}
// Determine what type of value this is, quoted value,
// token, name-only with an '=', or other (bad)
switch (buffer.get(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(buffer,
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(buffer.get(pos), versionOneStrictCompliance)) {
// Token
// Token
valueStart = pos;
// getToken returns the position at the delimeter
// or other non-token character
valueEnd = getTokenEndPosition(buffer, 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 && buffer.get(pos) != ';'
&& buffer.get(pos) != ',') {
pos++;
}
pos++;
// Make sure no special avpairs can be attributed to
// the previous cookie by setting the current cookie
// to null
cookie = null;
lazyCookie = 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(buffer.get(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 && buffer.get(pos) != ';' && buffer.get(pos) != ',') {
pos++;
}
pos++;
// All checks passed. Add the cookie, start with the
// special avpairs first
if (cookie != null) {
// Domain is more common, so it goes first
if (lazyCookie.getDomain().isNull() &&
equalsIgnoreCase("Domain", buffer, nameStart, nameEnd)) {
lazyCookie.getDomain().setBuffer(buffer,
valueStart, valueEnd);
continue;
}
// Path
if (lazyCookie.getPath().isNull() &&
equalsIgnoreCase("Path", buffer, nameStart, nameEnd)) {
lazyCookie.getPath().setBuffer(buffer,
valueStart, valueEnd);
continue;
}
// Version
if (CookieUtils.equals("Version", buffer, nameStart, nameEnd)) {
if (rfc6265Enabled) {
continue;
}
// Set version
if (buffer.get(valueStart) == '1'
&& valueEnd == (valueStart + 1)) {
cookie.setVersion(1);
} else {
// unknown version (Versioning is not very strict)
}
continue;
}
// Comment
if (lazyCookie.getComment().isNull() &&
CookieUtils.equals("Comment", buffer, nameStart, nameEnd)) {
lazyCookie.getComment().setBuffer(buffer,
valueStart, valueEnd);
continue;
}
// Max-Age
if (cookie.getMaxAge() == -1 &&
CookieUtils.equals("Max-Age", buffer, nameStart, nameEnd)) {
cookie.setMaxAge(Ascii.parseInt(buffer,
valueStart,
valueEnd - valueStart));
continue;
}
// Expires
if ((cookie.getVersion() == 0 || !cookie.isVersionSet()) && cookie.getMaxAge() == -1 &&
equalsIgnoreCase("Expires", buffer, nameStart, nameEnd)) {
try {
valueEnd = getTokenEndPosition(buffer, valueEnd + 1, end, false);
pos = valueEnd + 1;
final String expiresDate =
buffer.toStringContent(Charsets.ASCII_CHARSET,
valueStart,
valueEnd);
final Date date = OLD_COOKIE_FORMAT.get().parse(expiresDate);
cookie.setMaxAge(getMaxAgeDelta(date.getTime(), System.currentTimeMillis()) / 1000);
} catch (ParseException ignore) {
}
continue;
}
// Secure
if (!cookie.isSecure() &&
equalsIgnoreCase("Secure", buffer, nameStart, nameEnd)) {
lazyCookie.setSecure(true);
continue;
}
// HttpOnly
if (!cookie.isHttpOnly() &&
CookieUtils.equals("HttpOnly", buffer, nameStart, nameEnd)) {
cookie.setHttpOnly(true);
continue;
}
if (CookieUtils.equals("Discard", buffer, nameStart, nameEnd)) {
continue;
}
}
// Normal Cookie
cookie = cookies.getNextUnusedCookie();
if (!rfc6265Enabled && !cookie.isVersionSet()) {
cookie.setVersion(0);
}
lazyCookie = cookie.getLazyCookieState();
lazyCookie.getName().setBuffer(buffer, nameStart, nameEnd);
if (valueStart != -1) { // Normal AVPair
lazyCookie.getValue().setBuffer(buffer, valueStart, valueEnd);
if (isQuoted) {
// We know this is a byte value so this is safe
unescapeDoubleQuotes(lazyCookie.getValue());
}
} else {
// Name Only
lazyCookie.getValue().setString("");
}
}
}