private void trimBuffer() { int bufLen = buffer.length(); int boundaryLen = getBoundary().length; if (bufLen > boundaryLen) { // Leave enough bytes in _buffer that we can find an incomplete boundary string delegate.appendToPart(buffer.buffer(), 0, bufLen - boundaryLen); deleteUpThrough(bufLen - boundaryLen); } }
public Range searchFor(byte[] pattern, int start) { KMPMatch searcher = new KMPMatch(); int buffLen = Math.min(buffer.length(), buffer.buffer().length); int matchIndex = searcher.indexOf(buffer.buffer(), buffLen, pattern, start); if (matchIndex != -1) { return new Range(matchIndex, pattern.length); } else { return new Range(matchIndex, 0); } }
private void deleteUpThrough(int location) { // int start = location + 1; // start at the first byte after the location if (location <= 0) return; byte[] b = buffer.buffer(); int len = buffer.length(); int j = 0; int i = location; while (i < len) { b[j++] = b[i++]; } buffer.setLength(j); }
public void appendData(byte[] data, int off, int len) { if (buffer == null) { return; } if (len == 0) { return; } buffer.append(data, off, len); MultipartReaderState nextState; do { nextState = MultipartReaderState.kUninitialized; int bufLen = buffer.length(); switch (state) { case kAtStart: { // The entire message might start with a boundary without a leading CRLF. byte[] boundaryWithoutLeadingCRLF = getBoundaryWithoutLeadingCRLF(); if (bufLen >= boundaryWithoutLeadingCRLF.length) { if (memcmp( buffer.buffer(), boundaryWithoutLeadingCRLF, boundaryWithoutLeadingCRLF.length)) { deleteUpThrough(boundaryWithoutLeadingCRLF.length); nextState = MultipartReaderState.kInHeaders; } else { nextState = MultipartReaderState.kInPrologue; } } break; } case kInPrologue: case kInBody: { // Look for the next part boundary in the data we just added and the ending bytes of // the previous data (in case the boundary string is split across calls) if (bufLen < boundary.length) { break; } int start = Math.max(0, bufLen - data.length - boundary.length); Range r = searchFor(boundary, start); if (r.getLength() > 0) { if (state == MultipartReaderState.kInBody) { delegate.appendToPart(buffer.buffer(), 0, r.getLocation()); delegate.finishedPart(); } deleteUpThrough(r.getLocation() + r.getLength()); nextState = MultipartReaderState.kInHeaders; } else { trimBuffer(); } break; } case kInHeaders: { // First check for the end-of-message string ("--" after separator): if (bufLen >= kEOM.length && memcmp(buffer.buffer(), kEOM, kEOM.length)) { state = MultipartReaderState.kAtEnd; close(); return; } // Otherwise look for two CRLFs that delimit the end of the headers: Range r = searchFor(kCRLFCRLF, 0); if (r.getLength() > 0) { String headersString = new String(buffer.buffer(), 0, r.getLocation(), utf8); parseHeaders(headersString); deleteUpThrough(r.getLocation() + r.getLength()); delegate.startedPart(headers); nextState = MultipartReaderState.kInBody; } break; } default: { throw new IllegalStateException("Unexpected data after end of MIME body"); } } if (nextState != MultipartReaderState.kUninitialized) { state = nextState; } } while (nextState != MultipartReaderState.kUninitialized && buffer.length() > 0); }