1 64 65 package com.jcorporate.expresso.core.misc.upload; 66 67 120 122 import java.io.IOException ; 123 import java.io.InputStream ; 124 import java.io.OutputStream ; 125 126 127 183 public class MultipartStream { 184 185 190 public static final int HEADER_PART_SIZE_MAX = 10240; 191 192 195 protected InputStream input; 196 197 200 protected int boundaryLength; 201 202 206 protected int keepRegion; 207 208 211 protected byte[] boundary; 212 213 216 protected int bufSize; 217 218 221 protected static final int DEFAULT_BUFSIZE = 4096; 222 223 226 protected byte[] buffer; 227 228 233 protected int head; 234 235 240 protected int tail; 241 242 246 protected static final byte[] HEADER_SEPARATOR = {0x0D, 0x0A, 0x0D, 0x0A}; 247 248 252 protected static final byte[] FIELD_SEPARATOR = {0x0D, 0x0A}; 253 254 258 protected static final byte[] STREAM_TERMINATOR = {0x2D, 0x2D}; 259 260 274 public MultipartStream(InputStream input, byte[] boundary, int bufSize) 275 throws MalformedStreamException, IOException { 276 this.input = input; 277 this.bufSize = bufSize; 278 this.buffer = new byte[bufSize]; 279 280 this.boundary = new byte[boundary.length + 4]; 283 this.boundaryLength = boundary.length + 4; 284 this.keepRegion = boundary.length + 3; 285 this.boundary[0] = 0x0D; 286 this.boundary[1] = 0x0A; 287 this.boundary[2] = 0x2D; 288 this.boundary[3] = 0x2D; 289 System.arraycopy(boundary, 0, this.boundary, 4, boundary.length); 290 head = 0; 291 tail = 0; 292 } 293 294 302 public MultipartStream(InputStream input, byte[] boundary) 303 throws IOException { 304 this(input, boundary, DEFAULT_BUFSIZE); 305 } 306 307 314 public byte readByte() 315 throws IOException { 316 317 if (head == tail) { 319 head = 0; 320 321 tail = input.read(buffer, head, bufSize); 323 324 if (tail == -1) { 325 326 throw new IOException ("No more data is available"); 328 } 329 } 330 331 return buffer[head++]; 332 } 333 334 343 public boolean readBoundary() 344 throws MalformedStreamException { 345 byte[] marker = new byte[2]; 346 boolean nextChunk = false; 347 head += boundaryLength; 348 349 try { 350 marker[0] = readByte(); 351 marker[1] = readByte(); 352 353 if (arrayequals(marker, STREAM_TERMINATOR, 2)) { 354 nextChunk = false; 355 } else if (arrayequals(marker, FIELD_SEPARATOR, 2)) { 356 nextChunk = true; 357 } else { 358 throw new MalformedStreamException("Unexpected characters follow a boundary"); 359 } 360 } catch (IOException e) { 361 throw new MalformedStreamException("Stream ended unexpectedly"); 362 } 363 364 return nextChunk; 365 } 366 367 385 public void setBoundary(byte[] boundary) 386 throws IllegalBoundaryException { 387 if (boundary.length != boundaryLength - 4) { 388 throw new IllegalBoundaryException("The length of a boundary token can not be changed"); 389 } 390 391 System.arraycopy(boundary, 0, this.boundary, 4, boundary.length); 392 } 393 394 409 public String readHeaders() 410 throws MalformedStreamException { 411 int i = 0; 412 byte[] b = new byte[1]; 413 StringBuffer buf = new StringBuffer (); 414 int sizeMax = HEADER_PART_SIZE_MAX; 415 int size = 0; 416 417 while (i < 4) { 418 try { 419 b[0] = readByte(); 420 } catch (IOException e) { 421 throw new MalformedStreamException("Stream ended unexpectedly"); 422 } 423 424 size++; 425 426 if (b[0] == HEADER_SEPARATOR[i]) { 427 i++; 428 } else { 429 i = 0; 430 } 431 if (size <= sizeMax) { 432 buf.append(new String (b)); 433 } 434 } 435 436 return buf.toString(); 437 } 438 439 451 public int readBodyData(OutputStream output) 452 throws MalformedStreamException, IOException { 453 if (output == null) { 454 throw new IllegalArgumentException ("OutputStream may not be null"); 455 } 456 457 boolean done = false; 458 int pad; 459 int pos; 460 int bytesRead; 461 int total = 0; 462 463 while (!done) { 464 465 pos = findSeparator(); 467 468 if (pos != -1) { 469 470 output.write(buffer, head, pos - head); 472 total += pos - head; 473 head = pos; 474 done = true; 475 } else { 476 477 if (tail - head > keepRegion) { 480 pad = keepRegion; 481 } else { 482 pad = tail - head; 483 } 484 485 output.write(buffer, head, tail - head - pad); 487 488 total += tail - head - pad; 490 System.arraycopy(buffer, tail - pad, buffer, 0, pad); 491 492 head = 0; 494 bytesRead = input.read(buffer, pad, bufSize - pad); 495 496 if (bytesRead != -1) { 498 tail = pad + bytesRead; 499 } else { 500 501 output.write(buffer, 0, pad); 505 total += pad; 506 throw new MalformedStreamException("Stream ended unexpectedly"); 507 } 508 } 509 } 510 511 return total; 512 } 513 514 523 public int discardBodyData() 524 throws MalformedStreamException, IOException { 525 boolean done = false; 526 int pad; 527 int pos; 528 int bytesRead; 529 int total = 0; 530 531 while (!done) { 532 533 pos = findSeparator(); 535 536 if (pos != -1) { 537 538 total += pos - head; 540 head = pos; 541 done = true; 542 } else { 543 544 if (tail - head > keepRegion) { 547 pad = keepRegion; 548 } else { 549 pad = tail - head; 550 } 551 552 total += tail - head - pad; 553 554 System.arraycopy(buffer, tail - pad, buffer, 0, pad); 556 557 head = 0; 559 bytesRead = input.read(buffer, pad, bufSize - pad); 560 561 if (bytesRead != -1) { 563 tail = pad + bytesRead; 564 } else { 565 566 total += pad; 570 throw new MalformedStreamException("Stream ended unexpectedly"); 571 } 572 } 573 } 574 575 return total; 576 } 577 578 584 public boolean skipPreamble() 585 throws IOException { 586 587 System.arraycopy(boundary, 2, boundary, 0, boundary.length - 2); 589 boundaryLength = boundary.length - 2; 590 591 try { 592 593 discardBodyData(); 595 596 return readBoundary(); 599 } catch (MalformedStreamException e) { 600 return false; 601 } finally { 602 603 System.arraycopy(boundary, 0, boundary, 2, boundary.length - 2); 605 boundaryLength = boundary.length; 606 boundary[0] = 0x0D; 607 boundary[1] = 0x0A; 608 } 609 } 610 611 621 public static boolean arrayequals(byte[] a, byte[] b, int count) { 622 for (int i = 0; i < count; i++) { 623 if (a[i] != b[i]) { 624 return false; 625 } 626 } 627 628 return true; 629 } 630 631 640 protected int findByte(byte value, int pos) { 641 for (int i = pos; i < tail; i++) { 642 if (buffer[i] == value) { 643 return i; 644 } 645 } 646 647 return -1; 648 } 649 650 658 protected int findSeparator() { 659 int first; 660 int match = 0; 661 int maxpos = tail - boundaryLength; 662 663 for (first = head; 664 (first <= maxpos) && (match != boundaryLength); 665 first++) { 666 first = findByte(boundary[0], first); 667 668 if (first == -1 || (first > maxpos)) { 669 return -1; 670 } 671 for (match = 1; match < boundaryLength; match++) { 672 if (buffer[first + match] != boundary[match]) { 673 break; 674 } 675 } 676 } 677 if (match == boundaryLength) { 678 return first - 1; 679 } 680 681 return -1; 682 } 683 684 688 public class MalformedStreamException 689 extends IOException { 690 694 public MalformedStreamException() { 695 super(); 696 } 697 698 704 public MalformedStreamException(String message) { 705 super(message); 706 } 707 } 708 709 712 public class IllegalBoundaryException 713 extends IOException { 714 718 public IllegalBoundaryException() { 719 super(); 720 } 721 722 728 public IllegalBoundaryException(String message) { 729 super(message); 730 } 731 } 732 733 734 847 } | Popular Tags |