View Javadoc

    1   /*******************************************************************************
    2    * Copyright (c) 2011 Michael Mimo Moratti.
    3    *
    4    * Michael Mimo Moratti licenses this file to you under the Apache License, version 2.0
    5    * (the "License"); you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at:
    7    *     http://www.apache.org/licenses/LICENSE-2.0
    8    * Unless required by applicable law or agreed to in writing, software
    9    * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    10   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
    11   * License for the specific language governing permissions and limitations
    12   * under the License.
    13   *******************************************************************************/
    14  package ch.mimo.netty.handler.codec.icap;
    15
    16  import java.nio.charset.Charset;
    17
    18
    19  /**
    20   * This Codec class provides all required special characters such as space and linefeed.
    21   * It also provides validation methods for icap header name and value validation.
    22   *
    23   * @author Michael Mimo Moratti (mimo@mimo.ch)
    24   *
    25   */
    26  public final class IcapCodecUtil {
    27
    28  	/**
    29  	 * Preview early termination sequence
    30  	 *
    31  	 * 0; ieof
    32  	 */
    33  	public static final Byte[] IEOF_SEQUENCE = new Byte[]{48,59,32,105,101,111,102};
    34
    35  	public static final byte[] NATIVE_IEOF_SEQUENCE = new byte[]{48,59,32,105,101,111,102};
    36
    37  	public static final String IEOF_SEQUENCE_STRING = "0; ieof";
    38
    39  	/**
    40  	 * Space
    41  	 */
    42  	public static final byte SPACE = 32;
    43
    44      /**
    45       * Carriage return
    46       */
    47  	public static final byte CR = 13;
    48
    49      /**
    50       * Line feed character
    51       */
    52  	public static final byte LF = 10;
    53
    54      /**
    55       * carriage return line feed
    56       */
    57  	public static final byte[] CRLF = new byte[] { CR, LF };
    58
    59      /**
    60      * Colon ':'
    61      */
    62  	public static final byte COLON = 58;
    63
    64
    65  	public static final Charset ASCII_CHARSET = Charset.forName("ASCII");
    66
    67  	public static final String ENCAPSULATION_ELEMENT_REQHDR = "req-hdr";
    68  	public static final String ENCAPSULATION_ELEMENT_RESHDR = "res-hdr";
    69  	public static final String ENCAPSULATION_ELEMENT_REQBODY = "req-body";
    70  	public static final String ENCAPSULATION_ELEMENT_RESBODY = "res-body";
    71  	public static final String ENCAPSULATION_ELEMENT_OPTBODY = "opt-body";
    72  	public static final String ENCAPSULATION_ELEMENT_NULLBODY = "null-body";
    73
    74      private IcapCodecUtil() {
    75      }
    76
    77      /**
    78       * Valiation method for Icap header names.
    79       *
    80       * @param name to be validated
    81       */
    82      public static void validateHeaderName(String name) {
    83          if (name == null) {
    84              throw new NullPointerException("name");
    85          }
    86          for (int i = 0; i < name.length(); i ++) {
    87              char caracter = name.charAt(i);
    88              if (caracter > 127) {
    89                  throw new IllegalArgumentException("name contains non-ascii character: " + name);
    90              }
    91
    92              // Check prohibited characters.
    93              switch (caracter) {
    94              case '\t': case '\n': case 0x0b: case '\f': case '\r':
    95              case ' ':  case ',':  case ':':  case ';':  case '=':
    96                  throw new IllegalArgumentException("name contains one of the following prohibited characters: =,;: \\t\\r\\n\\v\\f: " + name);
    97              }
    98          }
    99      }
    100
    101     /**
    102      * Validation method for Icap header values
    103      *
    104      * @param value to be validated
    105      */
    106     public static void validateHeaderValue(String value) {
    107         if (value == null) {
    108             throw new NullPointerException("value");
    109         }
    110
    111         // 0 - the previous character was neither CR nor LF
    112         // 1 - the previous character was CR
    113         // 2 - the previous character was LF
    114         int state = 0;
    115
    116         for (int i = 0; i < value.length(); i ++) {
    117             final char caracter = value.charAt(i);
    118
    119             // Check the absolutely prohibited characters.
    120             if(caracter == 0x0b | caracter == '\f') {
    121             	throw new IllegalArgumentException("value contains a prohibited character " + caracter + ": " + value);
    122             }
    123
    124             // Check the CRLF (HT | SP) pattern
    125             if(state == 0) {
    126             	if(caracter == '\r') {
    127             		state = 1;
    128             	}
    129             	if(caracter == '\n') {
    130             		state = 2;
    131             	}
    132             } else if(state == 1) {
    133             	if(caracter == '\n') {
    134             		state = 2;
    135             	} else {
    136             		throw new IllegalArgumentException("Only '\\n' is allowed after '\\r': " + value);
    137             	}
    138             } else if(state == 2) {
    139             	if(caracter == '\t') {
    140             		state = 0;
    141             	} else {
    142             		throw new IllegalArgumentException("Only ' ' and '\\t' are allowed after '\\n': " + value);
    143             	}
    144             }
    145         }
    146
    147         if (state != 0) {
    148             throw new IllegalArgumentException("value must not end with '\\r' or '\\n':" + value);
    149         }
    150     }
    151 }