View Javadoc

    1   /*
    2    * Copyright 2009 Red Hat, Inc.
    3    *
    4    * Red Hat 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
    6    * License.  You may obtain a copy of the License at:
    7    *
    8    *    http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
    13   * License for the specific language governing permissions and limitations
    14   * under the License.
    15   */
    16  package org.jboss.netty.handler.codec.http;
    17
    18  import java.nio.charset.Charset;
    19  import java.util.List;
    20
    21  import org.jboss.netty.util.CharsetUtil;
    22
    23  /**
    24   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
    25   * @author Andy Taylor (andy.taylor@jboss.org)
    26   * @version $Rev: 2080 $, $Date: 2010-01-26 18:04:19 +0900 (Tue, 26 Jan 2010) $
    27   */
    28  class HttpCodecUtil {
    29      //space ' '
    30      static final byte SP = 32;
    31
    32      //tab ' '
    33      static final byte HT = 9;
    34
    35      /**
    36       * Carriage return
    37       */
    38      static final byte CR = 13;
    39
    40      /**
    41       * Equals '='
    42       */
    43      static final byte EQUALS = 61;
    44
    45      /**
    46       * Line feed character
    47       */
    48      static final byte LF = 10;
    49
    50      /**
    51       * carriage return line feed
    52       */
    53      static final byte[] CRLF = new byte[] { CR, LF };
    54
    55      /**
    56      * Colon ':'
    57      */
    58      static final byte COLON = 58;
    59
    60      /**
    61      * Semicolon ';'
    62      */
    63      static final byte SEMICOLON = 59;
    64
    65       /**
    66      * comma ','
    67      */
    68      static final byte COMMA = 44;
    69
    70      static final byte DOUBLE_QUOTE = '"';
    71
    72      static final Charset DEFAULT_CHARSET = CharsetUtil.UTF_8;
    73
    74      private HttpCodecUtil() {
    75          super();
    76      }
    77
    78      static void validateHeaderName(String name) {
    79          if (name == null) {
    80              throw new NullPointerException("name");
    81          }
    82          for (int i = 0; i < name.length(); i ++) {
    83              char c = name.charAt(i);
    84              if (c > 127) {
    85                  throw new IllegalArgumentException(
    86                          "name contains non-ascii character: " + name);
    87              }
    88
    89              // Check prohibited characters.
    90              switch (c) {
    91              case '\t': case '\n': case 0x0b: case '\f': case '\r':
    92              case ' ':  case ',':  case ':':  case ';':  case '=':
    93                  throw new IllegalArgumentException(
    94                          "name contains one of the following prohibited characters: " +
    95                          "=,;: \\t\\r\\n\\v\\f: " + name);
    96              }
    97          }
    98      }
    99
    100     static void validateHeaderValue(String value) {
    101         if (value == null) {
    102             throw new NullPointerException("value");
    103         }
    104
    105         // 0 - the previous character was neither CR nor LF
    106         // 1 - the previous character was CR
    107         // 2 - the previous character was LF
    108         int state = 0;
    109
    110         for (int i = 0; i < value.length(); i ++) {
    111             char c = value.charAt(i);
    112
    113             // Check the absolutely prohibited characters.
    114             switch (c) {
    115             case 0x0b: // Vertical tab
    116                 throw new IllegalArgumentException(
    117                         "value contains a prohibited character '\\v': " + value);
    118             case '\f':
    119                 throw new IllegalArgumentException(
    120                         "value contains a prohibited character '\\f': " + value);
    121             }
    122
    123             // Check the CRLF (HT | SP) pattern
    124             switch (state) {
    125             case 0:
    126                 switch (c) {
    127                 case '\r':
    128                     state = 1;
    129                     break;
    130                 case '\n':
    131                     state = 2;
    132                     break;
    133                 }
    134                 break;
    135             case 1:
    136                 switch (c) {
    137                 case '\n':
    138                     state = 2;
    139                     break;
    140                 default:
    141                     throw new IllegalArgumentException(
    142                             "Only '\\n' is allowed after '\\r': " + value);
    143                 }
    144                 break;
    145             case 2:
    146                 switch (c) {
    147                 case '\t': case ' ':
    148                     state = 0;
    149                     break;
    150                 default:
    151                     throw new IllegalArgumentException(
    152                             "Only ' ' and '\\t' are allowed after '\\n': " + value);
    153                 }
    154             }
    155         }
    156
    157         if (state != 0) {
    158             throw new IllegalArgumentException(
    159                     "value must not end with '\\r' or '\\n':" + value);
    160         }
    161     }
    162
    163     static boolean isTransferEncodingChunked(HttpMessage m) {
    164         List<String> chunked = m.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
    165         if (chunked.isEmpty()) {
    166             return false;
    167         }
    168
    169         for (String v: chunked) {
    170             if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
    171                 return true;
    172             }
    173         }
    174         return false;
    175     }
    176 }