package javaforce.service;
/**
*
* @author pquiring
*
* Created : Sept 16, 2013
*/
import java.io.*;
import java.util.*;
import javaforce.JF;
/** A class to handle file uploads (max 64MBs) */
public class WebUpload {
public static boolean isMultipartContent(WebRequest req) {
//Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...\r\n
String contentType = req.getHeader("Content-Type");
if (contentType == null) return false;
return (contentType.trim().startsWith("multipart/form-data;"));
}
public static class WebFile {
/** File data */
public byte data[];
/** Name of file (excluding any path info) */
public String name;
/** Copies temp uploaded file to dest */
public void write(File dest) throws Exception {
FileOutputStream fos = new FileOutputStream(dest);
fos.write(data);
fos.close();
}
public String getName() {return name;}
}
private WebFile[] list;
private static int maxlength = 64 * 1024 * 1024; //64MBs
private boolean cmp(byte s1[], int p1, byte s2[], int p2, int len) {
while (len > 0) {
if (s1[p1++] != s2[p2++]) return false;
len--;
}
return true;
}
public WebFile[] parseRequest(WebRequest req) throws Exception {
//TODO : read post data and save to files in temp folder
//Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...
String contentType = req.getHeader("Content-Type");
if (contentType == null) throw new Exception("WebUpload:No Content-Type");
int idx = contentType.indexOf("boundary=");
if (idx == -1) throw new Exception("WebUpload:No boundary");
byte boundary[] = ("--" + contentType.substring(idx+9)).getBytes();
int boundaryLength = boundary.length;
String contentLength = req.getHeader("Content-Length");
if (contentLength == null) throw new Exception("WebUpload:No Content-Length");
int postlength = Integer.valueOf(contentLength);
if (postlength > maxlength) throw new Exception("WebUpload:Upload > Max allowed");
byte data[] = JF.readAll(req.is, postlength);
//now process files in post data
//[\r\n]boundary\r\nContent-Disposition: form-data; name="???"; filename="???"\r\nContent-Type: mime/type\r\n\r\n
int pos = 0;
ArrayList<WebFile> files = new ArrayList<WebFile>();
while (pos < postlength) {
if (data[pos] == '\r' && data[pos+1] == '\n') {
pos += 2;
continue;
}
if (!cmp(data, pos, boundary, 0, boundaryLength)) throw new Exception("WebUpload:Bad boundary @ " + pos);
pos += boundaryLength;
//read header
StringBuilder headers = new StringBuilder();
while (!headers.toString().endsWith("\r\n\r\n")) {
headers.append((char)data[pos++]);
}
String lns[] = headers.toString().split("\r\n");
//extract Content-Disposition "filename"
String filename = null;
for(int a=0;a<lns.length;a++) {
if (lns[a].startsWith("Content-Disposition:")) {
String fields[] = lns[a].split(";");
for(int b=0;b<fields.length;b++) {
if (fields[b].trim().startsWith("filename=")) {
filename = fields[b].trim().substring(9);
break;
}
}
break;
}
}
if (filename == null) throw new Exception("WebUpload:Upload has no filename");
if (filename.startsWith("\"") && filename.endsWith("\"")) {
filename = filename.substring(1, filename.length() - 1); //remove quotes
}
WebFile file = new WebFile();
file.name = filename;
//find next boundary
int fileStart = pos;
int fileEnd = -1;
while (pos < postlength) {
if (data[pos] == '\r' && data[pos+1] == '\n' && cmp(data, pos+2, boundary, 0, boundaryLength)) {
fileEnd = pos;
break;
}
pos++;
}
if (fileEnd == -1) throw new Exception("WebUpload:No boundary found after file data");
int fileLength = fileEnd - fileStart;
file.data = new byte[fileLength];
System.arraycopy(data, fileStart, file.data, 0, fileLength);
files.add(file);
pos += fileLength;
}
return files.toArray(new WebFile[0]);
}
}