001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.server.connection;
030:
031: import com.caucho.log.Log;
032: import com.caucho.server.util.CauchoSystem;
033: import com.caucho.util.CharBuffer;
034: import com.caucho.util.HashMapImpl;
035: import com.caucho.util.L10N;
036: import com.caucho.vfs.MultipartStream;
037: import com.caucho.vfs.Path;
038: import com.caucho.vfs.ReadStream;
039: import com.caucho.vfs.TempBuffer;
040: import com.caucho.vfs.WriteStream;
041:
042: import java.io.IOException;
043: import java.util.logging.Level;
044: import java.util.logging.Logger;
045:
046: /**
047: * Multipart form handling.
048: */
049: class MultipartForm {
050: static final Logger log = Log.open(MultipartForm.class);
051: static final L10N L = new L10N(MultipartForm.class);
052:
053: static void parsePostData(HashMapImpl<String, String[]> table,
054: ReadStream rawIs, String boundary,
055: AbstractHttpRequest request, String javaEncoding,
056: long uploadMax) throws IOException {
057: MultipartStream ms = new MultipartStream(rawIs, boundary);
058: ms.setEncoding(javaEncoding);
059: ReadStream is;
060:
061: while ((is = ms.openRead()) != null) {
062: String attr = (String) ms
063: .getAttribute("content-disposition");
064:
065: if (attr == null || !attr.startsWith("form-data")) {
066: // XXX: is this an error?
067: continue;
068: }
069:
070: String name = getAttribute(attr, "name");
071: String filename = getAttribute(attr, "filename");
072:
073: if (name == null) {
074: // XXX: is this an error?
075: continue;
076: } else if (filename != null) {
077: String contentType = (String) ms
078: .getAttribute("content-type");
079:
080: Path tempDir = CauchoSystem.getWorkPath()
081: .lookup("form");
082: try {
083: tempDir.mkdirs();
084: } catch (IOException e) {
085: }
086: Path tempFile = tempDir.createTempFile("form", ".tmp");
087: request.addCloseOnExit(tempFile);
088:
089: WriteStream os = tempFile.openWrite();
090:
091: TempBuffer tempBuffer = TempBuffer.allocate();
092: byte[] buf = tempBuffer.getBuffer();
093:
094: int totalLength = 0;
095:
096: try {
097: int len;
098:
099: while ((len = is.read(buf, 0, buf.length)) > 0) {
100: os.write(buf, 0, len);
101: totalLength += len;
102: }
103: } finally {
104: os.close();
105:
106: TempBuffer.free(tempBuffer);
107: tempBuffer = null;
108: }
109:
110: if (uploadMax > 0 && uploadMax < tempFile.getLength()) {
111: String msg = L.l(
112: "multipart form data `{0}' too large", ""
113: + tempFile.getLength());
114: request.setAttribute("caucho.multipart.form.error",
115: msg);
116: request.setAttribute(
117: "caucho.multipart.form.error.size",
118: new Long(tempFile.getLength()));
119:
120: tempFile.remove();
121:
122: throw new IOException(msg);
123: } else if (tempFile.getLength() != totalLength) {
124: String msg = L
125: .l("multipart form upload failed (possibly due to full disk).");
126:
127: request.setAttribute("caucho.multipart.form.error",
128: msg);
129: request.setAttribute(
130: "caucho.multipart.form.error.size",
131: new Long(tempFile.getLength()));
132:
133: tempFile.remove();
134:
135: throw new IOException(msg);
136: }
137:
138: // server/136u
139: /*
140: addTable(table, name, tempFile.getNativePath());
141: addTable(table, name + ".file", tempFile.getNativePath());
142: addTable(table, name + ".filename", filename);
143: addTable(table, name + ".content-type", contentType);
144: */
145:
146: table.put(name,
147: new String[] { tempFile.getNativePath() });
148: table.put(name + ".file", new String[] { tempFile
149: .getNativePath() });
150: table
151: .put(name + ".filename",
152: new String[] { filename });
153: table.put(name + ".content-type",
154: new String[] { contentType });
155:
156: if (log.isLoggable(Level.FINE))
157: log.fine("mp-file: " + name + "(filename:"
158: + filename + ")");
159: } else {
160: CharBuffer value = new CharBuffer();
161: int ch;
162:
163: for (ch = is.readChar(); ch >= 0; ch = is.readChar())
164: value.append((char) ch);
165:
166: if (log.isLoggable(Level.FINE))
167: log.fine("mp-form: " + name + "=" + value);
168:
169: addTable(table, name, value.toString());
170: }
171: }
172:
173: if (!ms.isComplete()) {
174: throw new IOException("Incomplete form");
175: }
176: }
177:
178: private static void addTable(HashMapImpl<String, String[]> table,
179: String name, String value) {
180: String[] oldArray = table.get(name);
181:
182: if (oldArray != null) {
183: String[] newArray = new String[oldArray.length + 1];
184: System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
185: newArray[oldArray.length] = value;
186: table.put(name, newArray);
187: } else
188: table.put(name, new String[] { value });
189: }
190:
191: private static String getAttribute(String attr, String name) {
192: if (attr == null)
193: return null;
194:
195: int length = attr.length();
196: int i = attr.indexOf(name);
197: if (i < 0)
198: return null;
199:
200: for (i += name.length(); i < length && attr.charAt(i) != '='; i++) {
201: }
202:
203: for (i++; i < length && attr.charAt(i) == ' '; i++) {
204: }
205:
206: CharBuffer value = CharBuffer.allocate();
207: if (i < length && attr.charAt(i) == '\'') {
208: for (i++; i < length && attr.charAt(i) != '\''; i++)
209: value.append(attr.charAt(i));
210: } else if (i < length && attr.charAt(i) == '"') {
211: for (i++; i < length && attr.charAt(i) != '"'; i++)
212: value.append(attr.charAt(i));
213: } else if (i < length) {
214: char ch;
215: for (; i < length && (ch = attr.charAt(i)) != ' '
216: && ch != ';'; i++)
217: value.append(ch);
218: }
219:
220: return value.close();
221: }
222: }
|