001    package railo.runtime.net.http;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.ByteArrayOutputStream;
005    import java.io.IOException;
006    import java.io.UnsupportedEncodingException;
007    import java.util.Arrays;
008    
009    import org.apache.commons.fileupload.MultipartStream;
010    import org.apache.commons.lang.StringUtils;
011    
012    import railo.commons.io.IOUtil;
013    import railo.commons.lang.StringUtil;
014    import railo.runtime.exp.PageException;
015    import railo.runtime.type.Array;
016    import railo.runtime.type.ArrayImpl;
017    import railo.runtime.type.Struct;
018    import railo.runtime.type.StructImpl;
019    import railo.runtime.type.util.KeyConstants;
020    import railo.runtime.type.util.ListUtil;
021    
022    
023    public class MultiPartResponseUtils {
024    
025            public static boolean isMultipart(String mimetype) {
026                    return !StringUtil.isEmpty(extractBoundary(mimetype,null)) 
027                            && StringUtil.startsWithIgnoreCase(mimetype, "multipart/");
028            }
029    
030            public static Array getParts(byte[] barr,String contentTypeHeader) throws IOException, PageException {
031                    String boundary = extractBoundary(contentTypeHeader,"");
032                    ByteArrayInputStream bis = new ByteArrayInputStream(barr);
033                    MultipartStream stream;
034                    Array result = new ArrayImpl();
035                    stream = new MultipartStream(bis,getBytes(boundary,"UTF-8"));// 
036                    
037                    boolean hasNextPart = stream.skipPreamble();
038                    while (hasNextPart) {
039                            result.append(getPartData(stream));
040                            hasNextPart = stream.readBoundary();
041                    }
042                    return result;
043            }
044    
045            private static String extractBoundary(String contentTypeHeader, String defaultValue) {
046                    if (contentTypeHeader == null) return defaultValue;
047                    String[] headerSections = ListUtil.listToStringArray(contentTypeHeader, ';');
048                    for (String section: headerSections) {
049                            String[] subHeaderSections = ListUtil.listToStringArray(section,'=');
050                            String headerName = subHeaderSections[0].trim();
051                            if (headerName.toLowerCase().equals("boundary")) {
052                                    return subHeaderSections[1];
053                            }
054                    
055                    }
056                    return defaultValue;
057            }
058    
059            private static Struct getPartData(MultipartStream stream) throws IOException, PageException {
060                    Struct headers = extractHeaders(stream.readHeaders());
061                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
062                    stream.readBodyData(baos);
063                    Struct fileStruct = new StructImpl();
064                    fileStruct.set(KeyConstants._content, baos.toByteArray());
065                    fileStruct.set(KeyConstants._headers, headers);
066                    IOUtil.closeEL(baos);
067                    return fileStruct;
068            }
069    
070            private static Struct extractHeaders(String rawHeaders) throws PageException {
071                    Struct result = new StructImpl();
072                    String[] headers = ListUtil.listToStringArray(rawHeaders,'\n');
073                    for(String rawHeader :headers) {
074                            String[] headerArray = ListUtil.listToStringArray(rawHeader,':');
075                            String headerName = headerArray[0];
076                            if (!StringUtil.isEmpty(headerName,true)) {
077                                    String value = StringUtils.join(Arrays.copyOfRange(headerArray, 1, headerArray.length),":").trim();
078                                    result.set(headerName, value);
079                            }
080                    }
081                    return result;
082            }
083    
084            private static byte[] getBytes(String string, String charset) {
085                    byte[] bytes;
086                    try {
087                            bytes = string.getBytes(charset);
088                    } catch (UnsupportedEncodingException e) {
089                            bytes = string.getBytes();
090                    }
091                    return bytes;
092            }
093    
094    
095    }