コード例 #1
0
        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");
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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");
        }
コード例 #4
0
        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]);
                }
            }
        }
コード例 #5
0
        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);
            }
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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");
        }
コード例 #8
0
        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;
        }
コード例 #9
0
        /// <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;
        }
コード例 #10
0
        /// <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;
        }
コード例 #11
0
        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]);
            }
        }
コード例 #12
0
        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]);
            }
        }
コード例 #13
0
        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]);
            }
        }
コード例 #14
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);
            }
        }
コード例 #15
0
        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]);
            }
        }
コード例 #16
0
        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]);
                }
            }
        }
コード例 #17
0
        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]);
            }
        }
コード例 #18
0
        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]);
                }
            }
        }
コード例 #19
0
        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);
                }
            }
        }
コード例 #20
0
        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");
        }
コード例 #21
0
        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");
        }
コード例 #22
0
 /// <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();
     }
 }