Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * Copyright (C) 2006 The Android Open Source Project
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    *      http://www.apache.org/licenses/LICENSE-2.0
    *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package android.webkit;
  
  import android.util.Log;
  
  
  import java.util.Arrays;
  import java.util.Map;
  import java.util.TreeSet;

CookieManager manages cookies according to RFC2109 spec.
  
  public final class CookieManager {
  
      private static CookieManager sRef;
  
      private static final String LOGTAG = "webkit";
  
      private static final String DOMAIN = "domain";
  
      private static final String PATH = "path";
  
      private static final String EXPIRES = "expires";
  
      private static final String SECURE = "secure";
  
      private static final String MAX_AGE = "max-age";
  
      private static final String HTTP_ONLY = "httponly";
  
      private static final String HTTPS = "https";
  
      private static final char PERIOD = '.';
  
      private static final char COMMA = ',';
  
      private static final char SEMICOLON = ';';
  
      private static final char EQUAL = '=';
  
      private static final char PATH_DELIM = '/';
  
      private static final char QUESTION_MARK = '?';
  
      private static final char WHITE_SPACE = ' ';
  
      private static final char QUOTATION = '\"';
  
      private static final int SECURE_LENGTH = .length();
  
      private static final int HTTP_ONLY_LENGTH = .length();
  
      // RFC2109 defines 4k as maximum size of a cookie
      private static final int MAX_COOKIE_LENGTH = 4 * 1024;
  
      // RFC2109 defines 20 as max cookie count per domain. As we track with base
      // domain, we allow 50 per base domain
      private static final int MAX_COOKIE_COUNT_PER_BASE_DOMAIN = 50;
  
      // RFC2109 defines 300 as max count of domains. As we track with base
      // domain, we set 200 as max base domain count
      private static final int MAX_DOMAIN_COUNT = 200;
  
      // max cookie count to limit RAM cookie takes less than 100k, it is based on
      // average cookie entry size is less than 100 bytes
      private static final int MAX_RAM_COOKIES_COUNT = 1000;
  
      //  max domain count to limit RAM cookie takes less than 100k,
      private static final int MAX_RAM_DOMAIN_COUNT = 15;
  
      private Map<StringArrayList<Cookie>> mCookieMap = new LinkedHashMap
              <StringArrayList<Cookie>>(, 0.75f, true);
  
      private boolean mAcceptCookie = true;

    
This contains a list of 2nd-level domains that aren't allowed to have wildcards when combined with country-codes. For example: [.co.uk].
 
     private final static String[] BAD_COUNTRY_2LDS =
           { "ac""co""com""ed""edu""go""gouv""gov""info",
             "lg""ne""net""or""org" };
 
     static {
         Arrays.sort();
     }

    
Package level class to be accessed by cookie sync manager
 
     static class Cookie {
         static final byte MODE_NEW = 0;
 
         static final byte MODE_NORMAL = 1;
 
         static final byte MODE_DELETED = 2;
 
         static final byte MODE_REPLACED = 3;
 
         String domain;
 
         String path;
 
         String name;
 
         String value;
 
         long expires;
 
         long lastAcessTime;
 
         long lastUpdateTime;
 
         boolean secure;
 
         byte mode;
 
         Cookie() {
         }
 
         Cookie(String defaultDomainString defaultPath) {
              = defaultDomain;
              = defaultPath;
              = -1;
         }
 
         boolean exactMatch(Cookie in) {
             // An exact match means that domain, path, and name are equal. If
             // both values are null, the cookies match. If both values are
             // non-null, the cookies match. If one value is null and the other
             // is non-null, the cookies do not match (i.e. "foo=;" and "foo;")
             boolean valuesMatch = !(( == null) ^ (in.value == null));
             return .equals(in.domain) && .equals(in.path) &&
                     .equals(in.name) && valuesMatch;
         }
 
         boolean domainMatch(String urlHost) {
             if (.startsWith(".")) {
                 if (urlHost.endsWith(.substring(1))) {
                     int len = .length();
                     int urlLen = urlHost.length();
                     if (urlLen > len - 1) {
                         // make sure bar.com doesn't match .ar.com
                         return urlHost.charAt(urlLen - len) == ;
                     }
                     return true;
                 }
                 return false;
             } else {
                 // exact match if domain is not leading w/ dot
                 return urlHost.equals();
             }
         }
 
         boolean pathMatch(String urlPath) {
             if (urlPath.startsWith()) {
                 int len = .length();
                 if (len == 0) {
                     Log.w("Empty cookie path");
                     return false;
                 }
                 int urlLen = urlPath.length();
                 if (.charAt(len-1) !=  && urlLen > len) {
                     // make sure /wee doesn't match /we
                     return urlPath.charAt(len) == ;
                 }
                 return true;
             }
             return false;
         }
 
         public String toString() {
             return "domain: " +  + "; path: " +  + "; name: " + 
                     + "; value: " + ;
         }
     }
 
     private static final CookieComparator COMPARATOR = new CookieComparator();
 
     private static final class CookieComparator implements Comparator<Cookie> {
         public int compare(Cookie cookie1Cookie cookie2) {
             // According to RFC 2109, multiple cookies are ordered in a way such
             // that those with more specific Path attributes precede those with
             // less specific. Ordering with respect to other attributes (e.g.,
             // Domain) is unspecified.
             // As Set is not modified if the two objects are same, we do want to
             // assign different value for each cookie.
             int diff = cookie2.path.length() - cookie1.path.length();
             if (diff != 0) return diff;
 
             diff = cookie2.domain.length() - cookie1.domain.length();
             if (diff != 0) return diff;
 
             // If cookie2 has a null value, it should come later in
             // the list.
             if (cookie2.value == null) {
                 // If both cookies have null values, fall back to using the name
                 // difference.
                 if (cookie1.value != null) {
                     return -1;
                 }
             } else if (cookie1.value == null) {
                 // Now we know that cookie2 does not have a null value, if
                 // cookie1 has a null value, place it later in the list.
                 return 1;
             }
 
             // Fallback to comparing the name to ensure consistent order.
             return cookie1.name.compareTo(cookie2.name);
         }
     }
 
     private CookieManager() {
     }
 
     protected Object clone() throws CloneNotSupportedException {
         throw new CloneNotSupportedException("doesn't implement Cloneable");
     }

    
Get a singleton CookieManager. If this is called before any WebView is created or outside of WebView context, the caller needs to call CookieSyncManager#createInstance(Context ) first.

Returns:
CookieManager
 
     public static synchronized CookieManager getInstance() {
         if ( == null) {
              = new CookieManager();
         }
         return ;
     }

    
Control whether cookie is enabled or disabled

Parameters:
accept TRUE if accept cookie
 
     public synchronized void setAcceptCookie(boolean accept) {
          = accept;
     }

    
Return whether cookie is enabled

Returns:
TRUE if accept cookie
 
     public synchronized boolean acceptCookie() {
         return ;
     }

    
Set cookie for a given url. The old cookie with same host/path/name will be removed. The new cookie will be added if it is not expired or it does not have expiration which implies it is session cookie.

Parameters:
url The url which cookie is set for
value The value for set-cookie: in http response header
 
     public void setCookie(String urlString value) {
         WebAddress uri;
         try {
             uri = new WebAddress(url);
         } catch (ParseException ex) {
             Log.e("Bad address: " + url);
             return;
         }
         setCookie(urivalue);
     }

    
Set cookie for a given uri. The old cookie with same host/path/name will be removed. The new cookie will be added if it is not expired or it does not have expiration which implies it is session cookie.

Parameters:
uri The uri which cookie is set for
value The value for set-cookie: in http response header
Hide:
- hide this because it takes in a parameter of type WebAddress, a system private class.
 
     public synchronized void setCookie(WebAddress uriString value) {
         if (value != null && value.length() > ) {
             return;
         }
         if (! || uri == null) {
             return;
         }
         if (.) {
             Log.v("setCookie: uri: " + uri + " value: " + value);
         }
 
         String[] hostAndPath = getHostAndPath(uri);
         if (hostAndPath == null) {
             return;
         }
         
         // For default path, when setting a cookie, the spec says:
         //Path:   Defaults to the path of the request URL that generated the
         // Set-Cookie response, up to, but not including, the
         // right-most /.
         if (hostAndPath[1].length() > 1) {
             int index = hostAndPath[1].lastIndexOf();
             hostAndPath[1] = hostAndPath[1].substring(0, 
                     index > 0 ? index : index + 1);
         }
 
         ArrayList<Cookiecookies = null;
         try {
             cookies = parseCookie(hostAndPath[0], hostAndPath[1], value);
         } catch (RuntimeException ex) {
             Log.e("parse cookie failed for: " + value);
         }
 
         if (cookies == null || cookies.size() == 0) {
             return;
         }
 
         String baseDomain = getBaseDomain(hostAndPath[0]);
         ArrayList<CookiecookieList = .get(baseDomain);
         if (cookieList == null) {
             cookieList = CookieSyncManager.getInstance()
                     .getCookiesForDomain(baseDomain);
             .put(baseDomaincookieList);
         }
 
         long now = System.currentTimeMillis();
         int size = cookies.size();
         for (int i = 0; i < sizei++) {
             Cookie cookie = cookies.get(i);
 
             boolean done = false;
             Iterator<Cookieiter = cookieList.iterator();
             while (iter.hasNext()) {
                 Cookie cookieEntry = iter.next();
                 if (cookie.exactMatch(cookieEntry)) {
                     // expires == -1 means no expires defined. Otherwise
                     // negative means far future
                     if (cookie.expires < 0 || cookie.expires > now) {
                         // secure cookies can't be overwritten by non-HTTPS url
                         if (!cookieEntry.secure || .equals(uri.mScheme)) {
                             cookieEntry.value = cookie.value;
                             cookieEntry.expires = cookie.expires;
                             cookieEntry.secure = cookie.secure;
                             cookieEntry.lastAcessTime = now;
                             cookieEntry.lastUpdateTime = now;
                             cookieEntry.mode = .;
                         }
                     } else {
                         cookieEntry.lastUpdateTime = now;
                         cookieEntry.mode = .;
                     }
                     done = true;
                     break;
                 }
             }
 
             // expires == -1 means no expires defined. Otherwise negative means
             // far future
             if (!done && (cookie.expires < 0 || cookie.expires > now)) {
                 cookie.lastAcessTime = now;
                 cookie.lastUpdateTime = now;
                 cookie.mode = .;
                 if (cookieList.size() > ) {
                     Cookie toDelete = new Cookie();
                     toDelete.lastAcessTime = now;
                     Iterator<Cookieiter2 = cookieList.iterator();
                     while (iter2.hasNext()) {
                         Cookie cookieEntry2 = iter2.next();
                         if ((cookieEntry2.lastAcessTime < toDelete.lastAcessTime)
                                 && cookieEntry2.mode != .) {
                             toDelete = cookieEntry2;
                         }
                     }
                     toDelete.mode = .;
                 }
                 cookieList.add(cookie);
             }
         }
     }

    
Get cookie(s) for a given url so that it can be set to "cookie:" in http request header.

Parameters:
url The url needs cookie
Returns:
The cookies in the format of NAME=VALUE [; NAME=VALUE]
 
     public String getCookie(String url) {
         WebAddress uri;
         try {
             uri = new WebAddress(url);
         } catch (ParseException ex) {
             Log.e("Bad address: " + url);
             return null;
         }
         return getCookie(uri);
     }

    
Get cookie(s) for a given uri so that it can be set to "cookie:" in http request header.

Parameters:
uri The uri needs cookie
Returns:
The cookies in the format of NAME=VALUE [; NAME=VALUE]
Hide:
- hide this because it has a parameter of type WebAddress, which is a system private class.
 
     public synchronized String getCookie(WebAddress uri) {
         if (! || uri == null) {
             return null;
         }
    
         String[] hostAndPath = getHostAndPath(uri);
         if (hostAndPath == null) {
             return null;
         }
 
         String baseDomain = getBaseDomain(hostAndPath[0]);
         ArrayList<CookiecookieList = .get(baseDomain);
         if (cookieList == null) {
             cookieList = CookieSyncManager.getInstance()
                     .getCookiesForDomain(baseDomain);
             .put(baseDomaincookieList);
         }
 
         long now = System.currentTimeMillis();
         boolean secure = .equals(uri.mScheme);
         Iterator<Cookieiter = cookieList.iterator();
 
         SortedSet<CookiecookieSet = new TreeSet<Cookie>();
         while (iter.hasNext()) {
             Cookie cookie = iter.next();
             if (cookie.domainMatch(hostAndPath[0]) &&
                     cookie.pathMatch(hostAndPath[1])
                     // expires == -1 means no expires defined. Otherwise
                     // negative means far future
                     && (cookie.expires < 0 || cookie.expires > now)
                     && (!cookie.secure || secure)
                     && cookie.mode != .) {
                 cookie.lastAcessTime = now;
                 cookieSet.add(cookie);
             }
         }
 
         StringBuilder ret = new StringBuilder(256);
         Iterator<CookiesetIter = cookieSet.iterator();
         while (setIter.hasNext()) {
             Cookie cookie = setIter.next();
             if (ret.length() > 0) {
                 ret.append();
                 // according to RC2109, SEMICOLON is official separator,
                 // but when log in yahoo.com, it needs WHITE_SPACE too.
                 ret.append();
             }
 
             ret.append(cookie.name);
             if (cookie.value != null) {
                 ret.append();
                 ret.append(cookie.value);
             }
         }
 
         if (ret.length() > 0) {
             if (.) {
                 Log.v("getCookie: uri: " + uri + " value: " + ret);
             }
             return ret.toString();
         } else {
             if (.) {
                 Log.v("getCookie: uri: " + uri
                         + " But can't find cookie.");
             }
             return null;
         }
     }

    
Remove all session cookies, which are cookies without expiration date
 
     public void removeSessionCookie() {
         final Runnable clearCache = new Runnable() {
             public void run() {
                 synchronized(CookieManager.this) {
                     Collection<ArrayList<Cookie>> cookieList = .values();
                     Iterator<ArrayList<Cookie>> listIter = cookieList.iterator();
                     while (listIter.hasNext()) {
                         ArrayList<Cookielist = listIter.next();
                         Iterator<Cookieiter = list.iterator();
                         while (iter.hasNext()) {
                             Cookie cookie = iter.next();
                             if (cookie.expires == -1) {
                                 iter.remove();
                             }
                         }
                     }
                     CookieSyncManager.getInstance().clearSessionCookies();
                 }
             }
         };
         new Thread(clearCache).start();
     }

    
Remove all cookies
 
     public void removeAllCookie() {
         final Runnable clearCache = new Runnable() {
             public void run() {
                 synchronized(CookieManager.this) {
                      = new LinkedHashMap<StringArrayList<Cookie>>(
                             , 0.75f, true);
                     CookieSyncManager.getInstance().clearAllCookies();
                 }
             }
         };
         new Thread(clearCache).start();
     }

    
Return true if there are stored cookies.
 
     public synchronized boolean hasCookies() {
         return CookieSyncManager.getInstance().hasCookies();
     }

    
Remove all expired cookies
 
     public void removeExpiredCookie() {
         final Runnable clearCache = new Runnable() {
             public void run() {
                 synchronized(CookieManager.this) {
                     long now = System.currentTimeMillis();
                     Collection<ArrayList<Cookie>> cookieList = .values();
                     Iterator<ArrayList<Cookie>> listIter = cookieList.iterator();
                     while (listIter.hasNext()) {
                         ArrayList<Cookielist = listIter.next();
                         Iterator<Cookieiter = list.iterator();
                         while (iter.hasNext()) {
                             Cookie cookie = iter.next();
                             // expires == -1 means no expires defined. Otherwise 
                             // negative means far future
                             if (cookie.expires > 0 && cookie.expires < now) {
                                 iter.remove();
                             }
                         }
                     }
                     CookieSyncManager.getInstance().clearExpiredCookies(now);
                 }
             }
         };
         new Thread(clearCache).start();
     }

    
Package level api, called from CookieSyncManager Get a list of cookies which are updated since a given time.

Parameters:
last The given time in millisec
Returns:
A list of cookies
 
     synchronized ArrayList<CookiegetUpdatedCookiesSince(long last) {
         ArrayList<Cookiecookies = new ArrayList<Cookie>();
         Collection<ArrayList<Cookie>> cookieList = .values();
         Iterator<ArrayList<Cookie>> listIter = cookieList.iterator();
         while (listIter.hasNext()) {
             ArrayList<Cookielist = listIter.next();
             Iterator<Cookieiter = list.iterator();
             while (iter.hasNext()) {
                 Cookie cookie = iter.next();
                 if (cookie.lastUpdateTime > last) {
                     cookies.add(cookie);
                 }
             }
         }
         return cookies;
     }

    
Package level api, called from CookieSyncManager Delete a Cookie in the RAM

Parameters:
cookie Cookie to be deleted
 
     synchronized void deleteACookie(Cookie cookie) {
         if (cookie.mode == .) {
             String baseDomain = getBaseDomain(cookie.domain);
             ArrayList<CookiecookieList = .get(baseDomain);
             if (cookieList != null) {
                 cookieList.remove(cookie);
                 if (cookieList.isEmpty()) {
                     .remove(baseDomain);
                 }
             }
         }
     }

    
Package level api, called from CookieSyncManager Called after a cookie is synced to FLASH

Parameters:
cookie Cookie to be synced
 
     synchronized void syncedACookie(Cookie cookie) {
         cookie.mode = .;
     }

    
Package level api, called from CookieSyncManager Delete the least recent used domains if the total cookie count in RAM exceeds the limit

Returns:
A list of cookies which are removed from RAM
 
     synchronized ArrayList<CookiedeleteLRUDomain() {
         int count = 0;
         int byteCount = 0;
         int mapSize = .size();
 
         if (mapSize < ) {
             Collection<ArrayList<Cookie>> cookieLists = .values();
             Iterator<ArrayList<Cookie>> listIter = cookieLists.iterator();
             while (listIter.hasNext() && count < ) {
                 ArrayList<Cookielist = listIter.next();
                 if (.) {
                     Iterator<Cookieiter = list.iterator();
                     while (iter.hasNext() && count < ) {
                         Cookie cookie = iter.next();
                         // 14 is 3 * sizeof(long) + sizeof(boolean)
                         // + sizeof(byte)
                         byteCount += cookie.domain.length()
                                 + cookie.path.length()
                                 + cookie.name.length()
                                 + (cookie.value != null
                                         ? cookie.value.length()
                                         : 0)
                                 + 14;
                         count++;
                     }
                 } else {
                     count += list.size();
                 }
             }
         }
 
         ArrayList<Cookieretlist = new ArrayList<Cookie>();
         if (mapSize >=  || count >= ) {
             if (.) {
                 Log.v(count + " cookies used " + byteCount
                         + " bytes with " + mapSize + " domains");
             }
             Object[] domains = .keySet().toArray();
             int toGo = mapSize / 10 + 1;
             while (toGo-- > 0){
                 String domain = domains[toGo].toString();
                 if (.) {
                     Log.v("delete domain: " + domain
                             + " from RAM cache");
                 }
                 retlist.addAll(.get(domain));
                 .remove(domain);
             }
         }
         return retlist;
     }

    
Extract the host and path out of a uri

Parameters:
uri The given WebAddress
Returns:
The host and path in the format of String[], String[0] is host which has at least two periods, String[1] is path which always ended with "/"
 
     private String[] getHostAndPath(WebAddress uri) {
         if (uri.mHost != null && uri.mPath != null) {
 
             /*
              * The domain (i.e. host) portion of the cookie is supposed to be
              * case-insensitive. We will consistently return the domain in lower
              * case, which allows us to do the more efficient equals comparison
              * instead of equalIgnoreCase.
              *
              * See: http://www.ieft.org/rfc/rfc2965.txt (Section 3.3.3)
              */
             String[] ret = new String[2];
             ret[0] = uri.mHost.toLowerCase();
             ret[1] = uri.mPath;
 
             int index = ret[0].indexOf();
             if (index == -1) {
                 if (uri.mScheme.equalsIgnoreCase("file")) {
                     // There is a potential bug where a local file path matches
                     // another file in the local web server directory. Still
                     // "localhost" is the best pseudo domain name.
                     ret[0] = "localhost";
                 }
             } else if (index == ret[0].lastIndexOf()) {
                 // cookie host must have at least two periods
                 ret[0] =  + ret[0];
             }
 
             if (ret[1].charAt(0) != ) {
                 return null;
             }
 
             /*
              * find cookie path, e.g. for http://www.google.com, the path is "/"
              * for http://www.google.com/lab/, the path is "/lab"
              * for http://www.google.com/lab/foo, the path is "/lab/foo"
              * for http://www.google.com/lab?hl=en, the path is "/lab"
              * for http://www.google.com/lab.asp?hl=en, the path is "/lab.asp"
              * Note: the path from URI has at least one "/"
              * See:
              * http://www.unix.com.ua/rfc/rfc2109.html
              */
             index = ret[1].indexOf();
             if (index != -1) {
                 ret[1] = ret[1].substring(0, index);
             }
 
             return ret;
         } else
             return null;
     }

    
Get the base domain for a give host. E.g. mail.google.com will return google.com

Parameters:
host The give host
Returns:
the base domain
 
     private String getBaseDomain(String host) {
         int startIndex = 0;
         int nextIndex = host.indexOf();
         int lastIndex = host.lastIndexOf();
         while (nextIndex < lastIndex) {
             startIndex = nextIndex + 1;
             nextIndex = host.indexOf(startIndex);
         }
         if (startIndex > 0) {
             return host.substring(startIndex);
         } else {
             return host;
         }
     }

    
parseCookie() parses the cookieString which is a comma-separated list of one or more cookies in the format of "NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure httponly" to a list of Cookies. Here is a sample: IGDND=1, IGPC=ET=UB8TSNwtDmQ:AF=0; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/ig; domain=.google.com, =, PREF=ID=408909b1b304593d:TM=1156459854:LM=1156459854:S=V-vCAU6Sh-gobCfO; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com which contains 3 cookies IGDND, IGPC, PREF and an empty cookie

Parameters:
host The default host
path The default path
cookieString The string coming from "Set-Cookie:"
Returns:
A list of Cookies
 
     private ArrayList<CookieparseCookie(String hostString path,
             String cookieString) {
         ArrayList<Cookieret = new ArrayList<Cookie>();
 
         int index = 0;
         int length = cookieString.length();
         while (true) {
             Cookie cookie = null;
 
             // done
             if (index < 0 || index >= length) {
                 break;
             }
 
             // skip white space
             if (cookieString.charAt(index) == ) {
                 index++;
                 continue;
             }
 
             /*
              * get NAME=VALUE; pair. detecting the end of a pair is tricky, it
              * can be the end of a string, like "foo=bluh", it can be semicolon
              * like "foo=bluh;path=/"; or it can be enclosed by \", like
              * "foo=\"bluh bluh\";path=/"
              *
              * Note: in the case of "foo=bluh, bar=bluh;path=/", we interpret
              * it as one cookie instead of two cookies.
              */
             int semicolonIndex = cookieString.indexOf(index);
             int equalIndex = cookieString.indexOf(index);
             cookie = new Cookie(hostpath);
 
             // Cookies like "testcookie; path=/;" are valid and used
             // (lovefilm.se).
             // Look for 2 cases:
             // 1. "foo" or "foo;" where equalIndex is -1
             // 2. "foo; path=..." where the first semicolon is before an equal
             //    and a semicolon exists.
             if ((semicolonIndex != -1 && (semicolonIndex < equalIndex)) ||
                     equalIndex == -1) {
                 // Fix up the index in case we have a string like "testcookie"
                 if (semicolonIndex == -1) {
                     semicolonIndex = length;
                 }
                 cookie.name = cookieString.substring(indexsemicolonIndex);
                 cookie.value = null;
             } else {
                 cookie.name = cookieString.substring(indexequalIndex);
                 // Make sure we do not throw an exception if the cookie is like
                 // "foo="
                 if ((equalIndex < length - 1) &&
                         (cookieString.charAt(equalIndex + 1) == )) {
                     index = cookieString.indexOf(equalIndex + 2);
                     if (index == -1) {
                         // bad format, force return
                         break;
                     }
                 }
                 // Get the semicolon index again in case it was contained within
                 // the quotations.
                 semicolonIndex = cookieString.indexOf(index);
                 if (semicolonIndex == -1) {
                     semicolonIndex = length;
                 }
                 if (semicolonIndex - equalIndex > ) {
                     // cookie is too big, trim it
                     cookie.value = cookieString.substring(equalIndex + 1,
                             equalIndex + 1 + );
                 } else if (equalIndex + 1 == semicolonIndex
                         || semicolonIndex < equalIndex) {
                     // this is an unusual case like "foo=;" or "foo="
                     cookie.value = "";
                 } else {
                     cookie.value = cookieString.substring(equalIndex + 1,
                             semicolonIndex);
                 }
             }
             // get attributes
             index = semicolonIndex;
             while (true) {
                 // done
                 if (index < 0 || index >= length) {
                     break;
                 }
 
                 // skip white space and semicolon
                 if (cookieString.charAt(index) == 
                         || cookieString.charAt(index) == ) {
                     index++;
                     continue;
                 }
 
                 // comma means next cookie
                 if (cookieString.charAt(index) == ) {
                     index++;
                     break;
                 }
 
                 // "secure" is a known attribute doesn't use "=";
                 // while sites like live.com uses "secure="
                 if (length - index >= 
                         && cookieString.substring(indexindex + ).
                         equalsIgnoreCase()) {
                     index += ;
                     cookie.secure = true;
                     if (index == lengthbreak;
                     if (cookieString.charAt(index) == index++;
                     continue;
                 }
 
                 // "httponly" is a known attribute doesn't use "=";
                 // while sites like live.com uses "httponly="
                 if (length - index >= 
                         && cookieString.substring(index,
                             index + ).
                         equalsIgnoreCase()) {
                     index += ;
                     if (index == lengthbreak;
                     if (cookieString.charAt(index) == index++;
                     // FIXME: currently only parse the attribute
                     continue;
                 }
                 equalIndex = cookieString.indexOf(index);
                 if (equalIndex > 0) {
                     String name = cookieString.substring(indexequalIndex)
                             .toLowerCase();
                     if (name.equals()) {
                         int comaIndex = cookieString.indexOf(equalIndex);
 
                         // skip ',' in (Wdy, DD-Mon-YYYY HH:MM:SS GMT) or
                         // (Weekday, DD-Mon-YY HH:MM:SS GMT) if it applies.
                         // "Wednesday" is the longest Weekday which has length 9
                         if ((comaIndex != -1) &&
                                 (comaIndex - equalIndex <= 10)) {
                             index = comaIndex + 1;
                         }
                     }
                     semicolonIndex = cookieString.indexOf(index);
                     int commaIndex = cookieString.indexOf(index);
                     if (semicolonIndex == -1 && commaIndex == -1) {
                         index = length;
                     } else if (semicolonIndex == -1) {
                         index = commaIndex;
                     } else if (commaIndex == -1) {
                         index = semicolonIndex;
                     } else {
                         index = Math.min(semicolonIndexcommaIndex);
                     }
                     String value =
                             cookieString.substring(equalIndex + 1, index);
                     
                     // Strip quotes if they exist
                     if (value.length() > 2 && value.charAt(0) == ) {
                         int endQuote = value.indexOf(, 1);
                         if (endQuote > 0) {
                             value = value.substring(1, endQuote);
                         }
                     }
                     if (name.equals()) {
                         try {
                             cookie.expires = AndroidHttpClient.parseDate(value);
                         } catch (IllegalArgumentException ex) {
                             Log.e(,
                                     "illegal format for expires: " + value);
                         }
                     } else if (name.equals()) {
                         try {
                             cookie.expires = System.currentTimeMillis() + 1000
                                     * Long.parseLong(value);
                         } catch (NumberFormatException ex) {
                             Log.e(,
                                     "illegal format for max-age: " + value);
                         }
                     } else if (name.equals()) {
                         // only allow non-empty path value
                         if (value.length() > 0) {
                             cookie.path = value;
                         }
                     } else if (name.equals()) {
                         int lastPeriod = value.lastIndexOf();
                         if (lastPeriod == 0) {
                             // disallow cookies set for TLDs like [.com]
                             cookie.domain = null;
                             continue;
                         }
                         try {
                             Integer.parseInt(value.substring(lastPeriod + 1));
                             // no wildcard for ip address match
                             if (!value.equals(host)) {
                                 // no cross-site cookie
                                 cookie.domain = null;
                             }
                             continue;
                         } catch (NumberFormatException ex) {
                             // ignore the exception, value is a host name
                         }
                         value = value.toLowerCase();
                         if (value.charAt(0) != ) {
                             // pre-pended dot to make it as a domain cookie
                             value =  + value;
                             lastPeriod++;
                         }
                         if (host.endsWith(value.substring(1))) {
                             int len = value.length();
                             int hostLen = host.length();
                             if (hostLen > (len - 1)
                                     && host.charAt(hostLen - len) != ) {
                                 // make sure the bar.com doesn't match .ar.com
                                 cookie.domain = null;
                                 continue;
                             }
                             // disallow cookies set on ccTLDs like [.co.uk]
                             if ((len == lastPeriod + 3)
                                     && (len >= 6 && len <= 8)) {
                                 String s = value.substring(1, lastPeriod);
                                 if (Arrays.binarySearch(s) >= 0) {
                                     cookie.domain = null;
                                     continue;
                                }
                            }
                            cookie.domain = value;
                        } else {
                            // no cross-site or more specific sub-domain cookie
                            cookie.domain = null;
                        }
                    }
                } else {
                    // bad format, force return
                    index = length;
                }
            }
            if (cookie != null && cookie.domain != null) {
                ret.add(cookie);
            }
        }
        return ret;
    }
New to GrepCode? Check out our FAQ X