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    *   https://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 io.netty.handler.codec.http.multipart;
17  
18  import io.netty.buffer.ByteBuf;
19  import io.netty.channel.ChannelException;
20  import io.netty.handler.codec.http.HttpConstants;
21  import io.netty.util.AbstractReferenceCounted;
22  import io.netty.util.internal.ObjectUtil;
23  
24  import java.io.IOException;
25  import java.nio.charset.Charset;
26  
27  import static io.netty.util.internal.ObjectUtil.checkNonEmpty;
28  
29  /**
30   * Abstract HttpData implementation
31   */
32  public abstract class AbstractHttpData extends AbstractReferenceCounted implements HttpData {
33  
34      private final String name;
35      protected long definedSize;
36      protected long size;
37      private Charset charset = HttpConstants.DEFAULT_CHARSET;
38      private boolean completed;
39      private long maxSize = DefaultHttpDataFactory.MAXSIZE;
40  
41      protected AbstractHttpData(String name, Charset charset, long size) {
42          ObjectUtil.checkNotNull(name, "name");
43  
44          this.name = checkNonEmpty(cleanName(name), "name");
45          if (charset != null) {
46              setCharset(charset);
47          }
48          definedSize = size;
49      }
50  
51      //Replaces \r and \t with a space
52      //Removes leading and trailing whitespace and newlines
53      private static String cleanName(String name) {
54          int len = name.length();
55          StringBuilder sb = null;
56  
57          int start = 0;
58          int end = len;
59  
60          // Trim leading whitespace
61          while (start < end && Character.isWhitespace(name.charAt(start))) {
62              start++;
63          }
64  
65          // Trim trailing whitespace
66          while (end > start && Character.isWhitespace(name.charAt(end - 1))) {
67              end--;
68          }
69  
70          for (int i = start; i < end; i++) {
71              char c = name.charAt(i);
72  
73              if (c == '\n') {
74                  // Skip newline entirely
75                  if (sb == null) {
76                      sb = new StringBuilder(len);
77                      sb.append(name, start, i);
78                  }
79                  continue;
80              }
81  
82              if (c == '\r' || c == '\t') {
83                  if (sb == null) {
84                      sb = new StringBuilder(len);
85                      sb.append(name, start, i);
86                  }
87                  sb.append(' ');
88              } else if (sb != null) {
89                  sb.append(c);
90              }
91          }
92  
93          // If no replacements were needed, return the trimmed slice
94          return sb == null ? name.substring(start, end) : sb.toString();
95      }
96  
97      @Override
98      public long getMaxSize() {
99          return maxSize;
100     }
101 
102     @Override
103     public void setMaxSize(long maxSize) {
104         this.maxSize = maxSize;
105     }
106 
107     @Override
108     public void checkSize(long newSize) throws IOException {
109         if (maxSize >= 0 && newSize > maxSize) {
110             throw new IOException("Size exceed allowed maximum capacity");
111         }
112     }
113 
114     @Override
115     public String getName() {
116         return name;
117     }
118 
119     @Override
120     public boolean isCompleted() {
121         return completed;
122     }
123 
124     protected void setCompleted() {
125         setCompleted(true);
126     }
127 
128     protected void setCompleted(boolean completed) {
129         this.completed = completed;
130     }
131 
132     @Override
133     public Charset getCharset() {
134         return charset;
135     }
136 
137     @Override
138     public void setCharset(Charset charset) {
139         this.charset = ObjectUtil.checkNotNull(charset, "charset");
140     }
141 
142     @Override
143     public long length() {
144         return size;
145     }
146 
147     @Override
148     public long definedLength() {
149         return definedSize;
150     }
151 
152     @Override
153     public ByteBuf content() {
154         try {
155             return getByteBuf();
156         } catch (IOException e) {
157             throw new ChannelException(e);
158         }
159     }
160 
161     @Override
162     protected void deallocate() {
163         delete();
164     }
165 
166     @Override
167     public HttpData retain() {
168         super.retain();
169         return this;
170     }
171 
172     @Override
173     public HttpData retain(int increment) {
174         super.retain(increment);
175         return this;
176     }
177 
178     @Override
179     public abstract HttpData touch();
180 
181     @Override
182     public abstract HttpData touch(Object hint);
183 }