public void MimeMultipartParser_ThrowsOnTooBigBoundary() { string maxLegalBoundary = new string('a', 246); MimeMultipartParser parser = new MimeMultipartParser(maxLegalBoundary, ParserData.MinMessageSize); string minIllegalBoundary = new string('a', 247); Assert.ThrowsArgumentLessThanOrEqualTo(() => new MimeMultipartParser(minIllegalBoundary, ParserData.MinMessageSize), "boundary", "246", "247"); }
public State ParseBuffer( byte[] buffer, int bytesReady, ref int bytesConsumed, out ArraySegment <byte> remainingBodyPart, out ArraySegment <byte> bodyPart, out bool isFinalBodyPart) { if (buffer == null) { throw new ArgumentNullException("buffer"); } State parseStatus = State.NeedMoreData; remainingBodyPart = MimeMultipartParser._emptyBodyPart; bodyPart = MimeMultipartParser._emptyBodyPart; isFinalBodyPart = false; if (bytesConsumed >= bytesReady) { // we already can tell we need more data return(parseStatus); } try { parseStatus = MimeMultipartParser.ParseBodyPart( buffer, bytesReady, ref bytesConsumed, ref _bodyPartState, _maxMessageSize, ref _totalBytesConsumed, _currentBoundary); } catch (Exception) { parseStatus = State.Invalid; } remainingBodyPart = _currentBoundary.GetDiscardedBoundary(); bodyPart = _currentBoundary.BodyPart; if (parseStatus == State.BodyPartCompleted) { isFinalBodyPart = _currentBoundary.IsFinal; _currentBoundary.ClearAll(); } else { _currentBoundary.ClearBodyPart(); } return(parseStatus); }
public void MultipartParserNullBuffer() { MimeMultipartParser parser = CreateMimeMultipartParser(128, "-"); int bytesConsumed = 0; ArraySegment <byte> out1; ArraySegment <byte> out2; bool isFinal; Assert.ThrowsArgumentNull(() => { parser.ParseBuffer(null, 0, ref bytesConsumed, out out1, out out2, out isFinal); }, "buffer"); }
public void MultipartParserNearMatches(string boundary) { string[] text = new string[] { "AAA" + LF, "AAA" + CR, "AAA" + CRLF, "AAA" + CRLF + CRLF, "AAA" + CRLF + Dash, "AAA" + CRLF + Dash + CR, "AAA" + CRLF + Dash + CRLF, CR + Dash + "AAA", CRLF + Dash + "AAA", CRLF + DashDash + "AAA" + CR + "AAA", CRLF, "AAA", "AAA" + CRLF, CRLF + CRLF, CRLF + CRLF + CRLF, "AAA" + DashDash + "AAA", CRLF + "AAA" + DashDash + "AAA" + DashDash, CRLF + DashDash + "AAA" + CRLF, CRLF + DashDash + "AAA" + CRLF + CRLF, CRLF + DashDash + "AAA" + DashDash + CRLF, CRLF + DashDash + "AAA" + DashDash + CRLF + CRLF }; byte[] data = CreateBuffer(boundary, text); for (var cnt = 1; cnt <= data.Length; cnt++) { MimeMultipartParser parser = CreateMimeMultipartParser(data.Length, boundary); Assert.NotNull(parser); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps(parser, data, cnt, out bodyParts, out totalBytesConsumed); Assert.Equal(MimeMultipartParser.State.BodyPartCompleted, state); Assert.Equal(data.Length, totalBytesConsumed); Assert.Equal(text.Length + 1, bodyParts.Count); Assert.Equal(0, bodyParts[0].Length); for (var check = 0; check < text.Length; check++) { Assert.Equal(text[check].Length, bodyParts[check + 1].Length); Assert.Equal(text[check], bodyParts[check + 1]); } } }
public void MimeMultipartParserTestDataTooBig(string boundary) { byte[] data = CreateBuffer(boundary); for (var cnt = 1; cnt <= data.Length; cnt++) { MimeMultipartParser parser = CreateMimeMultipartParser(ParserData.MinMessageSize, boundary); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps(parser, data, cnt, out bodyParts, out totalBytesConsumed); Assert.Equal(MimeMultipartParser.State.DataTooBig, state); Assert.Equal(ParserData.MinMessageSize, totalBytesConsumed); } }
private static MimeMultipartParser.State ParseBufferInSteps(MimeMultipartParser parser, byte[] buffer, int readsize, out List <string> bodyParts, out int totalBytesConsumed) { MimeMultipartParser.State state = MimeMultipartParser.State.Invalid; totalBytesConsumed = 0; bodyParts = new List <string>(); bool isFinal = false; byte[] currentBodyPart = new byte[32 * 1024]; int currentBodyLength = 0; while (totalBytesConsumed <= buffer.Length) { int size = Math.Min(buffer.Length - totalBytesConsumed, readsize); byte[] parseBuffer = new byte[size]; Buffer.BlockCopy(buffer, totalBytesConsumed, parseBuffer, 0, size); int bytesConsumed = 0; ArraySegment <byte> out1; ArraySegment <byte> out2; state = parser.ParseBuffer(parseBuffer, parseBuffer.Length, ref bytesConsumed, out out1, out out2, out isFinal); totalBytesConsumed += bytesConsumed; Buffer.BlockCopy(out1.Array, out1.Offset, currentBodyPart, currentBodyLength, out1.Count); currentBodyLength += out1.Count; Buffer.BlockCopy(out2.Array, out2.Offset, currentBodyPart, currentBodyLength, out2.Count); currentBodyLength += out2.Count; if (state == MimeMultipartParser.State.BodyPartCompleted) { var bPart = new byte[currentBodyLength]; Buffer.BlockCopy(currentBodyPart, 0, bPart, 0, currentBodyLength); bodyParts.Add(Encoding.UTF8.GetString(bPart)); currentBodyLength = 0; if (isFinal) { break; } } else if (state != MimeMultipartParser.State.NeedMoreData) { return(state); } } Assert.True(isFinal); return(state); }
public void MimeMultipartParserConstructorTest(string boundary) { MimeMultipartParser parser = new MimeMultipartParser(boundary, ParserData.MinMessageSize); Assert.ThrowsArgumentGreaterThanOrEqualTo(() => new MimeMultipartParser("-", ParserData.MinMessageSize - 1), "maxMessageSize", ParserData.MinMessageSize.ToString(), ParserData.MinMessageSize - 1); foreach (string empty in TestData.EmptyStrings) { Assert.ThrowsArgument(() => { new MimeMultipartParser(empty, ParserData.MinMessageSize); }, "boundary", allowDerivedExceptions: true); } Assert.ThrowsArgument(() => { new MimeMultipartParser("trailingspace ", ParserData.MinMessageSize); }, "boundary"); Assert.ThrowsArgumentNull(() => { new MimeMultipartParser(null, ParserData.MinMessageSize); }, "boundary"); }
private static MimeMultipartParser.State ParseBufferInSteps(MimeMultipartParser parser, byte[] buffer, int readsize, out List<string> bodyParts, out int totalBytesConsumed) { MimeMultipartParser.State state = MimeMultipartParser.State.Invalid; totalBytesConsumed = 0; bodyParts = new List<string>(); bool isFinal = false; byte[] currentBodyPart = new byte[32 * 1024]; int currentBodyLength = 0; while (totalBytesConsumed <= buffer.Length) { int size = Math.Min(buffer.Length - totalBytesConsumed, readsize); byte[] parseBuffer = new byte[size]; Buffer.BlockCopy(buffer, totalBytesConsumed, parseBuffer, 0, size); int bytesConsumed = 0; ArraySegment<byte> out1; ArraySegment<byte> out2; state = parser.ParseBuffer(parseBuffer, parseBuffer.Length, ref bytesConsumed, out out1, out out2, out isFinal); totalBytesConsumed += bytesConsumed; Buffer.BlockCopy(out1.Array, out1.Offset, currentBodyPart, currentBodyLength, out1.Count); currentBodyLength += out1.Count; Buffer.BlockCopy(out2.Array, out2.Offset, currentBodyPart, currentBodyLength, out2.Count); currentBodyLength += out2.Count; if (state == MimeMultipartParser.State.BodyPartCompleted) { var bPart = new byte[currentBodyLength]; Buffer.BlockCopy(currentBodyPart, 0, bPart, 0, currentBodyLength); bodyParts.Add(Encoding.UTF8.GetString(bPart)); currentBodyLength = 0; if (isFinal) { break; } } else if (state != MimeMultipartParser.State.NeedMoreData) { return state; } } Assert.True(isFinal); return state; }
/// <summary> /// Initializes a new instance of the <see cref="MimeMultipartBodyPartParser"/> class. /// </summary> /// <param name="content">An existing <see cref="HttpContent"/> instance to use for the object's content.</param> /// <param name="streamProvider">A stream provider providing output streams for where to write body parts as they are parsed.</param> /// <param name="maxMessageSize">The max length of the entire MIME multipart message.</param> /// <param name="maxBodyPartHeaderSize">The max length of the MIME header within each MIME body part.</param> public MimeMultipartBodyPartParser( HttpContent content, MultipartStreamProvider streamProvider, long maxMessageSize, int maxBodyPartHeaderSize) { Contract.Assert(content != null, "content cannot be null."); Contract.Assert(streamProvider != null, "streamProvider cannot be null."); string boundary = ValidateArguments(content, maxMessageSize, true); _mimeParser = new MimeMultipartParser(boundary, maxMessageSize); _currentBodyPart = new MimeBodyPart(streamProvider, maxBodyPartHeaderSize, content); _content = content; _maxBodyPartHeaderSize = maxBodyPartHeaderSize; _streamProvider = streamProvider; }
/// <summary> /// Initializes a new instance of the <see cref="MimeMultipartBodyPartParser"/> class. /// </summary> /// <param name="content">An existing <see cref="HttpContent"/> instance to use for the object's content.</param> /// <param name="streamProvider">A stream provider providing output streams for where to write body parts as they are parsed.</param> /// <param name="maxMessageSize">The max length of the entire MIME multipart message.</param> /// <param name="maxBodyPartHeaderSize">The max length of the MIME header within each MIME body part.</param> public MimeMultipartBodyPartParser( HttpContent content, IMultipartStreamProvider streamProvider, long maxMessageSize, int maxBodyPartHeaderSize) { Contract.Assert(content != null, "content cannot be null."); Contract.Assert(streamProvider != null, "streamProvider cannot be null."); string boundary = ValidateArguments(content, maxMessageSize, true); _mimeParser = new MimeMultipartParser(boundary, maxMessageSize); _currentBodyPart = new MimeBodyPart(streamProvider, maxBodyPartHeaderSize); _maxBodyPartHeaderSize = maxBodyPartHeaderSize; _streamProvider = streamProvider; }
public void MultipartParserNearMatches(string boundary, bool withExtraWhitespace, bool withExtraCRLF, string nearBoundaryBody) { byte[] data = CreateBuffer(boundary, withExtraWhitespace, withExtraCRLF, nearBoundaryBody); for (var readSize = 1; readSize <= data.Length; readSize++) { MimeMultipartParser parser = CreateMimeMultipartParser(boundary); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps(parser, data, readSize, out bodyParts, out totalBytesConsumed); Assert.Equal(MimeMultipartParser.State.BodyPartCompleted, state); Assert.Equal(data.Length, totalBytesConsumed); Assert.Equal(2, bodyParts.Count); Assert.Equal(0, bodyParts[0].Length); Assert.Equal(nearBoundaryBody, bodyParts[1]); } }
public void MultipartParserNearMatches(string boundary, string nearBoundaryBody) { byte[] data = CreateBuffer(boundary, nearBoundaryBody); for (var cnt = 1; cnt <= data.Length; cnt++) { MimeMultipartParser parser = CreateMimeMultipartParser(data.Length, boundary); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps(parser, data, cnt, out bodyParts, out totalBytesConsumed); Assert.Equal(MimeMultipartParser.State.BodyPartCompleted, state); Assert.Equal(data.Length, totalBytesConsumed); Assert.Equal(2, bodyParts.Count); Assert.Equal(0, bodyParts[0].Length); Assert.Equal(nearBoundaryBody, bodyParts[1]); } }
public void MaxMessageSizeIsExact() { string boundary = "--A"; byte[] data = CreateBuffer(boundary, "cool"); for (var readSize = 1; readSize <= data.Length; readSize++) { MimeMultipartParser parser = CreateMimeMultipartParser(boundary, data.Length); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps(parser, data, 2, out bodyParts, out totalBytesConsumed); Assert.Equal(MimeMultipartParser.State.BodyPartCompleted, state); Assert.Equal(data.Length, totalBytesConsumed); Assert.Equal(2, bodyParts.Count); Assert.Empty(bodyParts[0]); } }
public void MultipartParserEmptyBuffer(string boundary) { byte[] data = CreateBuffer(boundary); for (var readSize = 1; readSize <= data.Length; readSize++) { MimeMultipartParser parser = CreateMimeMultipartParser(boundary); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps(parser, data, readSize, out bodyParts, out totalBytesConsumed); Assert.Equal(MimeMultipartParser.State.BodyPartCompleted, state); Assert.Equal(data.Length, totalBytesConsumed); Assert.Equal(2, bodyParts.Count); Assert.Equal(0, bodyParts[0].Length); Assert.Equal(0, bodyParts[1].Length); } }
public void MultipartParserSingleShortBodyPart(string boundary) { byte[] data = CreateBuffer(boundary, "A"); for (var cnt = 1; cnt <= data.Length; cnt++) { MimeMultipartParser parser = CreateMimeMultipartParser(data.Length, boundary); Assert.NotNull(parser); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps(parser, data, cnt, out bodyParts, out totalBytesConsumed); Assert.Equal(MimeMultipartParser.State.BodyPartCompleted, state); Assert.Equal(data.Length, totalBytesConsumed); Assert.Equal(2, bodyParts.Count); Assert.Equal(0, bodyParts[0].Length); Assert.Equal(1, bodyParts[1].Length); Assert.Equal("A", bodyParts[1]); } }
public void MultipartParserMultipleLongBodyParts( string boundary, bool withExtraWhitespace, bool withExtraCRLF, string[] multipleLongBodies ) { byte[] data = CreateBuffer( boundary, withExtraWhitespace, withExtraCRLF, multipleLongBodies ); for (var readSize = 1; readSize <= data.Length; readSize++) { MimeMultipartParser parser = CreateMimeMultipartParser(boundary); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps( parser, data, readSize, out bodyParts, out totalBytesConsumed ); Assert.Equal(MimeMultipartParser.State.BodyPartCompleted, state); Assert.Equal(data.Length, totalBytesConsumed); Assert.Equal(multipleLongBodies.Length + 1, bodyParts.Count); Assert.Equal(0, bodyParts[0].Length); for (var check = 0; check < multipleLongBodies.Length; check++) { Assert.Equal(multipleLongBodies[check], bodyParts[check + 1]); } } }
public async Task MimeMultipartParserTestMultipartContent(string boundary) { MultipartContent content = new MultipartContent("mixed", boundary); content.Add(new StringContent("A")); content.Add(new StringContent("B")); content.Add(new StringContent("C")); MemoryStream memStream = new MemoryStream(); await content.CopyToAsync(memStream); memStream.Position = 0; byte[] data = memStream.ToArray(); for (var readSize = 1; readSize <= data.Length; readSize++) { MimeMultipartParser parser = CreateMimeMultipartParser(boundary); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps( parser, data, readSize, out bodyParts, out totalBytesConsumed ); Assert.Equal(MimeMultipartParser.State.BodyPartCompleted, state); Assert.Equal(data.Length, totalBytesConsumed); Assert.Equal(4, bodyParts.Count); Assert.Empty(bodyParts[0]); Assert.EndsWith("A", bodyParts[1]); Assert.EndsWith("B", bodyParts[2]); Assert.EndsWith("C", bodyParts[3]); } }
public void MultipartParserMultipleShortBodyPartsWithLws(string boundary, string[] multipleShortBodies) { byte[] data = CreateBuffer(boundary, true, multipleShortBodies); for (var cnt = 1; cnt <= data.Length; cnt++) { MimeMultipartParser parser = CreateMimeMultipartParser(data.Length, boundary); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps(parser, data, cnt, out bodyParts, out totalBytesConsumed); Assert.Equal(MimeMultipartParser.State.BodyPartCompleted, state); Assert.Equal(data.Length, totalBytesConsumed); Assert.Equal(multipleShortBodies.Length + 1, bodyParts.Count); Assert.Equal(0, bodyParts[0].Length); for (var check = 0; check < multipleShortBodies.Length; check++) { Assert.Equal(multipleShortBodies[check], bodyParts[check + 1]); } } }
public void MultipartParserNesting(string boundary) { for (var nesting = 0; nesting < 16; nesting++) { string nested = CreateNestedBuffer(nesting); byte[] data = CreateBuffer(boundary, nested); for (var cnt = 1; cnt <= data.Length; cnt++) { MimeMultipartParser parser = CreateMimeMultipartParser(data.Length, boundary); int totalBytesConsumed; List <string> bodyParts; MimeMultipartParser.State state = ParseBufferInSteps(parser, data, cnt, out bodyParts, out totalBytesConsumed); Assert.Equal(MimeMultipartParser.State.BodyPartCompleted, state); Assert.Equal(data.Length, totalBytesConsumed); Assert.Equal(2, bodyParts.Count); Assert.Equal(0, bodyParts[0].Length); Assert.Equal(nested.Length, bodyParts[1].Length); } } }
/// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected void Dispose(bool disposing) { if (disposing) { _mimeParser = null; CleanupCurrentBodyPart(); } }