/// <summary> /// Detects the boundary from the input stream. Assumes that the /// current position of the reader is the start of the file and therefore /// the beginning of the boundary. /// </summary> /// <param name="reader"> /// The binary reader to parse /// </param> /// <returns> /// The boundary string /// </returns> private static string DetectBoundary(RebufferableBinaryReader reader) { string boundary = string.Concat(reader.ReadLine().Skip(2)); reader.Buffer("--" + boundary + "\n"); return(boundary); }
/// <summary> /// Parses a section of the stream that is known to be file data. /// </summary> /// <param name="parameters"> /// The header parameters of this file, expects "name" and "filename" to be valid keys /// </param> /// <param name="reader"> /// The StreamReader to read the data from /// </param> /// <returns> /// The <see cref="FilePart" /> con[] taining the parsed data (name, filename, stream containing file). /// </returns> private void ParseFilePart(Dictionary <string, string> parameters, RebufferableBinaryReader reader) { string name = parameters["name"]; string filename = parameters["filename"]; string contentType = parameters.ContainsKey("content-type") ? parameters["content-type"] : "text/plain"; string contentDisposition = parameters.ContainsKey("content-disposition") ? parameters["content-disposition"] : "form-data"; var curBuffer = new byte[BinaryBufferSize]; var prevBuffer = new byte[BinaryBufferSize]; var fullBuffer = new byte[BinaryBufferSize * 2]; int curLength = 0; int prevLength = 0; int fullLength = 0; prevLength = reader.Read(prevBuffer, 0, prevBuffer.Length); do { curLength = reader.Read(curBuffer, 0, curBuffer.Length); Buffer.BlockCopy(prevBuffer, 0, fullBuffer, 0, prevLength); Buffer.BlockCopy(curBuffer, 0, fullBuffer, prevLength, curLength); fullLength = prevLength + curLength; int endBoundaryPos = SubsequenceFinder.Search(fullBuffer, endBoundaryBinary, fullLength); int endBoundaryLength = endBoundaryBinary.Length; int boundaryPos = SubsequenceFinder.Search(fullBuffer, boundaryBinary, fullLength); int boundaryLength = boundaryBinary.Length; if (boundaryPos + boundaryLength == fullLength) { boundaryPos = -1; } int endPos = -1; int endPosLength = 0; if (endBoundaryPos >= 0 && boundaryPos >= 0) { if (boundaryPos < endBoundaryPos) { endPos = boundaryPos; endPosLength = boundaryLength; } else { endPos = endBoundaryPos; endPosLength = endBoundaryLength; readEndBoundary = true; } } else if (boundaryPos >= 0 && endBoundaryPos < 0) { endPos = boundaryPos; endPosLength = boundaryLength; } else if (boundaryPos < 0 && endBoundaryPos >= 0) { endPos = endBoundaryPos; endPosLength = endBoundaryLength; readEndBoundary = true; } if (endPos != -1) { int boundaryNewlineOffset = CalculateNewlineLength(ref fullBuffer, Math.Min(fullLength - 1, endPos + endPosLength)); int maxNewlineBytes = Encoding.GetMaxByteCount(2); int bufferNewlineOffset = FindNextNewline(ref fullBuffer, Math.Max(0, endPos - maxNewlineBytes), maxNewlineBytes); int bufferNewlineLength = CalculateNewlineLength(ref fullBuffer, bufferNewlineOffset); FileHandler(name, filename, contentType, contentDisposition, fullBuffer, endPos - bufferNewlineLength); int writeBackOffset = endPos + endPosLength + boundaryNewlineOffset; int writeBackAmount = (prevLength + curLength) - writeBackOffset; var writeBackBuffer = new byte[writeBackAmount]; Buffer.BlockCopy(fullBuffer, writeBackOffset, writeBackBuffer, 0, writeBackAmount); reader.Buffer(writeBackBuffer); break; } FileHandler(name, filename, contentType, contentDisposition, prevBuffer, prevLength); byte[] tempBuffer = curBuffer; curBuffer = prevBuffer; prevBuffer = tempBuffer; prevLength = curLength; }while (prevLength != 0); }