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/RFC2965PortAttributeHandler.java $
      3  * $Revision: 590695 $
      4  * $Date: 2007-10-31 07:55:41 -0700 (Wed, 31 Oct 2007) $
      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.StringTokenizer;
     35 
     36 import org.apache.http.cookie.ClientCookie;
     37 import org.apache.http.cookie.Cookie;
     38 import org.apache.http.cookie.CookieAttributeHandler;
     39 import org.apache.http.cookie.CookieOrigin;
     40 import org.apache.http.cookie.MalformedCookieException;
     41 import org.apache.http.cookie.SetCookie;
     42 import org.apache.http.cookie.SetCookie2;
     43 
     44 /**
     45  * <tt>"Port"</tt> cookie attribute handler for RFC 2965 cookie spec.
     46  */
     47 public class RFC2965PortAttributeHandler implements CookieAttributeHandler {
     48 
     49     public RFC2965PortAttributeHandler() {
     50         super();
     51     }
     52 
     53     /**
     54      * Parses the given Port attribute value (e.g. "8000,8001,8002")
     55      * into an array of ports.
     56      *
     57      * @param portValue port attribute value
     58      * @return parsed array of ports
     59      * @throws MalformedCookieException if there is a problem in
     60      *          parsing due to invalid portValue.
     61      */
     62     private static int[] parsePortAttribute(final String portValue)
     63             throws MalformedCookieException {
     64         StringTokenizer st = new StringTokenizer(portValue, ",");
     65         int[] ports = new int[st.countTokens()];
     66         try {
     67             int i = 0;
     68             while(st.hasMoreTokens()) {
     69                 ports[i] = Integer.parseInt(st.nextToken().trim());
     70                 if (ports[i] < 0) {
     71                   throw new MalformedCookieException ("Invalid Port attribute.");
     72                 }
     73                 ++i;
     74             }
     75         } catch (NumberFormatException e) {
     76             throw new MalformedCookieException ("Invalid Port "
     77                                                 + "attribute: " + e.getMessage());
     78         }
     79         return ports;
     80     }
     81 
     82     /**
     83      * Returns <tt>true</tt> if the given port exists in the given
     84      * ports list.
     85      *
     86      * @param port port of host where cookie was received from or being sent to.
     87      * @param ports port list
     88      * @return true returns <tt>true</tt> if the given port exists in
     89      *         the given ports list; <tt>false</tt> otherwise.
     90      */
     91     private static boolean portMatch(int port, int[] ports) {
     92         boolean portInList = false;
     93         for (int i = 0, len = ports.length; i < len; i++) {
     94             if (port == ports[i]) {
     95                 portInList = true;
     96                 break;
     97             }
     98         }
     99         return portInList;
    100     }
    101 
    102     /**
    103      * Parse cookie port attribute.
    104      */
    105     public void parse(final SetCookie cookie, final String portValue)
    106             throws MalformedCookieException {
    107         if (cookie == null) {
    108             throw new IllegalArgumentException("Cookie may not be null");
    109         }
    110         if (cookie instanceof SetCookie2) {
    111             SetCookie2 cookie2 = (SetCookie2) cookie;
    112             if (portValue != null && portValue.trim().length() > 0) {
    113                 int[] ports = parsePortAttribute(portValue);
    114                 cookie2.setPorts(ports);
    115             }
    116         }
    117     }
    118 
    119     /**
    120      * Validate cookie port attribute. If the Port attribute was specified
    121      * in header, the request port must be in cookie's port list.
    122      */
    123     public void validate(final Cookie cookie, final CookieOrigin origin)
    124             throws MalformedCookieException {
    125         if (cookie == null) {
    126             throw new IllegalArgumentException("Cookie may not be null");
    127         }
    128         if (origin == null) {
    129             throw new IllegalArgumentException("Cookie origin may not be null");
    130         }
    131         int port = origin.getPort();
    132         if (cookie instanceof ClientCookie
    133                 && ((ClientCookie) cookie).containsAttribute(ClientCookie.PORT_ATTR)) {
    134             if (!portMatch(port, cookie.getPorts())) {
    135                 throw new MalformedCookieException(
    136                         "Port attribute violates RFC 2965: "
    137                         + "Request port not found in cookie's port list.");
    138             }
    139         }
    140     }
    141 
    142     /**
    143      * Match cookie port attribute. If the Port attribute is not specified
    144      * in header, the cookie can be sent to any port. Otherwise, the request port
    145      * must be in the cookie's port list.
    146      */
    147     public boolean match(final Cookie cookie, final CookieOrigin origin) {
    148         if (cookie == null) {
    149             throw new IllegalArgumentException("Cookie may not be null");
    150         }
    151         if (origin == null) {
    152             throw new IllegalArgumentException("Cookie origin may not be null");
    153         }
    154         int port = origin.getPort();
    155         if (cookie instanceof ClientCookie
    156                 && ((ClientCookie) cookie).containsAttribute(ClientCookie.PORT_ATTR)) {
    157             if (cookie.getPorts() == null) {
    158                 // Invalid cookie state: port not specified
    159                 return false;
    160             }
    161             if (!portMatch(port, cookie.getPorts())) {
    162                 return false;
    163             }
    164         }
    165         return true;
    166     }
    167 
    168 }
    169