1 6 package org.objectweb.jac.aspects.gui.web; 7 8 import java.io.ByteArrayInputStream ; 9 import java.io.ByteArrayOutputStream ; 10 import java.io.IOException ; 11 import java.io.InputStream ; 12 import java.io.UnsupportedEncodingException ; 13 import java.util.Hashtable ; 14 import java.util.List ; 15 import java.util.StringTokenizer ; 16 import javax.servlet.http.HttpServletRequest ; 17 import org.apache.log4j.Logger; 18 import org.mortbay.http.HttpFields; 19 import org.mortbay.util.Code; 20 import org.mortbay.util.LineInput; 21 import org.mortbay.util.MultiMap; 22 import org.mortbay.util.StringUtil; 23 import org.objectweb.jac.util.ExtArrays; 24 25 26 43 public class MultiPartRequest 44 { 45 static Logger logger = Logger.getLogger("web.servlet"); 46 47 48 HttpServletRequest _request; 49 LineInput _in; 50 String _boundary; 51 byte[] _byteBoundary; 52 MultiMap _partMap = new MultiMap(10); 53 int _char = -2; 54 boolean _lastPart = false; 55 String _enc = StringUtil.__ISO_8859_1; 56 57 58 64 public MultiPartRequest(HttpServletRequest request, String enc) 65 throws IOException 66 { 67 _request=request; 68 _enc = enc; 69 String content_type = request.getHeader(HttpFields.__ContentType); 70 if (!content_type.startsWith("multipart/form-data")) 71 throw new IOException ("Not multipart/form-data request"); 72 73 Code.debug("Multipart content type = ",content_type); 74 75 _in = new LineInput(request.getInputStream()); 76 77 _boundary="--"+ 79 value(content_type.substring(content_type.indexOf("boundary="))); 80 81 Code.debug("Boundary=",_boundary); 82 _byteBoundary= (_boundary+"--").getBytes(StringUtil.__ISO_8859_1); 83 84 loadAllParts(); 85 } 86 87 protected Part getPart(String name) { 88 Object part = _partMap.get(name); 89 if (part instanceof List) 90 return (Part)((List)part).get(0); 91 else 92 return (Part)part; 93 } 94 95 96 99 public String [] getPartNames() 100 { 101 return (String []) _partMap.keySet().toArray(ExtArrays.emptyStringArray); 102 } 103 104 105 109 public boolean contains(String name) 110 { 111 Part part = (Part)_partMap.get(name); 112 return (part!=null); 113 } 114 115 116 120 public String getString(String name) 121 { 122 List part = (List)_partMap.getValues(name); 123 if (part==null) 124 return null; 125 return decodeString(((Part)part.get(0))._data); 126 } 127 128 129 133 public String [] getStrings(String name) 134 { 135 List parts = (List)_partMap.getValues(name); 136 if (parts==null) 137 return null; 138 String [] strings = new String [parts.size()]; 139 for (int i=0; i<strings.length; i++) { 140 strings[i] = decodeString(((Part)parts.get(i))._data); 141 } 142 return strings; 143 } 144 145 protected String decodeString(byte[] bytes) { 146 try { 147 return new String (bytes,_enc); 148 } catch (UnsupportedEncodingException e) { 149 logger.error("Unsupported encoding: "+_enc); 150 return new String (bytes); 151 } 152 } 153 154 155 159 public InputStream getInputStream(String name) 160 { 161 Part part = getPart(name); 162 if (part==null) 163 return null; 164 else 165 return new ByteArrayInputStream (part._data); 166 } 167 168 public InputStream [] getInputStreams(String name) 169 { 170 List parts = (List)_partMap.getValues(name); 171 if (parts==null) 172 return null; 173 InputStream [] streams = new InputStream [parts.size()]; 174 for (int i=0; i<streams.length; i++) { 175 streams[i] = new ByteArrayInputStream (((Part)parts.get(i))._data); 176 } 177 return streams; 178 } 179 180 181 185 public Hashtable getParams(String name) 186 { 187 List part = (List)_partMap.getValues(name); 188 if (part==null) 189 return null; 190 return ((Part)part.get(0))._headers; 191 } 192 193 public Hashtable [] getMultipleParams(String name) 194 { 195 List parts = (List)_partMap.getValues(name); 196 if (parts==null) 197 return null; 198 Hashtable [] params = new Hashtable [parts.size()]; 199 for (int i=0; i<params.length; i++) { 200 params[i] = ((Part)parts.get(i))._headers; 201 } 202 return params; 203 } 204 205 206 210 public String getFilename(String name) 211 { 212 List part = (List)_partMap.getValues(name); 213 if (part==null) 214 return null; 215 return ((Part)part.get(0))._filename; 216 } 217 218 public String [] getFilenames(String name) 219 { 220 List parts = (List)_partMap.getValues(name); 221 if (parts==null) 222 return null; 223 String [] filenames = new String [parts.size()]; 224 for (int i=0; i<filenames.length; i++) { 225 filenames[i] = ((Part)parts.get(i))._filename; 226 } 227 return filenames; 228 } 229 230 231 private void loadAllParts() 232 throws IOException 233 { 234 String line = _in.readLine(); 236 if (!line.equals(_boundary)) 237 { 238 Code.warning(line); 239 throw new IOException ("Missing initial multi part boundary"); 240 } 241 242 while (!_lastPart) 244 { 245 Part part = new Part(); 247 248 String content_disposition=null; 249 while ((line=_in.readLine())!=null) 250 { 251 if (line.length()==0) 253 break; 254 255 Code.debug("LINE=",line); 256 257 int c = line.indexOf(':',0); 259 if (c>0) 260 { 261 String key = line.substring(0,c).trim().toLowerCase(); 262 String value = line.substring(c+1,line.length()).trim(); 263 String ev = (String ) part._headers.get(key); 264 part._headers.put(key,(ev!=null)?(ev+';'+value):value); 265 Code.debug(key,": ",value); 266 if (key.equals("content-disposition")) 267 content_disposition=value; 268 } 269 } 270 271 boolean form_data=false; 273 if (content_disposition==null) 274 { 275 throw new IOException ("Missing content-disposition"); 276 } 277 278 StringTokenizer tok = 279 new StringTokenizer (content_disposition,";"); 280 while (tok.hasMoreTokens()) 281 { 282 String t = tok.nextToken().trim(); 283 String tl = t.toLowerCase(); 284 if (t.startsWith("form-data")) 285 form_data=true; 286 else if (tl.startsWith("name=")) 287 part._name=value(t); 288 else if (tl.startsWith("filename=")) 289 part._filename=value(t); 290 } 291 292 if (!form_data) 294 { 295 Code.warning("Non form-data part in multipart/form-data"); 296 continue; 297 } 298 if (part._name==null || part._name.length()==0) 299 { 300 Code.warning("Part with no name in multipart/form-data"); 301 continue; 302 } 303 Code.debug("name=",part._name); 304 Code.debug("filename=",part._filename); 305 _partMap.add(part._name,part); 306 part._data=readBytes(); 307 } 308 } 309 310 311 private byte[] readBytes() 312 throws IOException 313 { 314 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 315 316 int c; 317 boolean cr=false; 318 boolean lf=false; 319 320 while (true) 322 { 323 int b=0; 324 while ((c=(_char!=-2)?_char:_in.read())!=-1) 325 { 326 _char=-2; 327 328 if (c==13 || c==10) 330 { 331 if (c==13) _char=_in.read(); 332 break; 333 } 334 335 if (b>=0 && b<_byteBoundary.length && c==_byteBoundary[b]) 337 b++; 338 else 339 { 340 if (cr) baos.write(13); 342 if (lf) baos.write(10); 343 cr=lf=false; 344 345 if (b>0) 346 baos.write(_byteBoundary,0,b); 347 b=-1; 348 349 baos.write(c); 350 } 351 } 352 353 if ((b>0 && b<_byteBoundary.length-2) || 355 (b==_byteBoundary.length-1)) 356 { 357 if (cr) baos.write(13); 358 if (lf) baos.write(10); 359 cr=lf=false; 360 baos.write(_byteBoundary,0,b); 361 b=-1; 362 } 363 364 if (b>0 || c==-1) 366 { 367 if (b==_byteBoundary.length) 368 _lastPart=true; 369 if (_char==10) _char=-2; 370 break; 371 } 372 373 if (cr) baos.write(13); 375 if (lf) baos.write(10); 376 cr=(c==13); 377 lf=(c==10 || _char==10); 378 if (_char==10) _char=-2; 379 } 380 if (Code.verbose()) Code.debug(baos.toString()); 381 return baos.toByteArray(); 382 } 383 384 385 386 private String value(String nameEqualsValue) 387 { 388 String value = 389 nameEqualsValue.substring(nameEqualsValue.indexOf('=')+1).trim(); 390 391 int i=value.indexOf(';'); 392 if (i>0) 393 value=value.substring(0,i); 394 if (value.startsWith("\"")) 395 { 396 value=value.substring(1,value.indexOf('"',1)); 397 } 398 399 else 400 { 401 i=value.indexOf(' '); 402 if (i>0) 403 value=value.substring(0,i); 404 } 405 return value; 406 } 407 408 409 private class Part 410 { 411 String _name=null; 412 String _filename=null; 413 Hashtable _headers= new Hashtable (10); 414 byte[] _data=null; 415 } 416 }; 417 | Popular Tags |