Methods Summary |
---|
private static void | assignAttribute(java.net.HttpCookie cookie, java.lang.String attrName, java.lang.String attrValue)
assignors = new java.util.HashMap<String, CookieAttributeAssignor>();
assignors.put("comment", new CookieAttributeAssignor(){
public void assign(HttpCookie cookie, String attrName, String attrValue) {
if (cookie.getComment() == null) cookie.setComment(attrValue);
}
});
assignors.put("commenturl", new CookieAttributeAssignor(){
public void assign(HttpCookie cookie, String attrName, String attrValue) {
if (cookie.getCommentURL() == null) cookie.setCommentURL(attrValue);
}
});
assignors.put("discard", new CookieAttributeAssignor(){
public void assign(HttpCookie cookie, String attrName, String attrValue) {
cookie.setDiscard(true);
}
});
assignors.put("domain", new CookieAttributeAssignor(){
public void assign(HttpCookie cookie, String attrName, String attrValue) {
if (cookie.getDomain() == null) cookie.setDomain(attrValue);
}
});
assignors.put("max-age", new CookieAttributeAssignor(){
public void assign(HttpCookie cookie, String attrName, String attrValue) {
try {
long maxage = Long.parseLong(attrValue);
if (cookie.getMaxAge() == MAX_AGE_UNSPECIFIED) cookie.setMaxAge(maxage);
} catch (NumberFormatException ignored) {
throw new IllegalArgumentException("Illegal cookie max-age attribute");
}
}
});
assignors.put("path", new CookieAttributeAssignor(){
public void assign(HttpCookie cookie, String attrName, String attrValue) {
if (cookie.getPath() == null) cookie.setPath(attrValue);
}
});
assignors.put("port", new CookieAttributeAssignor(){
public void assign(HttpCookie cookie, String attrName, String attrValue) {
if (cookie.getPortlist() == null) cookie.setPortlist(attrValue);
}
});
assignors.put("secure", new CookieAttributeAssignor(){
public void assign(HttpCookie cookie, String attrName, String attrValue) {
cookie.setSecure(true);
}
});
assignors.put("version", new CookieAttributeAssignor(){
public void assign(HttpCookie cookie, String attrName, String attrValue) {
try {
int version = Integer.parseInt(attrValue);
cookie.setVersion(version);
} catch (NumberFormatException ignored) {
throw new IllegalArgumentException("Illegal cookie version attribute");
}
}
});
assignors.put("expires", new CookieAttributeAssignor(){ // Netscape only
public void assign(HttpCookie cookie, String attrName, String attrValue) {
if (cookie.getMaxAge() == MAX_AGE_UNSPECIFIED) {
cookie.setMaxAge(cookie.expiryDate2DeltaSeconds(attrValue));
}
}
});
// strip off the surrounding "-sign if there's any
attrValue = stripOffSurroundingQuote(attrValue);
CookieAttributeAssignor assignor = assignors.get(attrName.toLowerCase());
if (assignor != null) {
assignor.assign(cookie, attrName, attrValue);
} else {
// must be an error
throw new IllegalArgumentException("Illegal cookie attribute");
}
|
public java.lang.Object | clone()Create and return a copy of this object.
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e.getMessage());
}
|
public static boolean | domainMatches(java.lang.String domain, java.lang.String host)The utility method to check whether a host name is in a domain
or not.
This concept is described in the cookie specification.
To understand the concept, some terminologies need to be defined first:
effective host name = hostname if host name contains dot
or = hostname.local if not
Host A's name domain-matches host B's if:
- their host name strings string-compare equal; or
- A is a HDN string and has the form NB, where N is a non-empty
name string, B has the form .B', and B' is a HDN string. (So,
x.y.com domain-matches .Y.com but not Y.com.)
A host isn't in a domain (RFC 2965 sec. 3.3.2) if:
- The value for the Domain attribute contains no embedded dots,
and the value is not .local.
- The effective host name that derives from the request-host does
not domain-match the Domain attribute.
- The request-host is a HDN (not IP address) and has the form HD,
where D is the value of the Domain attribute, and H is a string
that contains one or more dots.
Examples:
- A Set-Cookie2 from request-host y.x.foo.com for Domain=.foo.com
would be rejected, because H is y.x and contains a dot.
- A Set-Cookie2 from request-host x.foo.com for Domain=.foo.com
would be accepted.
- A Set-Cookie2 with Domain=.com or Domain=.com., will always be
rejected, because there is no embedded dot.
- A Set-Cookie2 with Domain=ajax.com will be accepted, and the
value for Domain will be taken to be .ajax.com, because a dot
gets prepended to the value.
- A Set-Cookie2 from request-host example for Domain=.local will
be accepted, because the effective host name for the request-
host is example.local, and example.local domain-matches .local.
if (domain == null || host == null)
return false;
// if there's no embedded dot in domain and domain is not .local
boolean isLocalDomain = ".local".equalsIgnoreCase(domain);
int embeddedDotInDomain = domain.indexOf('.");
if (embeddedDotInDomain == 0)
embeddedDotInDomain = domain.indexOf('.", 1);
if (!isLocalDomain
&& (embeddedDotInDomain == -1 || embeddedDotInDomain == domain.length() - 1))
return false;
// if the host name contains no dot and the domain name is .local
int firstDotInHost = host.indexOf('.");
if (firstDotInHost == -1 && isLocalDomain)
return true;
int domainLength = domain.length();
int lengthDiff = host.length() - domainLength;
if (lengthDiff == 0) {
// if the host name and the domain name are just string-compare euqal
return host.equalsIgnoreCase(domain);
}
else if (lengthDiff > 0) {
// need to check H & D component
String H = host.substring(0, lengthDiff);
String D = host.substring(lengthDiff);
return (H.indexOf('.") == -1 && D.equalsIgnoreCase(domain));
}
else if (lengthDiff == -1) {
// if domain is actually .host
return (domain.charAt(0) == '." &&
host.equalsIgnoreCase(domain.substring(1)));
}
return false;
|
public boolean | equals(java.lang.Object obj)Test the equality of two http cookies.
The result is true only if two cookies
come from same domain (case-insensitive),
have same name (case-insensitive),
and have same path (case-sensitive).
if (obj == this)
return true;
if (!(obj instanceof HttpCookie))
return false;
HttpCookie other = (HttpCookie)obj;
// One http cookie equals to another cookie (RFC 2965 sec. 3.3.3) if:
// 1. they come from same domain (case-insensitive),
// 2. have same name (case-insensitive),
// 3. and have same path (case-sensitive).
return equalsIgnoreCase(getName(), other.getName()) &&
equalsIgnoreCase(getDomain(), other.getDomain()) &&
equals(getPath(), other.getPath());
|
private static boolean | equals(java.lang.String s, java.lang.String t)
if (s == t) return true;
if ((s != null) && (t != null)) {
return s.equals(t);
}
return false;
|
private static boolean | equalsIgnoreCase(java.lang.String s, java.lang.String t)
if (s == t) return true;
if ((s != null) && (t != null)) {
return s.equalsIgnoreCase(t);
}
return false;
|
private long | expiryDate2DeltaSeconds(java.lang.String dateString)
SimpleDateFormat df = new SimpleDateFormat(NETSCAPE_COOKIE_DATE_FORMAT);
df.setTimeZone(TimeZone.getTimeZone("GMT"));
try {
Date date = df.parse(dateString);
return (date.getTime() - whenCreated) / 1000;
} catch (Exception e) {
return 0;
}
|
public java.lang.String | getComment()Returns the comment describing the purpose of this cookie, or
null if the cookie has no comment.
return comment;
|
public java.lang.String | getCommentURL()Returns the comment url describing the purpose of this cookie, or
null if the cookie has no comment url.
return commentURL;
|
public boolean | getDiscard()Return the discard attribute of the cookie
return toDiscard;
|
public java.lang.String | getDomain()Returns the domain name set for this cookie. The form of
the domain name is set by RFC 2965.
return domain;
|
public long | getMaxAge()Returns the maximum age of the cookie, specified in seconds.
By default, -1 indicating the cookie will persist
until browser shutdown.
return maxAge;
|
public java.lang.String | getName()Returns the name of the cookie. The name cannot be changed after
creation.
return name;
|
public java.lang.String | getPath()Returns the path on the server
to which the browser returns this cookie. The
cookie is visible to all subpaths on the server.
return path;
|
public java.lang.String | getPortlist()Return the port list attribute of the cookie
return portlist;
|
public boolean | getSecure()Returns true if the browser is sending cookies
only over a secure protocol, or false if the
browser can send cookies using any protocol.
return secure;
|
public java.lang.String | getValue()Returns the value of the cookie.
return value;
|
public int | getVersion()Returns the version of the protocol this cookie complies
with. Version 1 complies with RFC 2965/2109,
and version 0 complies with the original
cookie specification drafted by Netscape. Cookies provided
by a browser use and identify the browser's cookie version.
return version;
|
private static int | guessCookieVersion(java.lang.String header)
int version = 0;
header = header.toLowerCase();
if (header.indexOf("expires=") != -1) {
// only netscape cookie using 'expires'
version = 0;
} else if (header.indexOf("version=") != -1) {
// version is mandatory for rfc 2965/2109 cookie
version = 1;
} else if (header.indexOf("max-age") != -1) {
// rfc 2965/2109 use 'max-age'
version = 1;
} else if (startsWithIgnoreCase(header, SET_COOKIE2)) {
// only rfc 2965 cookie starts with 'set-cookie2'
version = 1;
}
return version;
|
public boolean | hasExpired()Reports whether this http cookie has expired or not.
if (maxAge == 0) return true;
// if not specify max-age, this cookie should be
// discarded when user agent is to be closed, but
// it is not expired.
if (maxAge == MAX_AGE_UNSPECIFIED) return false;
long deltaSecond = (System.currentTimeMillis() - whenCreated) / 1000;
if (deltaSecond > maxAge)
return true;
else
return false;
|
public int | hashCode()Return hash code of this http cookie. The result is the sum of
hash code value of three significant components of this cookie:
name, domain, and path.
That is, the hash code is the value of the expression:
getName().toLowerCase().hashCode()
+ getDomain().toLowerCase().hashCode()
+ getPath().hashCode()
int h1 = name.toLowerCase().hashCode();
int h2 = (domain!=null) ? domain.toLowerCase().hashCode() : 0;
int h3 = (path!=null) ? path.hashCode() : 0;
return h1 + h2 + h3;
|
private static boolean | isReserved(java.lang.String name)
if (name.equalsIgnoreCase("Comment")
|| name.equalsIgnoreCase("CommentURL") // rfc2965 only
|| name.equalsIgnoreCase("Discard") // rfc2965 only
|| name.equalsIgnoreCase("Domain")
|| name.equalsIgnoreCase("Expires") // netscape draft only
|| name.equalsIgnoreCase("Max-Age")
|| name.equalsIgnoreCase("Path")
|| name.equalsIgnoreCase("Port") // rfc2965 only
|| name.equalsIgnoreCase("Secure")
|| name.equalsIgnoreCase("Version")
|| name.charAt(0) == '$")
{
return true;
}
return false;
|
private static boolean | isToken(java.lang.String value)
/*
* Tests a string and returns true if the string counts as a
* token.
*
* @param value the <code>String</code> to be tested
*
* @return <code>true</code> if the <code>String</code> is
* a token; <code>false</code> if it is not
*/
int len = value.length();
for (int i = 0; i < len; i++) {
char c = value.charAt(i);
if (c < 0x20 || c >= 0x7f || tspecials.indexOf(c) != -1)
return false;
}
return true;
|
public static java.util.List | parse(java.lang.String header)Constructs cookies from set-cookie or set-cookie2 header string.
RFC 2965 section 3.2.2 set-cookie2 syntax indicates that one header line
may contain more than one cookie definitions, so this is a static
utility method instead of another constructor.
int version = guessCookieVersion(header);
// if header start with set-cookie or set-cookie2, strip it off
if (startsWithIgnoreCase(header, SET_COOKIE2)) {
header = header.substring(SET_COOKIE2.length());
} else if (startsWithIgnoreCase(header, SET_COOKIE)) {
header = header.substring(SET_COOKIE.length());
}
List<HttpCookie> cookies = new java.util.ArrayList<HttpCookie>();
// The Netscape cookie may have a comma in its expires attribute,
// while the comma is the delimiter in rfc 2965/2109 cookie header string.
// so the parse logic is slightly different
if (version == 0) {
// Netscape draft cookie
HttpCookie cookie = parseInternal(header);
cookie.setVersion(0);
cookies.add(cookie);
} else {
// rfc2965/2109 cookie
// if header string contains more than one cookie,
// it'll separate them with comma
List<String> cookieStrings = splitMultiCookies(header);
for (String cookieStr : cookieStrings) {
HttpCookie cookie = parseInternal(cookieStr);
cookie.setVersion(1);
cookies.add(cookie);
}
}
return cookies;
|
private static java.net.HttpCookie | parseInternal(java.lang.String header)
HttpCookie cookie = null;
String namevaluePair = null;
StringTokenizer tokenizer = new StringTokenizer(header, ";");
// there should always have at least on name-value pair;
// it's cookie's name
try {
namevaluePair = tokenizer.nextToken();
int index = namevaluePair.indexOf('=");
if (index != -1) {
String name = namevaluePair.substring(0, index).trim();
String value = namevaluePair.substring(index + 1).trim();
cookie = new HttpCookie(name, stripOffSurroundingQuote(value));
} else {
// no "=" in name-value pair; it's an error
throw new IllegalArgumentException("Invalid cookie name-value pair");
}
} catch (NoSuchElementException ignored) {
throw new IllegalArgumentException("Empty cookie header string");
}
// remaining name-value pairs are cookie's attributes
while (tokenizer.hasMoreTokens()) {
namevaluePair = tokenizer.nextToken();
int index = namevaluePair.indexOf('=");
String name, value;
if (index != -1) {
name = namevaluePair.substring(0, index).trim();
value = namevaluePair.substring(index + 1).trim();
} else {
name = namevaluePair.trim();
value = null;
}
// assign attribute to cookie
assignAttribute(cookie, name, value);
}
return cookie;
|
public void | setComment(java.lang.String purpose)Specifies a comment that describes a cookie's purpose.
The comment is useful if the browser presents the cookie
to the user. Comments
are not supported by Netscape Version 0 cookies.
comment = purpose;
|
public void | setCommentURL(java.lang.String purpose)Specifies a comment url that describes a cookie's purpose.
The comment url is useful if the browser presents the cookie
to the user. Comment url is RFC 2965 only.
commentURL = purpose;
|
public void | setDiscard(boolean discard)Specify whether user agent should discard the cookie unconditionally.
This is RFC 2965 only attribute.
toDiscard = discard;
|
public void | setDomain(java.lang.String pattern)Specifies the domain within which this cookie should be presented.
The form of the domain name is specified by RFC 2965. A domain
name begins with a dot (.foo.com ) and means that
the cookie is visible to servers in a specified Domain Name System
(DNS) zone (for example, www.foo.com , but not
a.b.foo.com ). By default, cookies are only returned
to the server that sent them.
if (pattern != null)
domain = pattern.toLowerCase();
else
domain = pattern;
|
public void | setMaxAge(long expiry)Sets the maximum age of the cookie in seconds.
A positive value indicates that the cookie will expire
after that many seconds have passed. Note that the value is
the maximum age when the cookie will expire, not the cookie's
current age.
A negative value means
that the cookie is not stored persistently and will be deleted
when the Web browser exits. A zero value causes the cookie
to be deleted.
maxAge = expiry;
|
public void | setPath(java.lang.String uri)Specifies a path for the cookie
to which the client should return the cookie.
The cookie is visible to all the pages in the directory
you specify, and all the pages in that directory's subdirectories.
A cookie's path must include the servlet that set the cookie,
for example, /catalog, which makes the cookie
visible to all directories on the server under /catalog.
Consult RFC 2965 (available on the Internet) for more
information on setting path names for cookies.
path = uri;
|
public void | setPortlist(java.lang.String ports)Specify the portlist of the cookie, which restricts the port(s)
to which a cookie may be sent back in a Cookie header.
portlist = ports;
|
public void | setSecure(boolean flag)Indicates to the browser whether the cookie should only be sent
using a secure protocol, such as HTTPS or SSL.
The default value is false .
secure = flag;
|
public void | setValue(java.lang.String newValue)Assigns a new value to a cookie after the cookie is created.
If you use a binary value, you may want to use BASE64 encoding.
With Version 0 cookies, values should not contain white
space, brackets, parentheses, equals signs, commas,
double quotes, slashes, question marks, at signs, colons,
and semicolons. Empty values may not behave the same way
on all browsers.
value = newValue;
|
public void | setVersion(int v)Sets the version of the cookie protocol this cookie complies
with. Version 0 complies with the original Netscape cookie
specification. Version 1 complies with RFC 2965/2109.
if (v != 0 && v != 1) {
throw new IllegalArgumentException("cookie version should be 0 or 1");
}
version = v;
|
private static java.util.List | splitMultiCookies(java.lang.String header)
List<String> cookies = new java.util.ArrayList<String>();
int quoteCount = 0;
int p, q;
for (p = 0, q = 0; p < header.length(); p++) {
char c = header.charAt(p);
if (c == '"") quoteCount++;
if (c == '," && (quoteCount % 2 == 0)) { // it is comma and not surrounding by double-quotes
cookies.add(header.substring(q, p));
q = p + 1;
}
}
cookies.add(header.substring(q));
return cookies;
|
private static boolean | startsWithIgnoreCase(java.lang.String s, java.lang.String start)
if (s == null || start == null) return false;
if (s.length() >= start.length() &&
start.equalsIgnoreCase(s.substring(0, start.length()))) {
return true;
}
return false;
|
private static java.lang.String | stripOffSurroundingQuote(java.lang.String str)
if (str != null && str.length() > 0 &&
str.charAt(0) == '"" && str.charAt(str.length() - 1) == '"") {
return str.substring(1, str.length() - 1);
} else {
return str;
}
|
private java.lang.String | toNetscapeHeaderString()
StringBuilder sb = new StringBuilder();
sb.append(getName() + "=" + getValue());
return sb.toString();
|
private java.lang.String | toRFC2965HeaderString()
StringBuilder sb = new StringBuilder();
sb.append(getName()).append("=\"").append(getValue()).append('"");
if (getPath() != null)
sb.append(";$Path=\"").append(getPath()).append('"");
if (getDomain() != null)
sb.append(";$Domain=\"").append(getDomain()).append('"");
if (getPortlist() != null)
sb.append(";$Port=\"").append(getPortlist()).append('"");
return sb.toString();
|
public java.lang.String | toString()Constructs a cookie header string representation of this cookie,
which is in the format defined by corresponding cookie specification,
but without the leading "Cookie:" token.
if (getVersion() > 0) {
return toRFC2965HeaderString();
} else {
return toNetscapeHeaderString();
}
|