00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 package org.apache.commons.fileupload;
00064
00065
00066 import java.io.IOException;
00067 import java.io.InputStream;
00068 import java.io.OutputStream;
00069 import java.util.ArrayList;
00070 import java.util.HashMap;
00071 import java.util.List;
00072 import java.util.Map;
00073 import javax.servlet.http.HttpServletRequest;
00074
00075
00099 public abstract class FileUploadBase
00100 {
00101
00102
00103
00104
00114 public static final boolean isMultipartContent(HttpServletRequest req)
00115 {
00116 String contentType = req.getHeader(CONTENT_TYPE);
00117 if (contentType == null)
00118 {
00119 return false;
00120 }
00121 if (contentType.startsWith(MULTIPART))
00122 {
00123 return true;
00124 }
00125 return false;
00126 }
00127
00128
00129
00130
00131
00135 public static final String CONTENT_TYPE = "Content-type";
00136
00137
00141 public static final String CONTENT_DISPOSITION = "Content-disposition";
00142
00143
00147 public static final String FORM_DATA = "form-data";
00148
00149
00153 public static final String ATTACHMENT = "attachment";
00154
00155
00159 public static final String MULTIPART = "multipart/";
00160
00161
00165 public static final String MULTIPART_FORM_DATA = "multipart/form-data";
00166
00167
00171 public static final String MULTIPART_MIXED = "multipart/mixed";
00172
00173
00178 public static final int MAX_HEADER_SIZE = 1024;
00179
00180
00181
00182
00183
00188 private long sizeMax = -1;
00189
00190
00194 private String headerEncoding;
00195
00196
00197
00198
00199
00205 public abstract FileItemFactory getFileItemFactory();
00206
00207
00213 public abstract void setFileItemFactory(FileItemFactory factory);
00214
00215
00224 public long getSizeMax()
00225 {
00226 return sizeMax;
00227 }
00228
00229
00238 public void setSizeMax(long sizeMax)
00239 {
00240 this.sizeMax = sizeMax;
00241 }
00242
00243
00251 public String getHeaderEncoding()
00252 {
00253 return headerEncoding;
00254 }
00255
00256
00264 public void setHeaderEncoding(String encoding)
00265 {
00266 headerEncoding = encoding;
00267 }
00268
00269
00270
00271
00272
00286 public List parseRequest(HttpServletRequest req)
00287 throws FileUploadException
00288 {
00289 if (null == req)
00290 {
00291 throw new NullPointerException("req parameter");
00292 }
00293
00294 ArrayList items = new ArrayList();
00295 String contentType = req.getHeader(CONTENT_TYPE);
00296
00297 if ((null == contentType) || (!contentType.startsWith(MULTIPART)))
00298 {
00299 throw new InvalidContentTypeException(
00300 "the request doesn't contain a "
00301 + MULTIPART_FORM_DATA
00302 + " or "
00303 + MULTIPART_MIXED
00304 + " stream, content type header is "
00305 + contentType);
00306 }
00307 int requestSize = req.getContentLength();
00308
00309 if (requestSize == -1)
00310 {
00311 throw new UnknownSizeException(
00312 "the request was rejected because it's size is unknown");
00313 }
00314
00315 if (sizeMax >= 0 && requestSize > sizeMax)
00316 {
00317 throw new SizeLimitExceededException(
00318 "the request was rejected because "
00319 + "it's size exceeds allowed range");
00320 }
00321
00322 try
00323 {
00324 int boundaryIndex = contentType.indexOf("boundary=");
00325 if (boundaryIndex < 0)
00326 {
00327 throw new FileUploadException(
00328 "the request was rejected because "
00329 + "no multipart boundary was found");
00330 }
00331 byte[] boundary = contentType.substring(
00332 boundaryIndex + 9).getBytes();
00333
00334 InputStream input = req.getInputStream();
00335
00336 MultipartStream multi = new MultipartStream(input, boundary);
00337 multi.setHeaderEncoding(headerEncoding);
00338
00339 boolean nextPart = multi.skipPreamble();
00340 while (nextPart)
00341 {
00342 Map headers = parseHeaders(multi.readHeaders());
00343 String fieldName = getFieldName(headers);
00344 if (fieldName != null)
00345 {
00346 String subContentType = getHeader(headers, CONTENT_TYPE);
00347 if (subContentType != null && subContentType
00348 .startsWith(MULTIPART_MIXED))
00349 {
00350
00351 byte[] subBoundary =
00352 subContentType.substring(
00353 subContentType
00354 .indexOf("boundary=") + 9).getBytes();
00355 multi.setBoundary(subBoundary);
00356 boolean nextSubPart = multi.skipPreamble();
00357 while (nextSubPart)
00358 {
00359 headers = parseHeaders(multi.readHeaders());
00360 if (getFileName(headers) != null)
00361 {
00362 FileItem item =
00363 createItem(headers, false);
00364 OutputStream os = item.getOutputStream();
00365 try
00366 {
00367 multi.readBodyData(os);
00368 }
00369 finally
00370 {
00371 os.close();
00372 }
00373 items.add(item);
00374 }
00375 else
00376 {
00377
00378
00379 multi.discardBodyData();
00380 }
00381 nextSubPart = multi.readBoundary();
00382 }
00383 multi.setBoundary(boundary);
00384 }
00385 else
00386 {
00387 if (getFileName(headers) != null)
00388 {
00389
00390 FileItem item = createItem(headers, false);
00391 OutputStream os = item.getOutputStream();
00392 try
00393 {
00394 multi.readBodyData(os);
00395 }
00396 finally
00397 {
00398 os.close();
00399 }
00400 items.add(item);
00401 }
00402 else
00403 {
00404
00405 FileItem item = createItem(headers, true);
00406 OutputStream os = item.getOutputStream();
00407 try
00408 {
00409 multi.readBodyData(os);
00410 }
00411 finally
00412 {
00413 os.close();
00414 }
00415 items.add(item);
00416 }
00417 }
00418 }
00419 else
00420 {
00421
00422 multi.discardBodyData();
00423 }
00424 nextPart = multi.readBoundary();
00425 }
00426 }
00427 catch (IOException e)
00428 {
00429 throw new FileUploadException(
00430 "Processing of " + MULTIPART_FORM_DATA
00431 + " request failed. " + e.getMessage());
00432 }
00433
00434 return items;
00435 }
00436
00437
00438
00439
00440
00449 protected String getFileName(Map headers)
00450 {
00451 String fileName = null;
00452 String cd = getHeader(headers, CONTENT_DISPOSITION);
00453 if (cd.startsWith(FORM_DATA) || cd.startsWith(ATTACHMENT))
00454 {
00455 int start = cd.indexOf("filename=\"");
00456 int end = cd.indexOf('"', start + 10);
00457 if (start != -1 && end != -1)
00458 {
00459 fileName = cd.substring(start + 10, end).trim();
00460 }
00461 }
00462 return fileName;
00463 }
00464
00465
00474 protected String getFieldName(Map headers)
00475 {
00476 String fieldName = null;
00477 String cd = getHeader(headers, CONTENT_DISPOSITION);
00478 if (cd != null && cd.startsWith(FORM_DATA))
00479 {
00480 int start = cd.indexOf("name=\"");
00481 int end = cd.indexOf('"', start + 6);
00482 if (start != -1 && end != -1)
00483 {
00484 fieldName = cd.substring(start + 6, end);
00485 }
00486 }
00487 return fieldName;
00488 }
00489
00490
00503 protected FileItem createItem(Map headers,
00504 boolean isFormField)
00505 throws FileUploadException
00506 {
00507 return getFileItemFactory().createItem(getFieldName(headers),
00508 getHeader(headers, CONTENT_TYPE),
00509 isFormField,
00510 getFileName(headers));
00511 }
00512
00513
00526 protected Map parseHeaders(String headerPart)
00527 {
00528 Map headers = new HashMap();
00529 char buffer[] = new char[MAX_HEADER_SIZE];
00530 boolean done = false;
00531 int j = 0;
00532 int i;
00533 String header, headerName, headerValue;
00534 try
00535 {
00536 while (!done)
00537 {
00538 i = 0;
00539
00540
00541 while (i < 2 || buffer[i - 2] != '\r' || buffer[i - 1] != '\n')
00542 {
00543 buffer[i++] = headerPart.charAt(j++);
00544 }
00545 header = new String(buffer, 0, i - 2);
00546 if (header.equals(""))
00547 {
00548 done = true;
00549 }
00550 else
00551 {
00552 if (header.indexOf(':') == -1)
00553 {
00554
00555 continue;
00556 }
00557 headerName = header.substring(0, header.indexOf(':'))
00558 .trim().toLowerCase();
00559 headerValue =
00560 header.substring(header.indexOf(':') + 1).trim();
00561 if (getHeader(headers, headerName) != null)
00562 {
00563
00564
00565 headers.put(headerName,
00566 getHeader(headers, headerName) + ','
00567 + headerValue);
00568 }
00569 else
00570 {
00571 headers.put(headerName, headerValue);
00572 }
00573 }
00574 }
00575 }
00576 catch (IndexOutOfBoundsException e)
00577 {
00578
00579
00580 }
00581 return headers;
00582 }
00583
00584
00595 protected final String getHeader(Map headers,
00596 String name)
00597 {
00598 return (String) headers.get(name.toLowerCase());
00599 }
00600
00601
00605 public static class InvalidContentTypeException
00606 extends FileUploadException
00607 {
00612 public InvalidContentTypeException()
00613 {
00614 super();
00615 }
00616
00623 public InvalidContentTypeException(String message)
00624 {
00625 super(message);
00626 }
00627 }
00628
00629
00633 public static class UnknownSizeException
00634 extends FileUploadException
00635 {
00640 public UnknownSizeException()
00641 {
00642 super();
00643 }
00644
00651 public UnknownSizeException(String message)
00652 {
00653 super(message);
00654 }
00655 }
00656
00657
00661 public static class SizeLimitExceededException
00662 extends FileUploadException
00663 {
00668 public SizeLimitExceededException()
00669 {
00670 super();
00671 }
00672
00679 public SizeLimitExceededException(String message)
00680 {
00681 super(message);
00682 }
00683 }
00684
00685 }