package peergos.server.net; import java.io.*; import java.util.*; public class MultipartReceiver { private static final byte[] DOUBLE_NEW_LINE = "\r\n\r\n".getBytes(); public static List<byte[]> extractFiles(InputStream rawIn, String boundary) { try { int maxLineSize = 1024; InputStream in = new BufferedInputStream(rawIn); String first = readLine(in, maxLineSize); if (!first.substring(2).equals(boundary)) throw new IllegalStateException("Incorrect boundary! " + boundary + " != " + first.substring(2)); byte[] firstHeaders = readUntil(DOUBLE_NEW_LINE, in); byte[] boundaryBytes = ("\r\n--" + boundary).getBytes(); List<byte[]> files = new ArrayList<>(); while (true) { byte[] file = readUntil(boundaryBytes, in); files.add(file); byte[] headers = readUntil(DOUBLE_NEW_LINE, in); if (headers.length == 0 || Arrays.equals(headers, "--".getBytes())) return files; } } catch (IOException e) { throw new RuntimeException(e); } } /** * * @param pattern the pattern of bytes to search until * @param in * @return the bytes in this stream until pattern is encountered, or the end of the stream is reached * @throws IOException */ private static byte[] readUntil(byte[] pattern, InputStream in) throws IOException { ByteArrayOutputStream prior = new ByteArrayOutputStream(); int r; int indexInPattern = 0; while ((r = in.read()) != -1) { if ((byte) r == pattern[indexInPattern]) { indexInPattern++; if (indexInPattern == pattern.length) return prior.toByteArray(); } else { if (indexInPattern > 0) prior.write(pattern, 0, indexInPattern); indexInPattern = 0; // be careful of case where last byte before pattern == first byte of pattern if ((byte) r == pattern[0]) { indexInPattern = 1; if (pattern.length == 1) return prior.toByteArray(); } else prior.write(r); } } return prior.toByteArray(); } private static String readLine(InputStream in, int maxSize) throws IOException { ByteArrayOutputStream bout = new ByteArrayOutputStream(); int r, total = 0; while ((r = in.read()) >= 0) { total++; if (r == '\r') { int next = in.read(); if (next == '\n') break; bout.write(r); bout.write(next); } else bout.write(r); if (total > maxSize) break; } return new String(bout.toByteArray()); } }