001: /*
002: * @(#)MultipartInputStream.java 1.2 04/12/06
003: *
004: * Copyright (c) 1997-2003 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.servlet;
010:
011: import java.io.*;
012:
013: /**
014: * Handles multipart MIME messages defined in rfc1521.
015: */
016: public class MultipartInputStream extends FilterInputStream {
017:
018: private byte[] boundary;
019: private byte[] buffer;
020: private boolean partEnd;
021: private boolean fileEnd;
022:
023: protected MultipartInputStream(InputStream in) {
024: super (in);
025: }
026:
027: public MultipartInputStream(InputStream in, byte[] boundary) {
028: super (in);
029: if (!in.markSupported()) {
030: this .in = new BufferedInputStream(in, boundary.length + 4);
031: }
032: this .boundary = boundary;
033: this .buffer = new byte[boundary.length];
034: this .partEnd = false;
035: this .fileEnd = false;
036: }
037:
038: private final boolean readBoundaryBytes() throws IOException {
039: int pos = 0;
040: while (pos < buffer.length) {
041: int got = in.read(buffer, pos, buffer.length - pos);
042: if (got < 0) {
043: return false;
044: }
045: pos += got;
046: }
047: return true;
048: }
049:
050: protected boolean skipToBoundary() throws IOException {
051: int ch = in.read();
052: skip: while (ch != -1) {
053: if (ch != '-') {
054: ch = in.read();
055: continue;
056: }
057: if ((ch = in.read()) != '-') {
058: continue;
059: }
060: in.mark(boundary.length);
061: if (!readBoundaryBytes()) {
062: in.reset();
063: ch = in.read();
064: continue skip;
065: }
066: for (int i = 0; i < boundary.length; i++) {
067: if (buffer[i] != boundary[i]) {
068: in.reset();
069: ch = in.read();
070: continue skip;
071: }
072: }
073: if ((ch = in.read()) == '\r') {
074: ch = in.read();
075: }
076: in.mark(3);
077: if (in.read() == '-') {
078: if (in.read() == '\r' && in.read() == '\n') {
079: fileEnd = true;
080: return false;
081: }
082: }
083: in.reset();
084: return true;
085: }
086: fileEnd = true;
087: return false;
088: }
089:
090: public int read() throws IOException {
091: int ch;
092: if (partEnd) {
093: return -1;
094: }
095: switch (ch = in.read()) {
096: case '\r':
097: in.mark(boundary.length + 3);
098: int c1 = in.read();
099: int c2 = in.read();
100: int c3 = in.read();
101: if ((c1 == '\n') && (c2 == '-') && (c3 == '-')) {
102: if (!readBoundaryBytes()) {
103: reset();
104: return ch;
105: }
106: for (int i = 0; i < boundary.length; i++) {
107: if (buffer[i] != boundary[i]) {
108: in.reset();
109: return ch;
110: }
111: }
112: partEnd = true;
113: if ((ch = in.read()) == '\r') {
114: in.read();
115: } else if (ch == '-') {
116: if (in.read() == '-') {
117: fileEnd = true;
118: }
119: } else {
120: fileEnd = (ch == -1);
121: }
122: return -1;
123: } else {
124: in.reset();
125: return ch;
126: }
127: case -1:
128: fileEnd = true;
129: return -1;
130: default:
131: return ch;
132: }
133: }
134:
135: public int read(byte b[], int off, int len) throws IOException {
136: int got = 0;
137: int ch;
138:
139: while (got < len) {
140: if ((ch = read()) == -1) {
141: return (got == 0) ? -1 : got;
142: }
143: b[off + (got++)] = (byte) ch;
144: }
145: return got;
146: }
147:
148: public long skip(long n) throws IOException {
149: while ((--n >= 0) && (read() != -1)) {
150: }
151: return n;
152: }
153:
154: public boolean next() throws IOException {
155: if (fileEnd) {
156: return false;
157: }
158: if (!partEnd) {
159: return skipToBoundary();
160: } else {
161: partEnd = false;
162: return true;
163: }
164: }
165: }
|