1 package org.cofax.cms; 2 3 import java.util.Hashtable ; 4 import java.io.BufferedOutputStream ; 5 import java.io.BufferedInputStream ; 6 import java.io.InputStream ; 7 import java.io.PrintWriter ; 8 import java.io.FileOutputStream ; 9 import java.io.IOException ; 10 import java.util.Enumeration ; 11 import java.io.File ; 12 13 59 60 public class MultipartRequest { 61 private PrintWriter debug = null; 63 64 private Hashtable htParameters = null; 65 66 private Hashtable htFiles = null; 67 68 private String strBoundary = null; 69 70 private File fileOutPutDirectory = null; 72 73 private long intContentLength = -1; 74 75 private long intTotalRead = -1; 76 77 82 public static final int MAX_READ_BYTES = 2 * (1024 * 1024); 84 87 public static final int READ_LINE_BLOCK = 1024 * 128; 88 89 93 private byte[] blockOfBytes = null; 94 95 98 private static final int FILENAME = 0; 99 100 private static final int CONTENT_TYPE = 1; 101 102 private static final int SIZE = 2; 103 104 128 public MultipartRequest(String strContentTypeText, int intContentLength, InputStream in, String strSaveDirectory) throws IllegalArgumentException , 129 IOException { 130 this(null, strContentTypeText, intContentLength, in, strSaveDirectory); 131 } 132 133 159 public MultipartRequest(PrintWriter debug, String strContentTypeText, int intContentLength, InputStream in, String strSaveDirectory) 160 throws IllegalArgumentException , IOException { 161 162 this.debug = debug; 163 164 if (strContentTypeText != null && strContentTypeText.startsWith("multipart/form-data") && strContentTypeText.indexOf("boundary=") != -1) { 165 strBoundary = strContentTypeText.substring(strContentTypeText.indexOf("boundary=") + "boundary=".length()).trim(); 166 } else { 167 throw new IllegalArgumentException ("Invalid Content Type."); 168 } 169 170 this.intContentLength = intContentLength; 171 if (intContentLength > CofaxToolsServlet.uploadMaxSize * 1000 * 1000) 172 throw new IOException ("Invalid Content Length: " + intContentLength); 173 174 htParameters = new Hashtable (); 176 htFiles = new Hashtable (); 177 178 blockOfBytes = new byte[READ_LINE_BLOCK]; 179 180 if (strSaveDirectory != null) { 183 CofaxToolsUtil.log("directory is " + strSaveDirectory); 184 fileOutPutDirectory = new File (strSaveDirectory); 185 if (!fileOutPutDirectory.exists()) { 186 throw new IOException ("Multipart Directory does not exist."); 187 } 188 189 if (!fileOutPutDirectory.canWrite()) { 190 throw new IOException ("Multipart Directory cannot be written to."); 191 } 192 } 193 194 parse(new BufferedInputStream (in)); 196 197 this.blockOfBytes = null; 199 this.debug = null; 200 this.strBoundary = null; 201 } 202 203 206 public String getURLParameter(String strParameter) { 207 return (String ) htParameters.get(strParameter); 208 } 209 210 213 public Enumeration getParameterNames() { 214 return htParameters.keys(); 215 } 216 217 public Enumeration getFileParameterNames() { 218 return htFiles.keys(); 219 } 220 221 224 public String getContentType(String strName) { 225 Object [] objArray = (Object []) htFiles.get(strName); 226 if (objArray != null && objArray[CONTENT_TYPE] != null) 227 return (String ) objArray[CONTENT_TYPE]; 228 else 229 return null; 230 } 231 232 241 public File getFile(String strName) { 242 String filename = getFileSystemName(strName); 243 if (filename != null && getFileSize(strName) > 0 && fileOutPutDirectory != null) 246 return new File (fileOutPutDirectory, filename); 247 else 248 return null; 249 } 250 251 254 public String getFileSystemName(String strName) { 255 Object [] objArray = (Object []) htFiles.get(strName); 256 if (objArray != null && objArray[FILENAME] != null) 257 return (String ) objArray[FILENAME]; 258 else 259 return null; 260 } 261 262 267 public long getFileSize(String strName) { 268 Object [] objArray = (Object []) htFiles.get(strName); 269 if (objArray != null && objArray[SIZE] != null) 270 return ((Long ) objArray[SIZE]).longValue(); 271 else 272 return (long) -1; 273 } 274 275 private void parse(InputStream in) throws IOException { 276 String strContentType = null; 277 String strName = null; 278 String strFilename = null; 279 String strLine = null; 280 int read = -1; 281 282 read = readLine(in, blockOfBytes); 285 strLine = read > 0 ? new String (blockOfBytes, 0, read) : null; 286 287 if (strLine == null || strLine.indexOf(this.strBoundary) == -1) 289 throw new IOException ("Invalid Form Data, no boundary encountered."); 290 291 while (true) { 294 read = readLine(in, blockOfBytes); 296 if (read <= 0) 297 break; else { 299 strLine = new String (blockOfBytes, 0, read); 300 301 strName = trimQuotes(getValue("name", strLine)); 304 strFilename = trimQuotes(getValue("filename", strLine)); 307 309 if (strFilename != null) { 310 311 htParameters.put(strName, strFilename); 312 if (strFilename.length() > 0) { 315 read = readLine(in, blockOfBytes); 317 strLine = read > 0 ? new String (blockOfBytes, 0, read) : null; 318 strContentType = "application/octet-stream"; 319 if (strLine != null && strLine.length() > "Content-Type: ".length()) 322 strContentType = strLine.substring("Content-Type: ".length()); } else 325 readLine(in, blockOfBytes); 326 } 327 ; 328 readLine(in, blockOfBytes); 330 331 if (strFilename == null) { 333 String param = readParameter(in); 335 if ((param != null) && (strName != null)) { 336 htParameters.put(strName, param); 337 } else if ((param == null) && (strName != null)) { 338 htParameters.put(strName, ""); 339 } 340 } else { 341 if (strFilename.length() > 0) { 342 strFilename = getBasename(strFilename); 344 345 long filesize = readAndWriteFile(in, strFilename); 347 if (filesize > 0) 348 htFiles.put(strName, new Object [] { strFilename, strContentType, new Long (filesize) }); 349 else 350 htFiles.put(strName, new Object [] { strFilename, null, new Long (0) }); 352 } else { 355 htFiles.put(strName, new Object [] { null, null, null }); 356 readLine(in, blockOfBytes); 357 } 358 } 359 } 360 } } 362 363 369 private String readParameter(InputStream in) throws IOException { 370 StringBuffer buf = new StringBuffer (); 371 int read = -1; 372 373 while (true) { 374 read = readLine(in, blockOfBytes); 375 if (read < 0) 376 throw new IOException ("Stream ended prematurely."); 377 else if (read < blockOfBytes.length && new String (blockOfBytes, 0, read).indexOf(this.strBoundary) != -1) 378 break; else 380 buf.append(getCharArray(blockOfBytes, read)); 381 } 382 383 if (buf.length() > 0) 384 buf.setLength(getLengthMinusEnding(buf)); 385 return buf.toString(); 386 } 387 388 399 private long readAndWriteFile(InputStream in, String strFilename) throws IOException { 400 BufferedOutputStream file = null; 402 403 long fileSize = 0; 404 int read = -1; 405 byte[] endOfLineBytes = null; 407 408 while (true) { 409 read = readLine(in, blockOfBytes); 410 411 if (read < 0) { 412 if (file != null) { 414 file.flush(); 415 file.close(); 416 } 417 throw new IOException ("Stream ended prematurely."); 418 } else if (read < blockOfBytes.length && new String (blockOfBytes, 0, read).indexOf(this.strBoundary) != -1) { 419 if (file != null) { 421 file.flush(); 422 file.close(); 423 } 424 break; 425 } else { 426 int length = getLengthMinusEnding(blockOfBytes, read); 428 429 if (file == null && fileOutPutDirectory != null && (endOfLineBytes != null || length > 0)) 434 file = new BufferedOutputStream (new FileOutputStream (new File (fileOutPutDirectory, strFilename))); 435 436 if (endOfLineBytes != null) { 438 if (file != null) { 440 file.write(endOfLineBytes); 441 fileSize += endOfLineBytes.length; 443 } 444 } 445 446 if (length > 0) { 448 if (file != null) { 450 file.write(blockOfBytes, 0, length); 451 fileSize += length; 453 } 454 } 455 456 if (endOfLineBytes == null || endOfLineBytes.length != read - length) 459 endOfLineBytes = new byte[read - length]; 460 System.arraycopy(blockOfBytes, length, endOfLineBytes, 0, endOfLineBytes.length); 461 } 462 } 463 464 return fileSize; 465 } 466 467 476 private static final int getLengthMinusEnding(byte byteLine[], int endOfArray) { 477 if (byteLine == null) 478 return 0; 479 480 if (endOfArray >= 2 && byteLine[endOfArray - 2] == '\r' && byteLine[endOfArray - 1] == '\n') 481 return endOfArray - 2; 482 else if (endOfArray >= 1 && byteLine[endOfArray - 1] == '\n' || byteLine[endOfArray - 1] == '\r') 483 return endOfArray - 1; 484 else 485 return endOfArray; 486 } 487 488 private static final int getLengthMinusEnding(StringBuffer buf) { 489 if (buf.length() >= 2 && buf.charAt(buf.length() - 2) == '\r' && buf.charAt(buf.length() - 1) == '\n') 490 return buf.length() - 2; 491 else if (buf.length() >= 1 && buf.charAt(buf.length() - 1) == '\n' || buf.charAt(buf.length() - 1) == '\r') 492 return buf.length() - 1; 493 else 494 return buf.length(); 495 } 496 497 504 private static final char[] getCharArray(byte byteLine[], int length) { 505 if (byteLine == null) 506 return null; 507 508 if (length <= 0) 510 length = byteLine.length; 511 512 char[] charArray = new char[length]; 513 for (int i = 0; i < length; i++) 514 charArray[i] = (char) byteLine[i]; 515 516 return charArray; 517 } 518 519 534 private int readLine(InputStream in, byte[] bytesToBeRead) throws IOException { 535 if (intTotalRead >= intContentLength) 537 return -1; 538 539 int length = bytesToBeRead.length; 541 542 if (length > (intContentLength - intTotalRead)) 546 length = (int) (intContentLength - intTotalRead); 550 int result = readLine(in, bytesToBeRead, 0, length); 551 if (result > 0) 554 intTotalRead += result; 555 556 return result; 557 } 558 559 565 private static final String getBasename(String strFilename) { 566 if (strFilename == null) 567 return strFilename; 568 569 int intIndex = strFilename.lastIndexOf("/"); 570 if (intIndex == -1 || strFilename.lastIndexOf("\\") > intIndex) 571 intIndex = strFilename.lastIndexOf("\\"); 572 573 if (intIndex != -1) 574 return strFilename.substring(intIndex + 1); 575 else 576 return strFilename; 577 } 578 579 583 private static final String trimQuotes(String strItem) { 584 if (strItem == null || strItem.indexOf("\"") == -1) 586 return strItem; 587 588 strItem = strItem.trim(); 590 591 if (strItem.charAt(0) == '\"') 592 strItem = strItem.substring(1); 593 594 if (strItem.charAt(strItem.length() - 1) == '\"') 595 strItem = strItem.substring(0, strItem.length() - 1); 596 597 return strItem; 598 } 599 600 605 private static final String getValue(String strName, String strToDecode) { 606 strName = strName + "="; 607 608 int startIndexOf = 0; 609 while (startIndexOf < strToDecode.length()) { 610 int indexOf = strToDecode.indexOf(strName, startIndexOf); 611 if (indexOf != -1) { 613 if (indexOf == 0 || Character.isWhitespace(strToDecode.charAt(indexOf - 1)) || strToDecode.charAt(indexOf - 1) == ';') { 614 int endIndexOf = strToDecode.indexOf(";", indexOf + strName.length()); 615 if (endIndexOf == -1) return strToDecode.substring(indexOf + strName.length()); 617 else 618 return strToDecode.substring(indexOf + strName.length(), endIndexOf); 619 } else 620 startIndexOf = indexOf + strName.length(); 621 } else 622 return null; 623 } 624 return null; 625 } 626 627 655 private int readLine(InputStream in, byte[] b, int off, int len) throws IOException { 656 if (len <= 0) 657 return 0; 658 659 int count = 0, c; 660 661 while ((c = in.read()) != -1) { 662 b[off++] = (byte) c; 663 count++; 664 if (c == '\n' || count == len) 665 break; 666 } 667 return count > 0 ? count : -1; 668 } 669 670 673 public String getHtmlTable() { 674 StringBuffer sbReturn = new StringBuffer (); 675 676 sbReturn.append("<H1>Parameters</h1>"); 677 sbReturn.append("\n<table border=2><tr><td><b>Name</b></td><td><b>Value</b></td></tr>"); 678 for (Enumeration e = getParameterNames(); e.hasMoreElements();) { 679 String strName = (String ) e.nextElement(); 680 sbReturn.append("\n<tr>" + "<td>" + strName + "</td>" + "<td>" + getURLParameter(strName) + "</td>" + "</tr>"); 681 } 682 sbReturn.append("</table>"); 683 684 sbReturn 685 .append("\n<table border=2><tr><td><b>Name</b></td><td><b>Filename</b></td><td><b>Path</b></td><td><b>Content Type</b></td><td><b>Size</b></td></tr>"); 686 for (Enumeration e = getFileParameterNames(); e.hasMoreElements();) { 687 String strName = (String ) e.nextElement(); 688 689 sbReturn.append("\n<tr>" + "<td>" + strName + "</td>" + "<td>" + (getFileSystemName(strName) != null ? getFileSystemName(strName) : "") + "</td>" 690 + "<td>" + (getFile(strName) != null ? getFile(strName).getAbsolutePath() : "") + "</td>" + "<td>" 691 + (getContentType(strName) != null ? getContentType(strName) : "") + "</td>" + "<td>" 692 + (getFileSize(strName) != -1 ? getFileSize(strName) + "" : "") + "</td>" + "</tr>"); 693 } 694 sbReturn.append("</table>"); 695 696 return sbReturn.toString(); 697 } 698 699 private void debug(String x) { 701 if (debug != null) 702 debug.println(x); 703 } 704 } 705 | Popular Tags |