1 package org.apache.turbine.util.upload; 2 3 18 19 import java.io.IOException ; 20 import java.io.InputStream ; 21 import java.io.OutputStream ; 22 23 79 public class MultipartStream 80 { 81 85 public static final int HEADER_PART_SIZE_MAX = 10240; 86 87 88 protected InputStream input; 89 90 93 protected int boundaryLength; 94 95 99 protected int keepRegion; 100 101 102 protected byte[] boundary; 103 104 105 protected int bufSize; 106 107 108 protected static final int DEFAULT_BUFSIZE = 4096; 109 110 111 protected byte[] buffer; 112 113 118 protected int head; 119 120 125 protected int tail; 126 127 131 protected static final byte[] HEADER_SEPARATOR = {0x0D, 0x0A, 0x0D, 0x0A}; 132 133 137 protected static final byte[] FIELD_SEPARATOR = {0x0D, 0x0A}; 138 139 143 protected static final byte[] STREAM_TERMINATOR = {0x2D, 0x2D}; 144 145 161 public MultipartStream(InputStream input, 162 byte[] boundary, 163 int bufSize) 164 throws MalformedStreamException, 165 IOException 166 { 167 this.input = input; 168 this.bufSize = bufSize; 169 this.buffer = new byte[bufSize]; 170 171 this.boundary = new byte[boundary.length + 4]; 174 this.boundaryLength = boundary.length + 4; 175 this.keepRegion = boundary.length + 3; 176 this.boundary[0] = 0x0D; 177 this.boundary[1] = 0x0A; 178 this.boundary[2] = 0x2D; 179 this.boundary[3] = 0x2D; 180 System.arraycopy(boundary, 0, this.boundary, 4, boundary.length); 181 182 head = 0; 183 tail = 0; 184 } 185 186 195 public MultipartStream(InputStream input, 196 byte[] boundary) 197 throws IOException 198 { 199 this(input, boundary, DEFAULT_BUFSIZE); 200 } 201 202 209 public byte readByte() 210 throws IOException 211 { 212 if (head == tail) 214 { 215 head = 0; 216 tail = input.read(buffer, head, bufSize); 218 if (tail == -1) 219 { 220 throw new IOException ("No more data is available"); 222 } 223 } 224 return buffer[head++]; 225 } 226 227 236 public boolean readBoundary() 237 throws MalformedStreamException 238 { 239 byte[] marker = new byte[2]; 240 boolean nextChunk = false; 241 242 head += boundaryLength; 243 try 244 { 245 marker[0] = readByte(); 246 marker[1] = readByte(); 247 if (arrayequals(marker, STREAM_TERMINATOR, 2)) 248 { 249 nextChunk = false; 250 } 251 else if (arrayequals(marker, FIELD_SEPARATOR, 2)) 252 { 253 nextChunk = true; 254 } 255 else 256 { 257 throw new MalformedStreamException("Unexpected characters follow a boundary"); 258 } 259 } 260 catch (IOException e) 261 { 262 throw new MalformedStreamException("Stream ended unexpectedly"); 263 } 264 return nextChunk; 265 } 266 267 285 public void setBoundary(byte[] boundary) 286 throws IllegalBoundaryException 287 { 288 if (boundary.length != boundaryLength - 4) 289 { 290 throw new IllegalBoundaryException("The length of a boundary token can not be changed"); 291 } 292 System.arraycopy(boundary, 0, this.boundary, 4, boundary.length); 293 } 294 295 310 public String readHeaders() 311 throws MalformedStreamException 312 { 313 int i = 0; 314 byte b[] = new byte[1]; 315 StringBuffer buf = new StringBuffer (); 316 int sizeMax = HEADER_PART_SIZE_MAX; 317 int size = 0; 318 while (i < 4) 319 { 320 try 321 { 322 b[0] = readByte(); 323 } 324 catch (IOException e) 325 { 326 throw new MalformedStreamException("Stream ended unexpectedly"); 327 } 328 size++; 329 if (b[0] == HEADER_SEPARATOR[i]) 330 { 331 i++; 332 } 333 else 334 { 335 i = 0; 336 } 337 if (size <= sizeMax) 338 { 339 buf.append(new String (b)); 340 } 341 } 342 return buf.toString(); 343 } 344 345 359 public int readBodyData(OutputStream output) 360 throws MalformedStreamException, 361 IOException 362 { 363 boolean done = false; 364 int pad; 365 int pos; 366 int bytesRead; 367 int total = 0; 368 while (!done) 369 { 370 pos = findSeparator(); 372 if (pos != -1) 373 { 374 output.write(buffer, head, pos - head); 376 total += pos - head; 377 head = pos; 378 done = true; 379 } 380 else 381 { 382 if (tail - head > keepRegion) 385 { 386 pad = keepRegion; 387 } 388 else 389 { 390 pad = tail - head; 391 } 392 output.write(buffer, head, tail - head - pad); 394 395 total += tail - head - pad; 397 System.arraycopy(buffer, tail - pad, buffer, 0, pad); 398 399 head = 0; 401 bytesRead = input.read(buffer, pad, bufSize - pad); 402 403 if (bytesRead != -1) 405 { 406 tail = pad + bytesRead; 407 } 408 else 409 { 410 output.write(buffer, 0, pad); 414 output.flush(); 415 total += pad; 416 throw new MalformedStreamException("Stream ended unexpectedly"); 417 } 418 } 419 } 420 output.flush(); 421 return total; 422 } 423 424 435 public int discardBodyData() 436 throws MalformedStreamException, 437 IOException 438 { 439 boolean done = false; 440 int pad; 441 int pos; 442 int bytesRead; 443 int total = 0; 444 while (!done) 445 { 446 pos = findSeparator(); 448 if (pos != -1) 449 { 450 total += pos - head; 452 head = pos; 453 done = true; 454 } 455 else 456 { 457 if (tail - head > keepRegion) 460 { 461 pad = keepRegion; 462 } 463 else 464 { 465 pad = tail - head; 466 } 467 total += tail - head - pad; 468 469 System.arraycopy(buffer, tail - pad, buffer, 0, pad); 471 472 head = 0; 474 bytesRead = input.read(buffer, pad, bufSize - pad); 475 476 if (bytesRead != -1) 478 { 479 tail = pad + bytesRead; 480 } 481 else 482 { 483 total += pad; 487 throw new MalformedStreamException("Stream ended unexpectedly"); 488 } 489 } 490 } 491 return total; 492 } 493 494 501 public boolean skipPreamble() 502 throws IOException 503 { 504 System.arraycopy(boundary, 2, boundary, 0, boundary.length - 2); 506 boundaryLength = boundary.length - 2; 507 try 508 { 509 discardBodyData(); 511 512 return readBoundary(); 515 } 516 catch (MalformedStreamException e) 517 { 518 return false; 519 } 520 finally 521 { 522 System.arraycopy(boundary, 0, boundary, 2, boundary.length - 2); 524 boundaryLength = boundary.length; 525 boundary[0] = 0x0D; 526 boundary[1] = 0x0A; 527 } 528 } 529 530 540 public static boolean arrayequals(byte[] a, 541 byte[] b, 542 int count) 543 { 544 for (int i = 0; i < count; i++) 545 { 546 if (a[i] != b[i]) 547 { 548 return false; 549 } 550 } 551 return true; 552 } 553 554 563 protected int findByte(byte value, 564 int pos) 565 { 566 for (int i = pos; i < tail; i++) 567 if (buffer[i] == value) 568 return i; 569 570 return -1; 571 } 572 573 581 protected int findSeparator() 582 { 583 int first; 584 int match = 0; 585 int maxpos = tail - boundaryLength; 586 for (first = head; 587 (first <= maxpos) && (match != boundaryLength); 588 first++) 589 { 590 first = findByte(boundary[0], first); 591 if (first == -1 || (first > maxpos)) 592 return -1; 593 for (match = 1; match < boundaryLength; match++) 594 { 595 if (buffer[first + match] != boundary[match]) 596 break; 597 } 598 } 599 if (match == boundaryLength) 600 { 601 return first - 1; 602 } 603 return -1; 604 } 605 606 610 public class MalformedStreamException 611 extends IOException 612 { 613 617 public MalformedStreamException() 618 { 619 super(); 620 } 621 622 628 public MalformedStreamException(String message) 629 { 630 super(message); 631 } 632 } 633 634 637 public class IllegalBoundaryException 638 extends IOException 639 { 640 644 public IllegalBoundaryException() 645 { 646 super(); 647 } 648 649 655 public IllegalBoundaryException(String message) 656 { 657 super(message); 658 } 659 } 660 661 724 } 725 | Popular Tags |