/**
*
* Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
**/
package lucee.runtime.net.http;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import lucee.commons.io.IOUtil;
import lucee.commons.lang.StringUtil;
import lucee.runtime.exp.PageException;
import lucee.runtime.type.Array;
import lucee.runtime.type.ArrayImpl;
import lucee.runtime.type.Struct;
import lucee.runtime.type.StructImpl;
import lucee.runtime.type.util.KeyConstants;
import lucee.runtime.type.util.ListUtil;
import org.apache.commons.fileupload.MultipartStream;
import org.apache.commons.lang.StringUtils;
public class MultiPartResponseUtils {
public static boolean isMultipart(String mimetype) {
return !StringUtil.isEmpty(extractBoundary(mimetype,null))
&& StringUtil.startsWithIgnoreCase(mimetype, "multipart/");
}
public static Array getParts(byte[] barr,String contentTypeHeader) throws IOException, PageException {
String boundary = extractBoundary(contentTypeHeader,"");
ByteArrayInputStream bis = new ByteArrayInputStream(barr);
MultipartStream stream;
Array result = new ArrayImpl();
stream = new MultipartStream(bis,getBytes(boundary,"UTF-8"));//
boolean hasNextPart = stream.skipPreamble();
while (hasNextPart) {
result.append(getPartData(stream));
hasNextPart = stream.readBoundary();
}
return result;
}
private static String extractBoundary(String contentTypeHeader, String defaultValue) {
if (contentTypeHeader == null) return defaultValue;
String[] headerSections = ListUtil.listToStringArray(contentTypeHeader, ';');
for (String section: headerSections) {
String[] subHeaderSections = ListUtil.listToStringArray(section,'=');
String headerName = subHeaderSections[0].trim();
if (headerName.toLowerCase().equals("boundary")) {
return subHeaderSections[1].replaceAll("^\"|\"$", "");
}
}
return defaultValue;
}
private static Struct getPartData(MultipartStream stream) throws IOException, PageException {
Struct headers = extractHeaders(stream.readHeaders());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
stream.readBodyData(baos);
Struct fileStruct = new StructImpl();
fileStruct.set(KeyConstants._content, baos.toByteArray());
fileStruct.set(KeyConstants._headers, headers);
IOUtil.closeEL(baos);
return fileStruct;
}
private static Struct extractHeaders(String rawHeaders) throws PageException {
Struct result = new StructImpl();
String[] headers = ListUtil.listToStringArray(rawHeaders,'\n');
for(String rawHeader :headers) {
String[] headerArray = ListUtil.listToStringArray(rawHeader,':');
String headerName = headerArray[0];
if (!StringUtil.isEmpty(headerName,true)) {
String value = StringUtils.join(Arrays.copyOfRange(headerArray, 1, headerArray.length),":").trim();
result.set(headerName, value);
}
}
return result;
}
private static byte[] getBytes(String string, String charset) {
byte[] bytes;
try {
bytes = string.getBytes(charset);
} catch (UnsupportedEncodingException e) {
bytes = string.getBytes();
}
return bytes;
}
}