001: /*
002: * UploadHandler.java
003: *
004: * Created on 23 April 2000, 09:01
005: * Checkout http://www.ietf.org/rfc/rfc1867.txt for the file upload protocol
006: */
007: package com.javelin.swinglets;
008:
009: import javax.servlet.http.*;
010: import java.io.*;
011: import javax.servlet.*;
012: import java.util.*;
013:
014: /**
015: *
016: * @author Dino
017: * @version
018: */
019: public class UploadHandler {
020:
021: HttpServletRequest request = null;
022:
023: ServletInputStream in;
024: int totalExpected;
025: int totalRead = 0;
026: byte[] buf = new byte[8192];
027: StringBuffer sbuf = new StringBuffer();
028:
029: private File dir = new File(".");
030:
031: private Hashtable parameters = new Hashtable(); // name - Vector of values
032: private Hashtable files = new Hashtable(); // name - UploadedFile
033:
034: String boundary = null;
035:
036: public UploadHandler(HttpServletRequest request) throws IOException {
037: this .request = request;
038: processForm();
039: }
040:
041: public Enumeration getParameterNames() {
042: return parameters.keys();
043: }
044:
045: public Enumeration getUploadFiles() {
046: return files.elements();
047: }
048:
049: public String getParameter(String name) {
050: try {
051: Vector values = (Vector) parameters.get(name);
052: if (values == null || values.size() == 0) {
053: return null;
054: }
055: String value = (String) values.elementAt(values.size() - 1);
056: return value;
057: } catch (Exception e) {
058: return null;
059: }
060: }
061:
062: public String[] getParameterValues(String name) {
063: try {
064: Vector values = (Vector) parameters.get(name);
065: if (values == null || values.size() == 0) {
066: return null;
067: }
068: String[] valuesArray = new String[values.size()];
069: values.copyInto(valuesArray);
070: return valuesArray;
071: } catch (Exception e) {
072: return null;
073: }
074: }
075:
076: private String getBoundary(String line) throws IOException {
077: int index = line.lastIndexOf("boundary=");
078: if (index == -1) {
079: return null;
080: }
081: String boundary = line.substring(index + 9);
082:
083: boundary = "--" + boundary;
084:
085: return boundary;
086: }
087:
088: protected void processForm() throws IOException {
089: int length = request.getContentLength();
090:
091: String ctype = request.getContentType();
092: // must be a multipart form
093: if (ctype == null
094: || !ctype.toLowerCase().startsWith(
095: "multipart/form-data")) {
096: throw new IOException("Form isn't multipart/form-data");
097: }
098: // get the form boundary, very important
099:
100: System.out.println("Content type=" + ctype);
101: String type1 = request.getHeader("Content-Type");
102: System.out.println("Content type1=" + type1);
103: System.out.flush();
104:
105: boundary = getBoundary(ctype);
106:
107: // store inputstream
108: in = request.getInputStream();
109: totalExpected = length;
110:
111: // get first line
112: String line = readLine();
113: if (line == null) {
114: throw new IOException("Could not read first line");
115: }
116:
117: // should start with the boundary
118: if (!line.startsWith(boundary)) {
119: throw new IOException("Could not find boundary");
120: }
121:
122: // Handle each part of the form, may be a normal field, or may be a file
123: boolean more = true;
124: while (more) {
125: more = handleNextPart();
126: }
127:
128: }
129:
130: protected String readLine() throws IOException {
131: sbuf.setLength(0);
132: int result;
133:
134: do {
135: result = readLine(buf, 0, buf.length);
136: if (result != -1) {
137: sbuf.append(new String(buf, 0, result, "ISO-8859-1"));
138: }
139: } while (result == buf.length); // loop only if the buffer was filled
140:
141: if (sbuf.length() == 0) {
142: return null; // nothing read, must be at the end of stream
143: }
144:
145: sbuf.setLength(sbuf.length() - 2); // cut off the trailing \r\n
146: return sbuf.toString();
147: }
148:
149: protected int readLine(byte b[], int off, int len)
150: throws IOException {
151: if (totalRead >= totalExpected) {
152: return -1;
153: }
154:
155: int bytesLeft = totalExpected - totalRead;
156: if (len > bytesLeft) {
157: len = bytesLeft;
158: }
159: int result = in.readLine(b, off, len);
160: if (result > 0) {
161: totalRead += result;
162: }
163: return result;
164: }
165:
166: protected boolean handleNextPart() throws IOException {
167: String line = readLine();
168: if (line == null || line.length() == 0) {
169: return false;
170: }
171:
172: String[] dispArray = getDisposition(line);
173: String disposition = dispArray[0];
174: String paramname = dispArray[1];
175: String filename = dispArray[2];
176:
177: line = readLine();
178: if (line == null) {
179: return false;
180: }
181:
182: String contentType = getContentType(line);
183: if (contentType != null) {
184: line = readLine();
185: if (line == null || line.length() > 0) {
186: throw new IOException(
187: "Line should be empty after content type: "
188: + line);
189: }
190: } else {
191: contentType = "application/octet-stream";
192: }
193:
194: if (filename == null) {
195: String value = getParameter();
196: if ("".equals(value)) {
197: value = null;
198: }
199: Vector values = (Vector) parameters.get(paramname);
200: // if param never seen before then create vector
201: if (values == null) {
202: values = new Vector();
203: parameters.put(paramname, values);
204: }
205: values.addElement(value);
206: } else {
207: System.out.println(new java.util.Date());
208: ByteArrayOutputStream stream = getStream();
209: System.out.println(new java.util.Date());
210: files.put(paramname, new UploadFile(stream, paramname,
211: filename, contentType));
212:
213: }
214: return true;
215: }
216:
217: protected String getParameter() throws IOException {
218: StringBuffer sbuf = new StringBuffer();
219: String line;
220:
221: while ((line = readLine()) != null) {
222: if (line.startsWith(boundary))
223: break;
224: sbuf.append(line + "\r\n");
225: }
226:
227: if (sbuf.length() == 0) {
228: return null;
229: }
230:
231: sbuf.setLength(sbuf.length() - 2);
232: return sbuf.toString();
233: }
234:
235: /*
236: Returns disposition, name, and filename as an array of string
237: Filename will be null if this part is not for a
238: */
239: private String[] getDisposition(String line) throws IOException {
240: String[] retval = new String[3];
241:
242: String origline = line;
243: line = origline.toLowerCase();
244:
245: int startAt = line.indexOf("content-disposition: ");
246: int endAt = line.indexOf(";");
247: if (startAt == -1 || endAt == -1) {
248: throw new IOException("Invalid content disposition: "
249: + origline);
250: }
251: String disposition = line.substring(startAt + 21, endAt);
252: if (!disposition.equals("form-data")) {
253: throw new IOException("Invalid content disposition: "
254: + disposition);
255: }
256:
257: startAt = line.indexOf("name=\"", endAt);
258: endAt = line.indexOf("\"", startAt + 7);
259: if (startAt == -1 || endAt == -1) {
260: throw new IOException("Content disposition corrupt: "
261: + origline);
262: }
263: String name = origline.substring(startAt + 6, endAt);
264:
265: String filename = null;
266: startAt = line.indexOf("filename=\"", endAt + 2);
267: endAt = line.indexOf("\"", startAt + 10);
268: if (startAt != -1 && endAt != -1) {
269: filename = origline.substring(startAt + 10, endAt);
270:
271: int slashAt = Math.max(filename.lastIndexOf('/'), filename
272: .lastIndexOf('\\'));
273: if (slashAt > -1) {
274: filename = filename.substring(slashAt + 1);
275: }
276:
277: }
278:
279: // Return a String array: disposition, name, filename
280: retval[0] = disposition;
281: retval[1] = name;
282: retval[2] = filename;
283: return retval;
284: }
285:
286: private String getContentType(String line) throws IOException {
287: String contentType = null;
288:
289: String origline = line;
290: line = origline.toLowerCase();
291:
292: if (line.startsWith("content-type")) {
293: int start = line.indexOf(" ");
294: if (start == -1) {
295: throw new IOException("Content type corrupt: "
296: + origline);
297: }
298: contentType = line.substring(start + 1);
299: } else if (line.length() != 0) { // no content type, so should be empty
300: throw new IOException("Malformed line after disposition: "
301: + origline);
302: }
303:
304: return contentType;
305: }
306:
307: protected ByteArrayOutputStream getStream() throws IOException {
308: ByteArrayOutputStream out = new ByteArrayOutputStream(32 * 1024);
309:
310: byte[] bbuf = new byte[32 * 1024];
311: int result;
312: String line;
313:
314: boolean rnflag = false;
315: while ((result = readLine(bbuf, 0, bbuf.length)) != -1) {
316:
317: if (result > 2 && bbuf[0] == '-' && bbuf[1] == '-') {
318: line = new String(bbuf, 0, result, "ISO-8859-1");
319: if (line.startsWith(boundary))
320: break;
321: }
322:
323: if (rnflag) {
324: out.write('\r');
325: out.write('\n');
326: rnflag = false;
327: }
328:
329: if (result >= 2 && bbuf[result - 2] == '\r'
330: && bbuf[result - 1] == '\n') {
331: out.write(bbuf, 0, result - 2);
332: rnflag = true;
333: } else {
334: out.write(bbuf, 0, result);
335: }
336: }
337: out.flush();
338: return out;
339: }
340:
341: }
|