public final void processCookieHeader(byte[] bytes,
int off,
int len) {
if( len< =0 || bytes==null ) return;
int end=off+len;
int pos=off;
int nameStart=0;
int nameEnd=0;
int valueStart=0;
int valueEnd=0;
int version = 0;
ServerCookie sc=null;
boolean isSpecial;
boolean isQuoted;
while (pos < end) {
isSpecial = false;
isQuoted = false;
// Skip whitespace and non-token characters (separators)
while (pos < end &&
(isSeparator(bytes[pos]) || isWhiteSpace(bytes[pos])))
{pos++; }
if (pos >= end)
return;
// Detect Special cookies
if (bytes[pos] == '$') {
isSpecial = true;
pos++;
}
// Get the cookie name. This must be a token
valueEnd = valueStart = nameStart = pos;
pos = nameEnd = getTokenEndPosition(bytes,pos,end,true);
// Skip whitespace
while (pos < end && isWhiteSpace(bytes[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 && bytes[pos] == '=') {
// Skip whitespace
do {
pos++;
} while (pos < end && isWhiteSpace(bytes[pos]));
if (pos >= end)
return;
// Determine what type of value this is, quoted value,
// token, name-only with an '=', or other (bad)
switch (bytes[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(bytes,
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(bytes[pos]) ||
bytes[pos] == '=' && ALLOW_EQUALS_IN_VALUE) {
// Token
valueStart=pos;
// getToken returns the position at the delimeter
// or other non-token character
valueEnd = getTokenEndPosition(bytes, valueStart, end,
false);
// We need pos to advance
pos = valueEnd;
} else {
// INVALID COOKIE, advance to next delimiter
// The starting character of the cookie value was
// not valid.
log("Invalid cookie. Value not a token or quoted value");
while (pos < end && bytes[pos] != ';' &&
bytes[pos] != ',')
{pos++; };
pos++;
// Make sure no special avpairs can be attributed to
// the previous cookie by setting the current cookie
// to null
sc = 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(bytes[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 && bytes[pos] != ';' && bytes[pos] != ',') {
pos++;
}
pos++;
/*
if (nameEnd < = nameStart || valueEnd < valueStart ) {
// Something is wrong, but this may be a case
// of having two ';' characters in a row.
// log("Cookie name/value does not conform to RFC 2965");
// Advance to next delimiter (ignoring everything else)
while (pos < end && bytes[pos] != ';' && bytes[pos] != ',')
{ pos++; };
pos++;
// Make sure no special cookies can be attributed to
// the previous cookie by setting the current cookie
// to null
sc = null;
continue;
}
*/
// 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 (equals( "Version", bytes, nameStart, nameEnd) &&
sc == null) {
// Set version
if( bytes[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 (sc == null) {
continue;
}
// Domain is more common, so it goes first
if (equals( "Domain", bytes, nameStart, nameEnd)) {
sc.getDomain().setBytes( bytes,
valueStart,
valueEnd-valueStart);
continue;
}
if (equals( "Path", bytes, nameStart, nameEnd)) {
sc.getPath().setBytes( bytes,
valueStart,
valueEnd-valueStart);
continue;
}
if (equals( "Port", bytes, nameStart, nameEnd)) {
// sc.getPort is not currently implemented.
// sc.getPort().setBytes( bytes,
// valueStart,
// valueEnd-valueStart );
continue;
}
// Unknown cookie, complain
log("Unknown Special Cookie");
} else { // Normal Cookie
sc = addCookie();
sc.setVersion( version );
sc.getName().setBytes( bytes, nameStart,
nameEnd-nameStart);
if (valueStart != -1) { // Normal AVPair
sc.getValue().setBytes( bytes, valueStart,
valueEnd-valueStart);
if (isQuoted) {
// We know this is a byte value so this is safe
ServerCookie.unescapeDoubleQuotes(
sc.getValue().getByteChunk());
}
} else {
// Name Only
sc.getValue().setString("");
}
continue;
}
}
}
Parses a cookie header after the initial "Cookie:"
[WS][$]token[WS]=[WS](token|QV)[;|,]
RFC 2965
JVK |