package com.laytonsmith.PureUtilities.Web; import com.laytonsmith.PureUtilities.PublicSuffix; import java.net.URL; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.logging.Level; import java.util.logging.Logger; /** * This class wraps a single HTTP cookie. */ public final class Cookie implements Comparable<Cookie> { private String name; private String value; private String domain; private String path; private long expiration = 0; private boolean httpOnly = false; private boolean secureOnly = false; /** * Given an unparsed value, this adds a new cookie to this cookie list * after parsing the string into a proper cookie, and setting the fields * appropriately. * @param unparsedValue * @param currentURL */ public Cookie(String unparsedValue, URL currentURL) { //Split on ; String[] parts = unparsedValue.split(";"); for (int i = 0; i < parts.length; i++) { String part = parts[i]; if (i == 0) { //This is the actual cookie value String[] nameVal = part.split("=", 2); name = nameVal[0].trim(); value = nameVal[1].trim(); continue; } //The rest of the fields are standard fields String[] keyval = part.split("=", 2); String key = keyval[0].trim().toLowerCase(); String val = null; if (keyval.length >= 2) { val = keyval[1].trim(); } if ("expires".equals(key)) { DateFormat formatter = new SimpleDateFormat("EEE, dd-MMM-yyyy kk:mm:ss zzz"); try { expiration = formatter.parse(val).getTime(); } catch (ParseException ex) { Logger.getLogger(WebUtility.class.getName()).log(Level.SEVERE, null, ex); } } else if ("path".equals(key)) { path = val; } else if ("domain".equals(key)) { //Finish the PublicSuffix stuff to validate this domain. if (PublicSuffix.get().getEffectiveTLDLength(val) != -1) { domain = val; } else { Logger.getLogger(WebUtility.class.getName()).log(Level.SEVERE, "Possible attack cookie being set from " + currentURL + ". Attempted" + " to set " + val + " as the domain."); } } else if ("httponly".equals(key)) { httpOnly = true; } else if ("secureonly".equals(key)) { secureOnly = true; } } if (domain == null) { domain = currentURL.getHost(); } if (path == null) { path = currentURL.getPath(); } } /** * Creates a cookie with only the required parameters set. That is, it creates * a session cookie with httpOnly and secure set to false. * @param domain The domain under which this cookie applies * @param name The name of this cookie * @param value The value of this cookie * @param path The path under which this cookie applies in the domain */ public Cookie(String name, String value, String domain, String path){ this(name, value, domain, path, 0, false, false); } /** * Creates a cookie with all of the various parameters set. * @param domain The domain under which this cookie applies * @param name The name of this cookie * @param value The value of this cookie * @param path The path under which this cookie applies in the domain * @param expiration Sets the expiration date of the cookie. 0 indicates a session cookie. * @param httpOnly Sets whether or not this cookie is httpOnly. Generally, this is an unused field * @param secureOnly Sets whether or not this cookie should only be send via https. */ public Cookie(String name, String value, String domain, String path, long expiration, boolean httpOnly, boolean secureOnly) { this.name = name; this.value = value; this.domain = domain; this.path = path; this.expiration = expiration; this.httpOnly = httpOnly; this.secureOnly = secureOnly; } @Override public int compareTo(Cookie o) { return (this.domain + this.name + this.path).compareTo(o.domain + o.name + o.path); } /** * Returns the domain of this cookie. * @return */ public String getDomain() { return domain; } /** * Returns the name of this cookie. * @return */ public String getName() { return name; } /** * Returns the value of this cookie. * @return */ public String getValue() { return value; } /** * Returns the path under which this cookie applies. * @return */ public String getPath() { return path; } /** * Returns the expiration time of this cookie, in unix time. If the * expiration is 0, the cookie never expires. * @return */ public long getExpiration() { return expiration; } /** * Returns true if this cookie only applies in http, not https requests. * @return */ public boolean isHttpOnly() { return httpOnly; } /** * Returns true if this cookie is only applicable in https, not http requests. * @return */ public boolean isSecureOnly() { return secureOnly; } /** * Returns true if the cookie is currently expired. * @return */ public boolean isExpired(){ return isExpired(System.currentTimeMillis()); } /** * Returns true if the cookie will be or was expired at the given time. * @param time The time to check against to determine if the cookie * will be expired at that time. * @return */ public boolean isExpired(long time){ return expiration != 0 && expiration < time; } @Override public String toString() { return domain + path + ": " + name + "=" + value; } }