/** * Parse a single part * * @param ts * @throws java.io.IOException * @throws org.apache.cocoon.servlet.multipart.MultipartException */ private void parsePart(DSpaceTokenStream ts) throws IOException, MultipartException { Hashtable headers = new Hashtable(); headers = readHeaders(ts); try { if (headers.containsKey("filename")) { if (!"".equals(headers.get("filename"))) { parseFilePart(ts, headers); } else { // IE6 sends an empty part with filename="" for // empty upload fields. Just parse away the part byte[] buf = new byte[32]; while (ts.getState() == DSpaceTokenStream.STATE_READING) ts.read(buf); } } else if (((String) headers.get("content-disposition")).toLowerCase().equals("form-data")) { parseInlinePart(ts, headers); } // FIXME: multipart/mixed parts are untested. else if (((String) headers.get("content-disposition")).toLowerCase().indexOf("multipart") > -1) { parseMultiPart( new DSpaceTokenStream(ts, MAX_BOUNDARY_SIZE), "--" + (String) headers.get("boundary")); ts.read(); // read past boundary } else { throw new MultipartException("Unknown part type"); } } catch (IOException e) { throw new MultipartException("Malformed stream: " + e.getMessage()); } catch (NullPointerException e) { e.printStackTrace(); throw new MultipartException("Malformed header"); } }
/** * Read string until newline or end of stream * * @param in * @throws java.io.IOException */ private String readln(DSpaceTokenStream in) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); int b = in.read(); while ((b != -1) && (b != '\r')) { bos.write(b); b = in.read(); } if (b == '\r') { in.read(); // read '\n' } return new String(bos.toByteArray(), this.characterEncoding); }
/** * Parse a multipart block * * @param ts * @param boundary * @throws java.io.IOException * @throws org.apache.cocoon.servlet.multipart.MultipartException */ private void parseMultiPart(DSpaceTokenStream ts, String boundary) throws IOException, MultipartException { ts.setBoundary(boundary.getBytes()); ts.read(); // read first boundary away ts.setBoundary(("\r\n" + boundary).getBytes()); while (ts.getState() == DSpaceTokenStream.STATE_NEXTPART) { ts.nextPart(); parsePart(ts); } if (ts.getState() != DSpaceTokenStream.STATE_ENDMULTIPART) { // sanity check throw new MultipartException("Malformed stream"); } }
/** * Parse an inline part * * @param in * @param headers * @throws java.io.IOException */ private void parseInlinePart(DSpaceTokenStream in, Hashtable headers) throws IOException { // Buffer incoming bytes for proper string decoding (there can be multibyte chars) ByteArrayOutputStream bos = new ByteArrayOutputStream(); while (in.getState() == DSpaceTokenStream.STATE_READING) { int c = in.read(); if (c != -1) bos.write(c); } String field = (String) headers.get("name"); Vector v = (Vector) this.parts.get(field); if (v == null) { v = new Vector(); this.parts.put(field, v); } v.add(new String(bos.toByteArray(), this.characterEncoding)); }
/** * Parse a file part * * @param in * @param headers * @throws java.io.IOException * @throws org.apache.cocoon.servlet.multipart.MultipartException */ private void parseFilePart(DSpaceTokenStream in, Hashtable headers) throws IOException, MultipartException { byte[] buf = new byte[FILE_BUFFER_SIZE]; OutputStream out; File file = null; if (oversized) { out = new NullOutputStream(); } else if (!saveUploadedFilesToDisk) { out = new ByteArrayOutputStream(); } else { String fileName = (String) headers.get("filename"); if (File.separatorChar == '\\') fileName = fileName.replace('/', '\\'); else fileName = fileName.replace('\\', '/'); String filePath = uploadDirectory.getPath() + File.separator; fileName = new File(fileName).getName(); file = new File(filePath + fileName); if (!allowOverwrite && !file.createNewFile()) { if (silentlyRename) { int c = 0; do { file = new File(filePath + c++ + "_" + fileName); } while (!file.createNewFile()); } else { throw new MultipartException( "Duplicate file '" + file.getName() + "' in '" + file.getParent() + "'"); } } out = new FileOutputStream(file); } if (hasSession) { // upload widget support this.uploadStatus.put("finished", Boolean.FALSE); this.uploadStatus.put("started", Boolean.TRUE); this.uploadStatus.put("widget", headers.get("name")); this.uploadStatus.put("filename", headers.get("filename")); } int length = 0; // Track length for OversizedPart try { int read = 0; while (in.getState() == DSpaceTokenStream.STATE_READING) { // read data read = in.read(buf); length += read; out.write(buf, 0, read); if (this.hasSession) { this.uploadStatus.put( "sent", new Integer(((Integer) this.uploadStatus.get("sent")).intValue() + read)); } } if (this.hasSession) { // upload widget support this.uploadStatus.put( "uploadsdone", new Integer(((Integer) this.uploadStatus.get("uploadsdone")).intValue() + 1)); this.uploadStatus.put("error", Boolean.FALSE); } } catch (IOException ioe) { // don't let incomplete file uploads pile up in the upload dir. // this usually happens with aborted form submits containing very large files. out.close(); out = null; if (file != null) file.delete(); if (this.hasSession) { // upload widget support this.uploadStatus.put("error", Boolean.TRUE); } throw ioe; } finally { if (out != null) out.close(); } String name = (String) headers.get("name"); if (oversized) { this.parts.put( name, new RejectedPart(headers, length, this.contentLength, this.maxUploadSize)); } else if (file == null) { byte[] bytes = ((ByteArrayOutputStream) out).toByteArray(); this.parts.put(name, new PartInMemory(headers, bytes)); } else { this.parts.put(name, new PartOnDisk(headers, file)); } }