1 23 24 package com.sun.enterprise.tools.admingui.servlet; 25 33 34 import java.io.BufferedOutputStream ; 35 import java.io.ByteArrayOutputStream ; 36 import java.io.File ; 37 import java.io.FileOutputStream ; 38 import java.io.FilterInputStream ; 39 import java.io.IOException ; 40 import java.io.InputStream ; 41 import java.io.OutputStream ; 42 import java.util.Enumeration ; 43 import java.util.Hashtable ; 44 import java.util.HashMap ; 45 import java.util.Vector ; 46 47 import javax.servlet.ServletInputStream ; 48 import javax.servlet.http.HttpServletRequest ; 49 50 53 public class MultipartHandler { 54 55 private static final int DEFAULT_MAX_UPLOAD_SIZE = 1024 * 1024; 57 protected Hashtable formFields = new Hashtable (); protected Hashtable uploadFiles = new Hashtable (); 60 61 private HttpServletRequest req; 62 63 64 private ServletInputStream in; 65 66 67 private String boundary; 68 69 70 private byte[] buf = new byte[8 * 1024]; 71 72 73 private File uploadDir; 74 75 76 private String fieldEncoding = "ISO-8859-1"; 77 78 81 82 85 public MultipartHandler(HttpServletRequest request, 86 String tmpDirectory) throws IOException { 87 this(request, tmpDirectory, DEFAULT_MAX_UPLOAD_SIZE, "ISO-8859-1"); 88 } 89 90 public MultipartHandler(HttpServletRequest request, 91 String tmpDirectory, 92 int maxUploadSize) throws IOException { 93 this(request, tmpDirectory, maxUploadSize, "ISO-8859-1"); 94 } 95 96 109 public MultipartHandler(HttpServletRequest request, 110 String tmpDirectory, 111 int maxUploadSize, 112 String fieldEncoding) throws IOException { 113 114 if (request == null) { 116 throw new IllegalArgumentException ( "request is null" ); 118 } 119 if (tmpDirectory == null) { 120 throw new IllegalArgumentException ( "tmp Dir is null" ); 122 } 123 if (maxUploadSize <= 0) { 124 throw new IllegalArgumentException ( "Max size is < 0" ); 126 } 127 128 uploadDir = new File (tmpDirectory); 130 if (!uploadDir.isDirectory()) { 131 throw new IllegalArgumentException ( "Not a Directory" ); 133 } 134 if (!uploadDir.canWrite()) { 135 throw new IllegalArgumentException ("write protected" ); 137 } 138 int length = request.getContentLength(); 139 144 String type = request.getContentType(); 146 if (type == null || 147 !type.toLowerCase().startsWith("multipart/form-data")) { 148 throw new IOException ( "type null" ); 150 } 151 152 this.fieldEncoding = fieldEncoding; 154 this.req = request; 155 } 156 157 163 public void parseMultipartUpload() 164 throws IOException { 165 startMultipartParse(); 168 169 HashMap partHeaders = parsePartHeaders(); 170 while (partHeaders != null) { 171 172 String fieldName = (String )partHeaders.get("fieldName"); 173 String fileName = (String )partHeaders.get("fileName"); 174 175 if (fileName != null) { 176 if (fileName.equals("")) { 178 fileName = null; } 180 181 if (fileName != null) { 182 saveUploadFile( fileName ); 184 185 uploadFiles.put(fieldName, 186 new MultipartFile( 187 uploadDir.toString(), 188 fileName, 189 (String )partHeaders.get("content-type")) 190 ); 191 } 192 else { 193 uploadFiles.put(fieldName, new MultipartFile(null, null, null)); 195 } 196 } 197 else { 198 byte[] valueBytes = parseFormFieldBytes(); 200 String value = new String (valueBytes, fieldEncoding); 201 202 Vector existingValues = (Vector )formFields.get(fieldName); 203 if (existingValues == null) { 204 existingValues = new Vector (); 205 formFields.put(fieldName, existingValues); 206 } 207 existingValues.addElement(value); 208 } 209 210 partHeaders.clear(); 211 partHeaders = parsePartHeaders(); 212 } 213 } 214 215 private void startMultipartParse() 216 throws IOException { 217 String boundary = parseBoundary(req.getContentType()); 220 if (boundary == null) { 221 throw new IOException ( "boundary is nul" ); 223 } 224 225 this.in = req.getInputStream(); 226 this.boundary = boundary; 227 228 String line = readLine(); 230 if (line == null) { 231 throw new IOException ( "line is null" ); 233 } 234 235 if (!line.startsWith(boundary)) { 237 throw new IOException ( "not start with boundary" ); 239 } 240 } 241 242 248 private HashMap parsePartHeaders() throws IOException { 249 HashMap partHeaders = new HashMap (); 250 251 Vector headers = new Vector (); 252 String line = readLine(); 253 if (line == null) { 254 return null; 256 } 257 else if (line.length() == 0) { 258 return null; 260 } 261 headers.addElement(line); 262 263 while ((line = readLine()) != null && (line.length() > 0)) { 265 headers.addElement(line); 266 } 267 268 if (line == null) { 270 return null; 271 } 272 273 partHeaders.put("content-type", "text/plain"); 275 276 Enumeration ee = headers.elements(); 277 while (ee.hasMoreElements()) { 278 String headerline = (String ) ee.nextElement(); 279 280 if (headerline.toLowerCase().startsWith("content-disposition:")) { 281 parseContentDisposition(headerline, partHeaders); 283 } 284 else if (headerline.toLowerCase().startsWith("content-type:")) { 285 parseContentType(headerline, partHeaders); 287 } 288 } 289 290 return partHeaders; 291 } 292 293 296 private String parseBoundary(String line) { 297 int index = line.lastIndexOf("boundary="); 300 if (index == -1) { 301 return null; 302 } 303 String boundary = line.substring(index + 9); if (boundary.charAt(0) == '"') { 305 index = boundary.lastIndexOf('"'); 307 boundary = boundary.substring(1, index); 308 } 309 310 boundary = "--" + boundary; 312 313 return boundary; 314 } 315 316 322 private void parseContentDisposition(String line, HashMap partHeaders) 323 throws IOException { 324 325 String origline = line; 328 line = origline.toLowerCase(); 329 330 int start = line.indexOf("content-disposition: "); 332 int end = line.indexOf(";"); 333 if (start == -1 || end == -1) { 334 throw new IOException ( "end reached" ); 336 } 337 String disposition = line.substring(start + 21, end); 338 if (!disposition.equals("form-data")) { 339 throw new IOException ( "fome-data not match" ); 341 } 342 343 start = line.indexOf("name=\"", end); end = line.indexOf("\"", start + 7); if (start == -1 || end == -1) { 347 throw new IOException ( "data corrupt" ); 349 } 350 351 String name = origline.substring(start + 6, end); 352 353 String fileName = null; 355 String origFileName = null; 356 start = line.indexOf("filename=\"", end + 2); end = line.indexOf("\"", start + 10); 359 if (start != -1 && end != -1) { fileName = origline.substring(start + 10, end); 361 origFileName = fileName; 362 int slash = 364 Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\')); 365 if (slash > -1) { 366 fileName = fileName.substring(slash + 1); } 368 } 369 370 partHeaders.put("disposition", disposition); 373 partHeaders.put("fieldName", name); 374 partHeaders.put("fileName", fileName); 375 partHeaders.put("filePath", origFileName); 376 } 377 378 382 private void parseContentType(String line, HashMap partHeaders) 383 throws IOException { 384 String contentType = null; 385 386 String origline = line; 388 line = origline.toLowerCase(); 389 390 if (line.startsWith("content-type")) { 392 int start = line.indexOf(" "); 393 394 if (start == -1) { 395 throw new IOException ( "no start" ); 397 } 398 contentType = line.substring(start + 1); 399 400 partHeaders.put("content-type", contentType); 401 } 402 else if (line.length() != 0) { throw new IOException ( "length 0" ); 405 } 406 } 407 408 410 private byte[] parseFormFieldBytes() throws IOException { 411 412 MultipartInputStream pis = new MultipartInputStream(in, boundary); 414 415 ByteArrayOutputStream baos = new ByteArrayOutputStream (512); 416 byte[] buf = new byte[128]; 417 int read; 418 while ((read = pis.read(buf)) != -1) { 419 baos.write(buf, 0, read); 420 } 421 pis.close(); 422 baos.close(); 423 424 return baos.toByteArray(); 426 } 427 428 435 private String readLine() throws IOException { 436 StringBuffer sbuf = new StringBuffer (); 437 int result; 438 String line; 439 440 do { 441 result = in.readLine(buf, 0, buf.length); if (result != -1) { 443 sbuf.append(new String (buf, 0, result, "ISO-8859-1")); 444 } 445 } while (result == buf.length); 447 if (sbuf.length() == 0) { 448 return null; } 450 451 int len = sbuf.length(); 454 if (sbuf.charAt(len - 2) == '\r') { 455 sbuf.setLength(len - 2); } 457 else { 458 sbuf.setLength(len - 1); } 460 return sbuf.toString(); 461 } 462 463 466 private long saveUploadFile(String fileName) 467 throws IOException { 468 469 long written = 0; 470 OutputStream fileOut = null; 471 472 try { 473 File file = new File (uploadDir, fileName); 475 476 fileOut = new BufferedOutputStream (new FileOutputStream (file)); 477 int numBytes; 478 byte[] buf = new byte[8 * 1024]; 479 480 481 MultipartInputStream partInput = new MultipartInputStream(in, boundary); 482 483 while((numBytes = partInput.read(buf)) != -1) { 484 fileOut.write(buf, 0, numBytes); 485 written += numBytes; 486 } 487 488 partInput.close(); 489 } 490 finally { 491 if (fileOut != null) fileOut.close(); 492 } 493 494 return written; 495 } 496 497 498 503 public Enumeration getParameterNames() { 504 return formFields.keys(); 505 } 506 507 514 public Enumeration getFileNames() { 515 return uploadFiles.keys(); 516 } 517 518 527 public String getParameter(String name) { 528 try { 529 Vector values = (Vector )formFields.get(name); 530 if (values == null || values.size() == 0) { 531 return null; 532 } 533 String value = (String )values.elementAt(values.size() - 1); 534 return value; 535 } 536 catch (Exception e) { 537 return null; 538 } 539 } 540 541 549 public String [] getParameterValues(String name) { 550 try { 551 Vector values = (Vector )formFields.get(name); 552 if (values == null || values.size() == 0) { 553 return null; 554 } 555 String [] valuesArray = new String [values.size()]; 556 values.copyInto(valuesArray); 557 return valuesArray; 558 } 559 catch (Exception e) { 560 return null; 561 } 562 } 563 564 571 public String getFileName(String name) { 572 try { 573 MultipartFile file = (MultipartFile)uploadFiles.get(name); 574 return file.getFileName(); } 576 catch (Exception e) { 577 return null; 578 } 579 } 580 581 586 public String getFileType(String name) { 587 try { 588 MultipartFile file = (MultipartFile)uploadFiles.get(name); 589 return file.getFileType(); } 591 catch (Exception e) { 592 return null; 593 } 594 } 595 596 601 public File getFile(String name) { 602 try { 603 MultipartFile file = (MultipartFile)uploadFiles.get(name); 604 return file.getFile(); } 606 catch (Exception e) { 607 return null; 608 } 609 } 610 611 614 public void close() throws IOException { 615 req = null; 616 in = null; 617 boundary = null; 618 buf = null; 619 uploadDir = null; 620 } 621 } 622 623 628 class MultipartInputStream extends FilterInputStream { 629 630 private String boundary; 631 632 633 private byte [] buf = new byte[64*1024]; 635 636 private int count; 637 638 639 private int pos; 640 641 642 private boolean eof; 643 644 647 648 653 MultipartInputStream(ServletInputStream in, 654 String boundary) throws IOException { 655 super(in); 656 this.boundary = boundary; 657 } 658 659 668 private void fill() throws IOException 669 { 670 if (eof) 671 return; 672 673 if (count > 0) 675 { 676 if (count - pos == 2) { 678 System.arraycopy(buf, pos, buf, 0, count - pos); 680 count -= pos; 681 pos = 0; 682 } else { 683 throw new IllegalStateException ( "should never happen" ); 686 } 687 } 688 689 int read = 0; 692 int maxRead = buf.length - boundary.length(); 693 while (count < maxRead) { 694 read = ((ServletInputStream )in).readLine(buf, count, buf.length - count); 696 if (read == -1) { 698 throw new IOException ( "read is -1" ); 700 } else { 701 if (read >= boundary.length()) { 702 eof = true; 703 for (int i=0; i < boundary.length(); i++) { 704 if (boundary.charAt(i) != buf[count + i]) { 705 eof = false; 707 break; 708 } 709 } 710 if (eof) { 711 break; 712 } 713 } 714 } 715 count += read; 717 } 718 } 719 720 726 public int read() throws IOException { 727 if (count - pos <= 2) { 728 fill(); 729 if (count - pos <= 2) { 730 return -1; 731 } 732 } 733 return buf[pos++] & 0xff; 734 } 735 736 744 public int read(byte b[]) throws IOException { 745 return read(b, 0, b.length); 746 } 747 748 755 public int read(byte b[], int off, int len) throws IOException 756 { 757 int total = 0; 758 if (len == 0) { 759 return 0; 760 } 761 762 int avail = count - pos - 2; 763 if (avail <= 0) { 764 fill(); 765 avail = count - pos - 2; 766 if(avail <= 0) { 767 return -1; 768 } 769 } 770 int copy = Math.min(len, avail); 771 System.arraycopy(buf, pos, b, off, copy); 772 pos += copy; 773 total += copy; 774 775 while (total < len) { 776 fill(); 777 avail = count - pos - 2; 778 if(avail <= 0) { 779 return total; 780 } 781 copy = Math.min(len - total, avail); 782 System.arraycopy(buf, pos, b, off + total, copy); 783 pos += copy; 784 total += copy; 785 } 786 return total; 787 } 788 789 797 public int available() throws IOException { 798 int avail = (count - pos - 2) + in.available(); 799 return (avail < 0 ? 0 : avail); 801 } 802 803 811 public void close() throws IOException { 812 if (!eof) { 813 while (read(buf, 0, buf.length) != -1) 814 ; } 816 } 817 } 818 819 820 class MultipartFile { 821 822 private String dir; 823 private String filename; 824 private String type; 825 826 MultipartFile(String dir, String filename, String type) { 827 this.dir = dir; 828 this.filename = filename; 829 this.type = type; 830 } 831 832 public String getFileType() { 833 return type; 834 } 835 836 public String getFileName() { 837 return filename; 838 } 839 840 public File getFile() { 841 if (dir == null || filename == null) { 842 return null; 843 } 844 else { 845 return new File (dir + File.separator + filename); 846 } 847 } 848 } 849 | Popular Tags |