1 package org.mortbay.servlet; 16 17 import java.io.ByteArrayOutputStream ; 18 import java.io.File ; 19 import java.io.FileOutputStream ; 20 import java.io.IOException ; 21 import java.io.OutputStream ; 22 import java.io.UnsupportedEncodingException ; 23 import java.util.Collections ; 24 import java.util.Enumeration ; 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.StringTokenizer ; 28 29 import javax.servlet.Filter ; 30 import javax.servlet.FilterChain ; 31 import javax.servlet.FilterConfig ; 32 import javax.servlet.ServletException ; 33 import javax.servlet.ServletRequest ; 34 import javax.servlet.ServletResponse ; 35 import javax.servlet.http.HttpServletRequest ; 36 import javax.servlet.http.HttpServletRequestWrapper ; 37 38 import org.apache.commons.logging.Log; 39 import org.mortbay.log.LogFactory; 40 import org.mortbay.util.IO; 41 import org.mortbay.util.LineInput; 42 import org.mortbay.util.MultiMap; 43 import org.mortbay.util.StringUtil; 44 45 46 58 public class MultiPartFilter implements Filter 59 { 60 private static Log log=LogFactory.getLog(MultiPartFilter.class); 61 private File tempdir; 62 63 64 67 public void init(FilterConfig filterConfig) throws ServletException 68 { 69 tempdir=(File )filterConfig.getServletContext().getAttribute("javax.servlet.context.tempdir"); 70 } 71 72 73 77 public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException , 78 ServletException 79 { 80 HttpServletRequest srequest=(HttpServletRequest )request; 81 if(srequest.getContentType()==null||!srequest.getContentType().startsWith("multipart/form-data")) 82 { 83 chain.doFilter(request,response); 84 return; 85 } 86 LineInput in=new LineInput(request.getInputStream()); 87 String content_type=srequest.getContentType(); 88 String boundary="--"+value(content_type.substring(content_type.indexOf("boundary="))); 89 byte[] byteBoundary=(boundary+"--").getBytes(StringUtil.__ISO_8859_1); 90 MultiMap params = new MultiMap(); 91 92 String line=in.readLine(); 94 if(!line.equals(boundary)) 95 { 96 log.warn(line); 97 throw new IOException ("Missing initial multi part boundary"); 98 } 99 100 boolean lastPart=false; 102 String content_disposition=null; 103 while(!lastPart) 104 { 105 while((line=in.readLine())!=null) 106 { 107 if(line.length()==0) 109 break; 110 int c=line.indexOf(':',0); 112 if(c>0) 113 { 114 String key=line.substring(0,c).trim().toLowerCase(); 115 String value=line.substring(c+1,line.length()).trim(); 116 if(key.equals("content-disposition")) 117 content_disposition=value; 118 } 119 } 120 boolean form_data=false; 122 if(content_disposition==null) 123 { 124 throw new IOException ("Missing content-disposition"); 125 } 126 127 StringTokenizer tok=new StringTokenizer (content_disposition,";"); 128 String name=null; 129 String filename=null; 130 while(tok.hasMoreTokens()) 131 { 132 String t=tok.nextToken().trim(); 133 String tl=t.toLowerCase(); 134 if(t.startsWith("form-data")) 135 form_data=true; 136 else if(tl.startsWith("name=")) 137 name=value(t); 138 else if(tl.startsWith("filename=")) 139 filename=value(t); 140 } 141 142 if(!form_data) 144 { 145 log.warn("Non form-data part in multipart/form-data"); 146 continue; 147 } 148 if(name==null||name.length()==0) 149 { 150 log.warn("Part with no name in multipart/form-data"); 151 continue; 152 } 153 154 OutputStream out=null; 155 File file=null; 156 try 157 { 158 if (filename!=null && filename.length()>0) 159 { 160 file = File.createTempFile("MultiPart", "", tempdir); 161 out = new FileOutputStream (file); 162 request.setAttribute(name,file); 163 params.put(name, filename); 164 } 165 else 166 out=new ByteArrayOutputStream (); 167 168 int state=-2; 169 int c; 170 boolean cr=false; 171 boolean lf=false; 172 173 while(true) 175 { 176 int b=0; 177 while((c=(state!=-2)?state:in.read())!=-1) 178 { 179 state=-2; 180 if(c==13||c==10) 182 { 183 if(c==13) 184 state=in.read(); 185 break; 186 } 187 if(b>=0&&b<byteBoundary.length&&c==byteBoundary[b]) 189 b++; 190 else 191 { 192 if(cr) 194 out.write(13); 195 if(lf) 196 out.write(10); 197 cr=lf=false; 198 if(b>0) 199 out.write(byteBoundary,0,b); 200 b=-1; 201 out.write(c); 202 } 203 } 204 if((b>0&&b<byteBoundary.length-2)||(b==byteBoundary.length-1)) 206 { 207 if(cr) 208 out.write(13); 209 if(lf) 210 out.write(10); 211 cr=lf=false; 212 out.write(byteBoundary,0,b); 213 b=-1; 214 } 215 if(b>0||c==-1) 217 { 218 if(b==byteBoundary.length) 219 lastPart=true; 220 if(state==10) 221 state=-2; 222 break; 223 } 224 if(cr) 226 out.write(13); 227 if(lf) 228 out.write(10); 229 cr=(c==13); 230 lf=(c==10||state==10); 231 if(state==10) 232 state=-2; 233 } 234 } 235 finally 236 { 237 IO.close(out); 238 } 239 240 if (file==null) 241 { 242 byte[] bytes = ((ByteArrayOutputStream )out).toByteArray(); 243 params.add(name,bytes); 244 } 245 } 246 247 chain.doFilter(new Wrapper (srequest,params),response); 248 249 } 251 252 253 254 private String value(String nameEqualsValue) 255 { 256 String value=nameEqualsValue.substring(nameEqualsValue.indexOf('=')+1).trim(); 257 int i=value.indexOf(';'); 258 if(i>0) 259 value=value.substring(0,i); 260 if(value.startsWith("\"")) 261 { 262 value=value.substring(1,value.indexOf('"',1)); 263 } 264 else 265 { 266 i=value.indexOf(' '); 267 if(i>0) 268 value=value.substring(0,i); 269 } 270 return value; 271 } 272 273 274 277 public void destroy() 278 { 279 } 280 281 private static class Wrapper extends HttpServletRequestWrapper 282 { 283 String encoding="UTF-8"; 284 MultiMap map; 285 286 287 290 public Wrapper(HttpServletRequest request, MultiMap map) 291 { 292 super(request); 293 this.map=map; 294 } 295 296 297 300 public int getContentLength() 301 { 302 return 0; 303 } 304 305 306 309 public String getParameter(String name) 310 { 311 Object o=map.get(name); 312 if (o instanceof byte[]) 313 { 314 try 315 { 316 String s=new String ((byte[])o,encoding); 317 return s; 318 } 319 catch(Exception e) 320 { 321 log.warn(e); 322 } 323 } 324 else if (o instanceof String ) 325 return (String )o; 326 return null; 327 } 328 329 330 333 public Map getParameterMap() 334 { 335 return map; 336 } 337 338 339 342 public Enumeration getParameterNames() 343 { 344 return Collections.enumeration(map.keySet()); 345 } 346 347 348 351 public String [] getParameterValues(String name) 352 { 353 List l=map.getValues(name); 354 if (l==null || l.size()==0) 355 return new String [0]; 356 String [] v = new String [l.size()]; 357 for (int i=0;i<l.size();i++) 358 { 359 Object o=l.get(i); 360 if (o instanceof byte[]) 361 { 362 try 363 { 364 v[i]=new String ((byte[])o,encoding); 365 } 366 catch(Exception e) 367 { 368 log.warn(e); 369 } 370 } 371 else if (o instanceof String ) 372 v[i]=(String )o; 373 } 374 return v; 375 } 376 377 378 381 public void setCharacterEncoding(String enc) 382 throws UnsupportedEncodingException 383 { 384 encoding=enc; 385 } 386 } 387 } 388 | Popular Tags |