package com.laytonsmith.PureUtilities.Web;
import com.laytonsmith.PureUtilities.LinkedComparatorSet;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class manages a list of several cookies. There are several ways to add
* a new cookie to this manager, and the getCookies method returns the pre-parsed
* string that is suitable for direct use in an HTTP request header.
*/
public final class CookieJar {
@Override
public String toString() {
StringBuilder b = new StringBuilder();
for (Cookie cookie : cookies) {
if (!cookie.isExpired()) {
b.append(cookie.getName()).append("=")
.append(cookie.getValue()).append("; used in ")
.append(cookie.getDomain()).append(cookie.getPath())
.append("\n");
}
}
return b.toString();
}
private final Set<Cookie> cookies = new LinkedComparatorSet<Cookie>(new LinkedComparatorSet.EqualsComparator<Cookie>() {
@Override
public boolean checkIfEquals(Cookie val1, Cookie val2) {
return val1.compareTo(val2) == 0;
}
});
/**
* Adds a new, pre-made cookie to this list. The constructors for Cookie
* are capable of parsing the cookies found in a HTTP request.
* @param cookie
*/
public void addCookie(Cookie cookie){
if(this.cookies.contains(cookie)){
//This is an update, so remove it first
this.cookies.remove(cookie);
}
this.cookies.add(cookie);
}
/**
* Returns a string that is suitable to send as is with the Cookie
* HTTP header. The URL is the search url, which will look through this
* cookie jar, and only use the cookies that are applicable to this domain,
* not expired, etc.
* @param url
* @return
*/
public String getCookies(URL url) {
List<Cookie> usable = new ArrayList<Cookie>();
//So we can iterate linearly
List<Cookie> foundCookies = new ArrayList<Cookie>(this.cookies);
for (int i = 0; i < foundCookies.size(); i++) {
Cookie cookie = foundCookies.get(i);
if (cookie.isExpired()) {
//This cookie is expired. Remove it from our list, and continue.
this.cookies.remove(cookie);
foundCookies.remove(i);
i--;
continue;
}
//Or it's secure only, and we aren't in https, continue.
if (cookie.isSecureOnly() && !url.getProtocol().equals("https")) {
continue;
}
//If we aren't in the correct domain
String domain = cookie.getDomain();
if (domain.startsWith(".")) {
domain = domain.substring(1);
}
if (!url.getHost().endsWith(domain)) {
continue;
}
//Or if we aren't in the right path
String path = (url.getPath().startsWith("/")?"":"/") + url.getPath();
if (!path.startsWith(cookie.getPath())) {
continue;
}
//If we're still here, it's good.
usable.add(cookie);
}
if (usable.isEmpty()) {
return null;
}
StringBuilder b = new StringBuilder();
for (Cookie cookie : usable) {
if (b.length() != 0) {
b.append("; ");
}
try {
b.append(URLEncoder.encode(cookie.getName(), "UTF-8")).append("=").append(cookie.getValue());
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(WebUtility.class.getName()).log(Level.SEVERE, null, ex);
}
}
return b.toString();
}
/**
* Clears out all session cookies from this cookie jar. That is, all
* cookies with an expiration of 0 set.
*/
public void clearSessionCookies(){
Iterator<Cookie> it = cookies.iterator();
while(it.hasNext()){
Cookie c = it.next();
if(c.getExpiration() == 0){
it.remove();
}
}
}
/**
* Clears all cookies from this cookie jar.
*/
public void clearAllCookies(){
cookies.clear();
}
/**
* Returns a copy of all the cookies in this cookie jar.
* @return
*/
public Set<Cookie> getAllCookies(){
return new TreeSet<Cookie>(cookies);
}
}