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     }
134 }