mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965Spec.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2  * ====================================================================
     3  *
     4  *  Licensed to the Apache Software Foundation (ASF) under one or more
     5  *  contributor license agreements.  See the NOTICE file distributed with
     6  *  this work for additional information regarding copyright ownership.
     7  *  The ASF licenses this file to You under the Apache License, Version 2.0
     8  *  (the "License"); you may not use this file except in compliance with
     9  *  the License.  You may obtain a copy of the License at
    10  *
    11  *      http://www.apache.org/licenses/LICENSE-2.0
    12  *
    13  *  Unless required by applicable law or agreed to in writing, software
    14  *  distributed under the License is distributed on an "AS IS" BASIS,
    15  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  *  See the License for the specific language governing permissions and
    17  *  limitations under the License.
    18  * ====================================================================
    19  *
    20  * This software consists of voluntary contributions made by many
    21  * individuals on behalf of the Apache Software Foundation.  For more
    22  * information on the Apache Software Foundation, please see
    23  * <http://www.apache.org/>.
    24  *
    25  */
    27 package ch.boye.httpclientandroidlib.impl.cookie;
    29 import java.util.ArrayList;
    30 import java.util.HashMap;
    31 import java.util.List;
    32 import java.util.Locale;
    33 import java.util.Map;
    35 import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
    37 import ch.boye.httpclientandroidlib.Header;
    38 import ch.boye.httpclientandroidlib.HeaderElement;
    39 import ch.boye.httpclientandroidlib.NameValuePair;
    40 import ch.boye.httpclientandroidlib.cookie.ClientCookie;
    41 import ch.boye.httpclientandroidlib.cookie.Cookie;
    42 import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
    43 import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
    44 import ch.boye.httpclientandroidlib.cookie.CookieSpec;
    45 import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
    46 import ch.boye.httpclientandroidlib.cookie.SM;
    47 import ch.boye.httpclientandroidlib.message.BufferedHeader;
    48 import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
    50 /**
    51  * RFC 2965 compliant {@link CookieSpec} implementation.
    52  *
    53  * @since 4.0
    54  */
    55 @NotThreadSafe // superclass is @NotThreadSafe
    56 public class RFC2965Spec extends RFC2109Spec {
    58     /**
    59      * Default constructor
    60      *
    61      */
    62     public RFC2965Spec() {
    63         this(null, false);
    64     }
    66     public RFC2965Spec(final String[] datepatterns, boolean oneHeader) {
    67         super(datepatterns, oneHeader);
    68         registerAttribHandler(ClientCookie.DOMAIN_ATTR, new RFC2965DomainAttributeHandler());
    69         registerAttribHandler(ClientCookie.PORT_ATTR, new RFC2965PortAttributeHandler());
    70         registerAttribHandler(ClientCookie.COMMENTURL_ATTR, new RFC2965CommentUrlAttributeHandler());
    71         registerAttribHandler(ClientCookie.DISCARD_ATTR, new RFC2965DiscardAttributeHandler());
    72         registerAttribHandler(ClientCookie.VERSION_ATTR, new RFC2965VersionAttributeHandler());
    73     }
    75     @Override
    76     public List<Cookie> parse(
    77             final Header header,
    78             CookieOrigin origin) throws MalformedCookieException {
    79         if (header == null) {
    80             throw new IllegalArgumentException("Header may not be null");
    81         }
    82         if (origin == null) {
    83             throw new IllegalArgumentException("Cookie origin may not be null");
    84         }
    85         if (!header.getName().equalsIgnoreCase(SM.SET_COOKIE2)) {
    86             throw new MalformedCookieException("Unrecognized cookie header '"
    87                     + header.toString() + "'");
    88         }
    89         origin = adjustEffectiveHost(origin);
    90         HeaderElement[] elems = header.getElements();
    91         return createCookies(elems, origin);
    92     }
    94     @Override
    95     protected List<Cookie> parse(
    96             final HeaderElement[] elems,
    97             CookieOrigin origin) throws MalformedCookieException {
    98         origin = adjustEffectiveHost(origin);
    99         return createCookies(elems, origin);
   100     }
   102     private List<Cookie> createCookies(
   103             final HeaderElement[] elems,
   104             final CookieOrigin origin) throws MalformedCookieException {
   105         List<Cookie> cookies = new ArrayList<Cookie>(elems.length);
   106         for (HeaderElement headerelement : elems) {
   107             String name = headerelement.getName();
   108             String value = headerelement.getValue();
   109             if (name == null || name.length() == 0) {
   110                 throw new MalformedCookieException("Cookie name may not be empty");
   111             }
   113             BasicClientCookie2 cookie = new BasicClientCookie2(name, value);
   114             cookie.setPath(getDefaultPath(origin));
   115             cookie.setDomain(getDefaultDomain(origin));
   116             cookie.setPorts(new int [] { origin.getPort() });
   117             // cycle through the parameters
   118             NameValuePair[] attribs = headerelement.getParameters();
   120             // Eliminate duplicate attributes. The first occurrence takes precedence
   121             // See RFC2965: 3.2  Origin Server Role
   122             Map<String, NameValuePair> attribmap =
   123                     new HashMap<String, NameValuePair>(attribs.length);
   124             for (int j = attribs.length - 1; j >= 0; j--) {
   125                 NameValuePair param = attribs[j];
   126                 attribmap.put(param.getName().toLowerCase(Locale.ENGLISH), param);
   127             }
   128             for (Map.Entry<String, NameValuePair> entry : attribmap.entrySet()) {
   129                 NameValuePair attrib = entry.getValue();
   130                 String s = attrib.getName().toLowerCase(Locale.ENGLISH);
   132                 cookie.setAttribute(s, attrib.getValue());
   134                 CookieAttributeHandler handler = findAttribHandler(s);
   135                 if (handler != null) {
   136                     handler.parse(cookie, attrib.getValue());
   137                 }
   138             }
   139             cookies.add(cookie);
   140         }
   141         return cookies;
   142     }
   144     @Override
   145     public void validate(final Cookie cookie, CookieOrigin origin)
   146             throws MalformedCookieException {
   147         if (cookie == null) {
   148             throw new IllegalArgumentException("Cookie may not be null");
   149         }
   150         if (origin == null) {
   151             throw new IllegalArgumentException("Cookie origin may not be null");
   152         }
   153         origin = adjustEffectiveHost(origin);
   154         super.validate(cookie, origin);
   155     }
   157     @Override
   158     public boolean match(final Cookie cookie, CookieOrigin origin) {
   159         if (cookie == null) {
   160             throw new IllegalArgumentException("Cookie may not be null");
   161         }
   162         if (origin == null) {
   163             throw new IllegalArgumentException("Cookie origin may not be null");
   164         }
   165         origin = adjustEffectiveHost(origin);
   166         return super.match(cookie, origin);
   167     }
   169     /**
   170      * Adds valid Port attribute value, e.g. "8000,8001,8002"
   171      */
   172     @Override
   173     protected void formatCookieAsVer(final CharArrayBuffer buffer,
   174             final Cookie cookie, int version) {
   175         super.formatCookieAsVer(buffer, cookie, version);
   176         // format port attribute
   177         if (cookie instanceof ClientCookie) {
   178             // Test if the port attribute as set by the origin server is not blank
   179             String s = ((ClientCookie) cookie).getAttribute(ClientCookie.PORT_ATTR);
   180             if (s != null) {
   181                 buffer.append("; $Port");
   182                 buffer.append("=\"");
   183                 if (s.trim().length() > 0) {
   184                     int[] ports = cookie.getPorts();
   185                     if (ports != null) {
   186                         for (int i = 0, len = ports.length; i < len; i++) {
   187                             if (i > 0) {
   188                                 buffer.append(",");
   189                             }
   190                             buffer.append(Integer.toString(ports[i]));
   191                         }
   192                     }
   193                 }
   194                 buffer.append("\"");
   195             }
   196         }
   197     }
   199     /**
   200      * Set 'effective host name' as defined in RFC 2965.
   201      * <p>
   202      * If a host name contains no dots, the effective host name is
   203      * that name with the string .local appended to it.  Otherwise
   204      * the effective host name is the same as the host name.  Note
   205      * that all effective host names contain at least one dot.
   206      *
   207      * @param origin origin where cookie is received from or being sent to.
   208      * @return
   209      */
   210     private static CookieOrigin adjustEffectiveHost(final CookieOrigin origin) {
   211         String host = origin.getHost();
   213         // Test if the host name appears to be a fully qualified DNS name,
   214         // IPv4 address or IPv6 address
   215         boolean isLocalHost = true;
   216         for (int i = 0; i < host.length(); i++) {
   217             char ch = host.charAt(i);
   218             if (ch == '.' || ch == ':') {
   219                 isLocalHost = false;
   220                 break;
   221             }
   222         }
   223         if (isLocalHost) {
   224             host += ".local";
   225             return new CookieOrigin(
   226                     host,
   227                     origin.getPort(),
   228                     origin.getPath(),
   229                     origin.isSecure());
   230         } else {
   231             return origin;
   232         }
   233     }
   235     @Override
   236     public int getVersion() {
   237         return 1;
   238     }
   240     @Override
   241     public Header getVersionHeader() {
   242         CharArrayBuffer buffer = new CharArrayBuffer(40);
   243         buffer.append(SM.COOKIE2);
   244         buffer.append(": ");
   245         buffer.append("$Version=");
   246         buffer.append(Integer.toString(getVersion()));
   247         return new BufferedHeader(buffer);
   248     }
   250     @Override
   251     public String toString() {
   252         return "rfc2965";
   253     }
   255 }

mercurial