View Javadoc

    1   /*
    2    * Copyright 2012 The Netty Project
    3    *
    4    * The Netty Project licenses this file to you under the Apache License,
    5    * version 2.0 (the "License"); you may not use this file except in compliance
    6    * with the 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.util.List;
    19
    20  final class HttpCodecUtil {
    21
    22      static void validateHeaderName(String name) {
    23          if (name == null) {
    24              throw new NullPointerException("name");
    25          }
    26          for (int i = 0; i < name.length(); i ++) {
    27              char c = name.charAt(i);
    28              if (c > 127) {
    29                  throw new IllegalArgumentException(
    30                          "name contains non-ascii character: " + name);
    31              }
    32
    33              // Check prohibited characters.
    34              switch (c) {
    35              case '\t': case '\n': case 0x0b: case '\f': case '\r':
    36              case ' ':  case ',':  case ':':  case ';':  case '=':
    37                  throw new IllegalArgumentException(
    38                          "name contains one of the following prohibited characters: " +
    39                          "=,;: \\t\\r\\n\\v\\f: " + name);
    40              }
    41          }
    42      }
    43
    44      static void validateHeaderValue(String value) {
    45          if (value == null) {
    46              throw new NullPointerException("value");
    47          }
    48
    49          // 0 - the previous character was neither CR nor LF
    50          // 1 - the previous character was CR
    51          // 2 - the previous character was LF
    52          int state = 0;
    53
    54          for (int i = 0; i < value.length(); i ++) {
    55              char c = value.charAt(i);
    56
    57              // Check the absolutely prohibited characters.
    58              switch (c) {
    59              case 0x0b: // Vertical tab
    60                  throw new IllegalArgumentException(
    61                          "value contains a prohibited character '\\v': " + value);
    62              case '\f':
    63                  throw new IllegalArgumentException(
    64                          "value contains a prohibited character '\\f': " + value);
    65              }
    66
    67              // Check the CRLF (HT | SP) pattern
    68              switch (state) {
    69              case 0:
    70                  switch (c) {
    71                  case '\r':
    72                      state = 1;
    73                      break;
    74                  case '\n':
    75                      state = 2;
    76                      break;
    77                  }
    78                  break;
    79              case 1:
    80                  switch (c) {
    81                  case '\n':
    82                      state = 2;
    83                      break;
    84                  default:
    85                      throw new IllegalArgumentException(
    86                              "Only '\\n' is allowed after '\\r': " + value);
    87                  }
    88                  break;
    89              case 2:
    90                  switch (c) {
    91                  case '\t': case ' ':
    92                      state = 0;
    93                      break;
    94                  default:
    95                      throw new IllegalArgumentException(
    96                              "Only ' ' and '\\t' are allowed after '\\n': " + value);
    97                  }
    98              }
    99          }
    100
    101         if (state != 0) {
    102             throw new IllegalArgumentException(
    103                     "value must not end with '\\r' or '\\n':" + value);
    104         }
    105     }
    106
    107     static boolean isTransferEncodingChunked(HttpMessage m) {
    108         List<String> chunked = m.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
    109         if (chunked.isEmpty()) {
    110             return false;
    111         }
    112
    113         for (String v: chunked) {
    114             if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
    115                 return true;
    116             }
    117         }
    118         return false;
    119     }
    120
    121     static void removeTransferEncodingChunked(HttpMessage m) {
    122         List<String> values = m.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
    123         values.remove(HttpHeaders.Values.CHUNKED);
    124         m.setHeader(HttpHeaders.Names.TRANSFER_ENCODING, values);
    125     }
    126
    127     static boolean isContentLengthSet(HttpMessage m) {
    128         List<String> contentLength = m.getHeaders(HttpHeaders.Names.CONTENT_LENGTH);
    129         return !contentLength.isEmpty();
    130     }
    131
    132     private HttpCodecUtil() {
    133         super();
    134     }
    135 }