1
2
3
4
5
6
7
8
9
10
11
12
13 package org.eclipse.jetty.servlets;
14
15 import java.io.BufferedInputStream;
16 import java.io.BufferedOutputStream;
17 import java.io.ByteArrayOutputStream;
18 import java.io.File;
19 import java.io.FileOutputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.io.UnsupportedEncodingException;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.Enumeration;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31
32 import javax.servlet.Filter;
33 import javax.servlet.FilterChain;
34 import javax.servlet.FilterConfig;
35 import javax.servlet.MultipartConfigElement;
36 import javax.servlet.ServletContext;
37 import javax.servlet.ServletException;
38 import javax.servlet.ServletRequest;
39 import javax.servlet.ServletResponse;
40 import javax.servlet.http.HttpServletRequest;
41 import javax.servlet.http.HttpServletRequestWrapper;
42 import javax.servlet.http.Part;
43
44
45 import org.eclipse.jetty.util.IO;
46 import org.eclipse.jetty.util.LazyList;
47 import org.eclipse.jetty.util.MultiMap;
48 import org.eclipse.jetty.util.MultiPartInputStream;
49 import org.eclipse.jetty.util.QuotedStringTokenizer;
50 import org.eclipse.jetty.util.StringUtil;
51 import org.eclipse.jetty.util.TypeUtil;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class MultiPartFilter implements Filter
71 {
72 private final static String FILES ="org.eclipse.jetty.servlet.MultiPartFilter.files";
73 private File tempdir;
74 private boolean _deleteFiles;
75 private ServletContext _context;
76 private int _fileOutputBuffer = 0;
77 private long _maxFileSize = -1L;
78 private long _maxRequestSize = -1L;
79
80
81
82
83
84 public void init(FilterConfig filterConfig) throws ServletException
85 {
86 tempdir=(File)filterConfig.getServletContext().getAttribute("javax.servlet.context.tempdir");
87 _deleteFiles="true".equals(filterConfig.getInitParameter("deleteFiles"));
88 String fileOutputBuffer = filterConfig.getInitParameter("fileOutputBuffer");
89 if(fileOutputBuffer!=null)
90 _fileOutputBuffer = Integer.parseInt(fileOutputBuffer);
91 String maxFileSize = filterConfig.getInitParameter("maxFileSize");
92 if (maxFileSize != null)
93 _maxFileSize = Long.parseLong(maxFileSize.trim());
94 String maxRequestSize = filterConfig.getInitParameter("maxRequestSize");
95 if (maxRequestSize != null)
96 _maxRequestSize = Long.parseLong(maxRequestSize.trim());
97
98 _context=filterConfig.getServletContext();
99 }
100
101
102
103
104
105
106 public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
107 throws IOException, ServletException
108 {
109 HttpServletRequest srequest=(HttpServletRequest)request;
110 if(srequest.getContentType()==null||!srequest.getContentType().startsWith("multipart/form-data"))
111 {
112 chain.doFilter(request,response);
113 return;
114 }
115
116 InputStream in = new BufferedInputStream(request.getInputStream());
117 String content_type=srequest.getContentType();
118
119
120 MultiMap<String> params = new MultiMap<String>();
121 for (Iterator<Map.Entry<String,String[]>> i = request.getParameterMap().entrySet().iterator();i.hasNext();)
122 {
123 Map.Entry<String,String[]> entry=i.next();
124 Object value=entry.getValue();
125 if (value instanceof String[])
126 params.addValues(entry.getKey(),(String[])value);
127 else
128 params.add(entry.getKey(),value);
129 }
130
131 MultipartConfigElement config = new MultipartConfigElement(tempdir.getCanonicalPath(), _maxFileSize, _maxRequestSize, _fileOutputBuffer);
132 MultiPartInputStream mpis = new MultiPartInputStream(in, content_type, config, tempdir);
133
134
135 try
136 {
137 Collection<Part> parts = mpis.getParts();
138 if (parts != null)
139 {
140 for (Part p:parts)
141 {
142 MultiPartInputStream.MultiPart mp = (MultiPartInputStream.MultiPart)p;
143 if (mp.getFile() != null)
144 {
145 request.setAttribute(mp.getName(),mp.getFile());
146 if (mp.getContentDispositionFilename() != null)
147 params.add(mp.getName(), mp.getContentDispositionFilename());
148 if (_deleteFiles)
149 {
150 mp.getFile().deleteOnExit();
151
152 ArrayList files = (ArrayList)request.getAttribute(FILES);
153 if (files==null)
154 {
155 files=new ArrayList();
156 request.setAttribute(FILES,files);
157 }
158 files.add(mp.getFile());
159 }
160 }
161 else
162 {
163 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
164 IO.copy(p.getInputStream(), bytes);
165 params.add(p.getName(), bytes.toByteArray());
166 }
167 }
168 }
169
170
171 chain.doFilter(new Wrapper(srequest,params),response);
172 }
173 finally
174 {
175 deleteFiles(request);
176 }
177 }
178
179 private void deleteFiles(ServletRequest request)
180 {
181 ArrayList files = (ArrayList)request.getAttribute(FILES);
182 if (files!=null)
183 {
184 Iterator iter = files.iterator();
185 while (iter.hasNext())
186 {
187 File file=(File)iter.next();
188 try
189 {
190 file.delete();
191 }
192 catch(Exception e)
193 {
194 _context.log("failed to delete "+file,e);
195 }
196 }
197 }
198 }
199
200
201 private String value(String nameEqualsValue)
202 {
203 return nameEqualsValue.substring(nameEqualsValue.indexOf('=')+1).trim();
204 }
205
206
207
208
209
210 public void destroy()
211 {
212 }
213
214
215
216 private static class Wrapper extends HttpServletRequestWrapper
217 {
218 String _encoding=StringUtil.__UTF8;
219 MultiMap _params;
220
221
222
223
224
225 public Wrapper(HttpServletRequest request, MultiMap map)
226 {
227 super(request);
228 this._params=map;
229 }
230
231
232
233
234
235 @Override
236 public int getContentLength()
237 {
238 return 0;
239 }
240
241
242
243
244
245 @Override
246 public String getParameter(String name)
247 {
248 Object o=_params.get(name);
249 if (!(o instanceof byte[]) && LazyList.size(o)>0)
250 o=LazyList.get(o,0);
251
252 if (o instanceof byte[])
253 {
254 try
255 {
256 String s=new String((byte[])o,_encoding);
257 return s;
258 }
259 catch(Exception e)
260 {
261 e.printStackTrace();
262 }
263 }
264 else if (o!=null)
265 return String.valueOf(o);
266 return null;
267 }
268
269
270
271
272
273 @Override
274 public Map getParameterMap()
275 {
276 return Collections.unmodifiableMap(_params.toStringArrayMap());
277 }
278
279
280
281
282
283 @Override
284 public Enumeration getParameterNames()
285 {
286 return Collections.enumeration(_params.keySet());
287 }
288
289
290
291
292
293 @Override
294 public String[] getParameterValues(String name)
295 {
296 List l=_params.getValues(name);
297 if (l==null || l.size()==0)
298 return new String[0];
299 String[] v = new String[l.size()];
300 for (int i=0;i<l.size();i++)
301 {
302 Object o=l.get(i);
303 if (o instanceof byte[])
304 {
305 try
306 {
307 v[i]=new String((byte[])o,_encoding);
308 }
309 catch(Exception e)
310 {
311 e.printStackTrace();
312 }
313 }
314 else if (o instanceof String)
315 v[i]=(String)o;
316 }
317 return v;
318 }
319
320
321
322
323
324 @Override
325 public void setCharacterEncoding(String enc)
326 throws UnsupportedEncodingException
327 {
328 _encoding=enc;
329 }
330 }
331 }