1 17 18 19 package org.apache.tomcat.util.http.fileupload; 20 21 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.io.OutputStream ; 25 import java.util.ArrayList ; 26 import java.util.HashMap ; 27 import java.util.List ; 28 import java.util.Map ; 29 import javax.servlet.http.HttpServletRequest ; 30 31 32 55 public abstract class FileUploadBase 56 { 57 58 60 61 70 public static final boolean isMultipartContent(HttpServletRequest req) 71 { 72 String contentType = req.getHeader(CONTENT_TYPE); 73 if (contentType == null) 74 { 75 return false; 76 } 77 if (contentType.startsWith(MULTIPART)) 78 { 79 return true; 80 } 81 return false; 82 } 83 84 85 87 88 91 public static final String CONTENT_TYPE = "Content-type"; 92 93 94 97 public static final String CONTENT_DISPOSITION = "Content-disposition"; 98 99 100 103 public static final String FORM_DATA = "form-data"; 104 105 106 109 public static final String ATTACHMENT = "attachment"; 110 111 112 115 public static final String MULTIPART = "multipart/"; 116 117 118 121 public static final String MULTIPART_FORM_DATA = "multipart/form-data"; 122 123 124 127 public static final String MULTIPART_MIXED = "multipart/mixed"; 128 129 130 134 public static final int MAX_HEADER_SIZE = 1024; 135 136 137 139 140 144 private long sizeMax = -1; 145 146 147 150 private String headerEncoding; 151 152 153 155 156 161 public abstract FileItemFactory getFileItemFactory(); 162 163 164 169 public abstract void setFileItemFactory(FileItemFactory factory); 170 171 172 180 public long getSizeMax() 181 { 182 return sizeMax; 183 } 184 185 186 194 public void setSizeMax(long sizeMax) 195 { 196 this.sizeMax = sizeMax; 197 } 198 199 200 207 public String getHeaderEncoding() 208 { 209 return headerEncoding; 210 } 211 212 213 220 public void setHeaderEncoding(String encoding) 221 { 222 headerEncoding = encoding; 223 } 224 225 226 228 229 242 public List parseRequest(HttpServletRequest req) 243 throws FileUploadException 244 { 245 if (null == req) 246 { 247 throw new NullPointerException ("req parameter"); 248 } 249 250 ArrayList items = new ArrayList (); 251 String contentType = req.getHeader(CONTENT_TYPE); 252 253 if ((null == contentType) || (!contentType.startsWith(MULTIPART))) 254 { 255 throw new InvalidContentTypeException( 256 "the request doesn't contain a " 257 + MULTIPART_FORM_DATA 258 + " or " 259 + MULTIPART_MIXED 260 + " stream, content type header is " 261 + contentType); 262 } 263 int requestSize = req.getContentLength(); 264 265 if (requestSize == -1) 266 { 267 throw new UnknownSizeException( 268 "the request was rejected because it's size is unknown"); 269 } 270 271 if (sizeMax >= 0 && requestSize > sizeMax) 272 { 273 throw new SizeLimitExceededException( 274 "the request was rejected because " 275 + "it's size exceeds allowed range"); 276 } 277 278 try 279 { 280 int boundaryIndex = contentType.indexOf("boundary="); 281 if (boundaryIndex < 0) 282 { 283 throw new FileUploadException( 284 "the request was rejected because " 285 + "no multipart boundary was found"); 286 } 287 byte[] boundary = contentType.substring( 288 boundaryIndex + 9).getBytes(); 289 290 InputStream input = req.getInputStream(); 291 292 MultipartStream multi = new MultipartStream(input, boundary); 293 multi.setHeaderEncoding(headerEncoding); 294 295 boolean nextPart = multi.skipPreamble(); 296 while (nextPart) 297 { 298 Map headers = parseHeaders(multi.readHeaders()); 299 String fieldName = getFieldName(headers); 300 if (fieldName != null) 301 { 302 String subContentType = getHeader(headers, CONTENT_TYPE); 303 if (subContentType != null && subContentType 304 .startsWith(MULTIPART_MIXED)) 305 { 306 byte[] subBoundary = 308 subContentType.substring( 309 subContentType 310 .indexOf("boundary=") + 9).getBytes(); 311 multi.setBoundary(subBoundary); 312 boolean nextSubPart = multi.skipPreamble(); 313 while (nextSubPart) 314 { 315 headers = parseHeaders(multi.readHeaders()); 316 if (getFileName(headers) != null) 317 { 318 FileItem item = 319 createItem(headers, false); 320 OutputStream os = item.getOutputStream(); 321 try 322 { 323 multi.readBodyData(os); 324 } 325 finally 326 { 327 os.close(); 328 } 329 items.add(item); 330 } 331 else 332 { 333 multi.discardBodyData(); 336 } 337 nextSubPart = multi.readBoundary(); 338 } 339 multi.setBoundary(boundary); 340 } 341 else 342 { 343 if (getFileName(headers) != null) 344 { 345 FileItem item = createItem(headers, false); 347 OutputStream os = item.getOutputStream(); 348 try 349 { 350 multi.readBodyData(os); 351 } 352 finally 353 { 354 os.close(); 355 } 356 items.add(item); 357 } 358 else 359 { 360 FileItem item = createItem(headers, true); 362 OutputStream os = item.getOutputStream(); 363 try 364 { 365 multi.readBodyData(os); 366 } 367 finally 368 { 369 os.close(); 370 } 371 items.add(item); 372 } 373 } 374 } 375 else 376 { 377 multi.discardBodyData(); 379 } 380 nextPart = multi.readBoundary(); 381 } 382 } 383 catch (IOException e) 384 { 385 throw new FileUploadException( 386 "Processing of " + MULTIPART_FORM_DATA 387 + " request failed. " + e.getMessage()); 388 } 389 390 return items; 391 } 392 393 394 396 397 405 protected String getFileName(Map headers) 406 { 407 String fileName = null; 408 String cd = getHeader(headers, CONTENT_DISPOSITION); 409 if (cd.startsWith(FORM_DATA) || cd.startsWith(ATTACHMENT)) 410 { 411 int start = cd.indexOf("filename=\""); 412 int end = cd.indexOf('"', start + 10); 413 if (start != -1 && end != -1) 414 { 415 fileName = cd.substring(start + 10, end).trim(); 416 } 417 } 418 return fileName; 419 } 420 421 422 430 protected String getFieldName(Map headers) 431 { 432 String fieldName = null; 433 String cd = getHeader(headers, CONTENT_DISPOSITION); 434 if (cd != null && cd.startsWith(FORM_DATA)) 435 { 436 int start = cd.indexOf("name=\""); 437 int end = cd.indexOf('"', start + 6); 438 if (start != -1 && end != -1) 439 { 440 fieldName = cd.substring(start + 6, end); 441 } 442 } 443 return fieldName; 444 } 445 446 447 459 protected FileItem createItem(Map headers, 460 boolean isFormField) 461 throws FileUploadException 462 { 463 return getFileItemFactory().createItem(getFieldName(headers), 464 getHeader(headers, CONTENT_TYPE), 465 isFormField, 466 getFileName(headers)); 467 } 468 469 470 482 protected Map parseHeaders(String headerPart) 483 { 484 Map headers = new HashMap (); 485 char buffer[] = new char[MAX_HEADER_SIZE]; 486 boolean done = false; 487 int j = 0; 488 int i; 489 String header, headerName, headerValue; 490 try 491 { 492 while (!done) 493 { 494 i = 0; 495 while (i < 2 || buffer[i - 2] != '\r' || buffer[i - 1] != '\n') 498 { 499 buffer[i++] = headerPart.charAt(j++); 500 } 501 header = new String (buffer, 0, i - 2); 502 if (header.equals("")) 503 { 504 done = true; 505 } 506 else 507 { 508 if (header.indexOf(':') == -1) 509 { 510 continue; 512 } 513 headerName = header.substring(0, header.indexOf(':')) 514 .trim().toLowerCase(); 515 headerValue = 516 header.substring(header.indexOf(':') + 1).trim(); 517 if (getHeader(headers, headerName) != null) 518 { 519 headers.put(headerName, 522 getHeader(headers, headerName) + ',' 523 + headerValue); 524 } 525 else 526 { 527 headers.put(headerName, headerValue); 528 } 529 } 530 } 531 } 532 catch (IndexOutOfBoundsException e) 533 { 534 } 537 return headers; 538 } 539 540 541 551 protected final String getHeader(Map headers, 552 String name) 553 { 554 return (String ) headers.get(name.toLowerCase()); 555 } 556 557 558 561 public static class InvalidContentTypeException 562 extends FileUploadException 563 { 564 568 public InvalidContentTypeException() 569 { 570 super(); 571 } 572 573 579 public InvalidContentTypeException(String message) 580 { 581 super(message); 582 } 583 } 584 585 586 589 public static class UnknownSizeException 590 extends FileUploadException 591 { 592 596 public UnknownSizeException() 597 { 598 super(); 599 } 600 601 607 public UnknownSizeException(String message) 608 { 609 super(message); 610 } 611 } 612 613 614 617 public static class SizeLimitExceededException 618 extends FileUploadException 619 { 620 624 public SizeLimitExceededException() 625 { 626 super(); 627 } 628 629 635 public SizeLimitExceededException(String message) 636 { 637 super(message); 638 } 639 } 640 641 } 642 | Popular Tags |