Home | History | Annotate | Download | only in cookie
      1 /*
      2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/cookie/BrowserCompatSpec.java $
      3  * $Revision: 657334 $
      4  * $Date: 2008-05-17 04:44:16 -0700 (Sat, 17 May 2008) $
      5  *
      6  * ====================================================================
      7  * Licensed to the Apache Software Foundation (ASF) under one
      8  * or more contributor license agreements.  See the NOTICE file
      9  * distributed with this work for additional information
     10  * regarding copyright ownership.  The ASF licenses this file
     11  * to you under the Apache License, Version 2.0 (the
     12  * "License"); you may not use this file except in compliance
     13  * with the License.  You may obtain a copy of the License at
     14  *
     15  *   http://www.apache.org/licenses/LICENSE-2.0
     16  *
     17  * Unless required by applicable law or agreed to in writing,
     18  * software distributed under the License is distributed on an
     19  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     20  * KIND, either express or implied.  See the License for the
     21  * specific language governing permissions and limitations
     22  * under the License.
     23  * ====================================================================
     24  *
     25  * This software consists of voluntary contributions made by many
     26  * individuals on behalf of the Apache Software Foundation.  For more
     27  * information on the Apache Software Foundation, please see
     28  * <http://www.apache.org/>.
     29  *
     30  */
     31 
     32 package org.apache.http.impl.cookie;
     33 
     34 import java.util.ArrayList;
     35 import java.util.List;
     36 import java.util.Locale;
     37 
     38 import org.apache.http.FormattedHeader;
     39 import org.apache.http.Header;
     40 import org.apache.http.HeaderElement;
     41 import org.apache.http.cookie.ClientCookie;
     42 import org.apache.http.cookie.Cookie;
     43 import org.apache.http.cookie.CookieOrigin;
     44 import org.apache.http.cookie.MalformedCookieException;
     45 import org.apache.http.cookie.SM;
     46 import org.apache.http.message.BufferedHeader;
     47 import org.apache.http.message.ParserCursor;
     48 import org.apache.http.util.CharArrayBuffer;
     49 
     50 /**
     51  * Cookie specification that strives to closely mimic (mis)behavior of
     52  * common web browser applications such as Microsoft Internet Explorer
     53  * and Mozilla FireFox.
     54  *
     55  * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
     56  *
     57  * @since 4.0
     58  */
     59 public class BrowserCompatSpec extends CookieSpecBase {
     60 
     61     /** Valid date patterns used per default */
     62     protected static final String[] DATE_PATTERNS = new String[] {
     63             DateUtils.PATTERN_RFC1123,
     64             DateUtils.PATTERN_RFC1036,
     65             DateUtils.PATTERN_ASCTIME,
     66             "EEE, dd-MMM-yyyy HH:mm:ss z",
     67             "EEE, dd-MMM-yyyy HH-mm-ss z",
     68             "EEE, dd MMM yy HH:mm:ss z",
     69             "EEE dd-MMM-yyyy HH:mm:ss z",
     70             "EEE dd MMM yyyy HH:mm:ss z",
     71             "EEE dd-MMM-yyyy HH-mm-ss z",
     72             "EEE dd-MMM-yy HH:mm:ss z",
     73             "EEE dd MMM yy HH:mm:ss z",
     74             "EEE,dd-MMM-yy HH:mm:ss z",
     75             "EEE,dd-MMM-yyyy HH:mm:ss z",
     76             "EEE, dd-MM-yyyy HH:mm:ss z",
     77         };
     78 
     79     private final String[] datepatterns;
     80 
     81     /** Default constructor */
     82     public BrowserCompatSpec(final String[] datepatterns) {
     83         super();
     84         if (datepatterns != null) {
     85             this.datepatterns = datepatterns.clone();
     86         } else {
     87             this.datepatterns = DATE_PATTERNS;
     88         }
     89         registerAttribHandler(ClientCookie.PATH_ATTR, new BasicPathHandler());
     90         registerAttribHandler(ClientCookie.DOMAIN_ATTR, new BasicDomainHandler());
     91         registerAttribHandler(ClientCookie.MAX_AGE_ATTR, new BasicMaxAgeHandler());
     92         registerAttribHandler(ClientCookie.SECURE_ATTR, new BasicSecureHandler());
     93         registerAttribHandler(ClientCookie.COMMENT_ATTR, new BasicCommentHandler());
     94         registerAttribHandler(ClientCookie.EXPIRES_ATTR, new BasicExpiresHandler(
     95                 this.datepatterns));
     96     }
     97 
     98     /** Default constructor */
     99     public BrowserCompatSpec() {
    100         this(null);
    101     }
    102 
    103     public List<Cookie> parse(final Header header, final CookieOrigin origin)
    104             throws MalformedCookieException {
    105         if (header == null) {
    106             throw new IllegalArgumentException("Header may not be null");
    107         }
    108         if (origin == null) {
    109             throw new IllegalArgumentException("Cookie origin may not be null");
    110         }
    111         String headervalue = header.getValue();
    112         boolean isNetscapeCookie = false;
    113         int i1 = headervalue.toLowerCase(Locale.ENGLISH).indexOf("expires=");
    114         if (i1 != -1) {
    115             i1 += "expires=".length();
    116             int i2 = headervalue.indexOf(';', i1);
    117             if (i2 == -1) {
    118                 i2 = headervalue.length();
    119             }
    120             try {
    121                 DateUtils.parseDate(headervalue.substring(i1, i2), this.datepatterns);
    122                 isNetscapeCookie = true;
    123             } catch (DateParseException e) {
    124                 // Does not look like a valid expiry date
    125             }
    126         }
    127         HeaderElement[] elems = null;
    128         if (isNetscapeCookie) {
    129             NetscapeDraftHeaderParser parser = NetscapeDraftHeaderParser.DEFAULT;
    130             CharArrayBuffer buffer;
    131             ParserCursor cursor;
    132             if (header instanceof FormattedHeader) {
    133                 buffer = ((FormattedHeader) header).getBuffer();
    134                 cursor = new ParserCursor(
    135                         ((FormattedHeader) header).getValuePos(),
    136                         buffer.length());
    137             } else {
    138                 String s = header.getValue();
    139                 if (s == null) {
    140                     throw new MalformedCookieException("Header value is null");
    141                 }
    142                 buffer = new CharArrayBuffer(s.length());
    143                 buffer.append(s);
    144                 cursor = new ParserCursor(0, buffer.length());
    145             }
    146             elems = new HeaderElement[] { parser.parseHeader(buffer, cursor) };
    147         } else {
    148             elems = header.getElements();
    149         }
    150         return parse(elems, origin);
    151     }
    152 
    153     public List<Header> formatCookies(final List<Cookie> cookies) {
    154         if (cookies == null) {
    155             throw new IllegalArgumentException("List of cookies may not be null");
    156         }
    157         if (cookies.isEmpty()) {
    158             throw new IllegalArgumentException("List of cookies may not be empty");
    159         }
    160         CharArrayBuffer buffer = new CharArrayBuffer(20 * cookies.size());
    161         buffer.append(SM.COOKIE);
    162         buffer.append(": ");
    163         for (int i = 0; i < cookies.size(); i++) {
    164             Cookie cookie = cookies.get(i);
    165             if (i > 0) {
    166                 buffer.append("; ");
    167             }
    168             buffer.append(cookie.getName());
    169             buffer.append("=");
    170             String s = cookie.getValue();
    171             if (s != null) {
    172                 buffer.append(s);
    173             }
    174         }
    175         List<Header> headers = new ArrayList<Header>(1);
    176         headers.add(new BufferedHeader(buffer));
    177         return headers;
    178     }
    179 
    180     public int getVersion() {
    181         return 0;
    182     }
    183 
    184     public Header getVersionHeader() {
    185         return null;
    186     }
    187 
    188 }
    189