예제 #1
0
        private static void MultipartWriteSegmentAsyncComplete(IAsyncResult result)
        {
            Contract.Assert(result != null, "result cannot be null.");
            MultipartAsyncContext context = (MultipartAsyncContext)result.AsyncState;

            Contract.Assert(context != null, "context cannot be null");

            MimeBodyPart part = context.PartsEnumerator.Current;

            try
            {
                Stream output = context.PartsEnumerator.Current.GetOutputStream();
                output.EndWrite(result);
            }
            catch (Exception e)
            {
                part.Dispose();
                context.TaskCompletionSource.TrySetException(new IOException(Properties.Resources.ReadAsMimeMultipartErrorWriting, e));
            }

            if (!MoveNextSegment(context))
            {
                MoveNextPart(context);
            }
        }
예제 #2
0
        public void GetOutputStream_ThrowsOnInvalidStreamProvider(MultipartStreamProvider streamProvider)
        {
            HttpContent  parent   = new StringContent("hello");
            MimeBodyPart bodypart = new MimeBodyPart(streamProvider, 1024);

            Assert.Throws <InvalidOperationException>(() => bodypart.GetOutputStream(parent));
        }
        public async Task Dispose_ClosesOutputStreamOnNonMemoryStream()
        {
            // Arrange
            HttpContent   parent     = new StringContent("hello");
            Mock <Stream> mockStream = new Mock <Stream>()
            {
                CallBase = true
            };

            mockStream.Setup(s => s.CanWrite).Returns(true);
            Mock <MultipartStreamProvider> mockStreamProvider = new Mock <MultipartStreamProvider>();

            mockStreamProvider.Setup(sp => sp.GetStream(It.IsAny <HttpContent>(), It.IsAny <HttpContentHeaders>())).Returns(mockStream.Object);
            MimeBodyPart bodypart = new MimeBodyPart(mockStreamProvider.Object, 1024, parent);

            bodypart.Segments.Add(new ArraySegment <byte>(new byte[] { 1 }));
            await bodypart.WriteSegment(bodypart.Segments[0], CancellationToken.None);

            bodypart.IsComplete = true;

            // Act
            bodypart.GetCompletedHttpContent();
            bodypart.Dispose();

            // Assert
            mockStream.Verify(s => s.Close(), Times.Once());
        }
예제 #4
0
        public void GetOutputStream_ThrowsOnInvalidStreamProvider(MultipartStreamProvider streamProvider)
        {
            // Arrange
            HttpContent parent = new StringContent("hello");
            MimeBodyPart bodypart = new MimeBodyPart(streamProvider, 1024, parent);
            bodypart.Segments.Add(new ArraySegment<byte>(new byte[] { 1 }));

            // Act and Assert
            Assert.Throws<InvalidOperationException>(() => bodypart.WriteSegment(bodypart.Segments[0]).Wait());
        }
예제 #5
0
        public void GetOutputStream_ThrowsOnInvalidStreamProvider(MultipartStreamProvider streamProvider)
        {
            // Arrange
            HttpContent  parent   = new StringContent("hello");
            MimeBodyPart bodypart = new MimeBodyPart(streamProvider, 1024, parent);

            bodypart.Segments.Add(new ArraySegment <byte>(new byte[] { 1 }));

            // Act and Assert
            Assert.Throws <InvalidOperationException>(() => bodypart.WriteSegment(bodypart.Segments[0]).Wait());
        }
        public async Task GetOutputStream_ThrowsOnInvalidStreamProvider(MultipartStreamProvider streamProvider)
        {
            // Arrange
            HttpContent  parent   = new StringContent("hello");
            MimeBodyPart bodypart = new MimeBodyPart(streamProvider, 1024, parent);

            bodypart.Segments.Add(new ArraySegment <byte>(new byte[] { 1 }));

            // Act and Assert
            await Assert.ThrowsAsync <InvalidOperationException>(() => bodypart.WriteSegment(bodypart.Segments[0], CancellationToken.None));
        }
        public void Dispose_SetsPositionToZeroOnMemoryStream()
        {
            // Arrange
            HttpContent parent = new StringContent("hello");
            Mock<MemoryStream> mockStream = new Mock<MemoryStream> { CallBase = true };
            Mock<MultipartStreamProvider> mockStreamProvider = new Mock<MultipartStreamProvider>();
            mockStreamProvider.Setup(sp => sp.GetStream(It.IsAny<HttpContent>(), It.IsAny<HttpContentHeaders>())).Returns(mockStream.Object);
            MimeBodyPart bodypart = new MimeBodyPart(mockStreamProvider.Object, 1024);

            // Act
            bodypart.GetOutputStream(parent);
            bodypart.Dispose();

            // Assert
            mockStream.VerifySet(s => s.Position = 0);
        }
        public void Dispose_ClosesOutputStreamOnNonMemoryStream()
        {
            // Arrange
            HttpContent parent = new StringContent("hello");
            Mock<Stream> mockStream = new Mock<Stream>();
            mockStream.Setup(s => s.CanWrite).Returns(true);
            Mock<MultipartStreamProvider> mockStreamProvider = new Mock<MultipartStreamProvider>();
            mockStreamProvider.Setup(sp => sp.GetStream(It.IsAny<HttpContent>(), It.IsAny<HttpContentHeaders>())).Returns(mockStream.Object);
            MimeBodyPart bodypart = new MimeBodyPart(mockStreamProvider.Object, 1024);

            // Act
            bodypart.GetOutputStream(parent);
            bodypart.Dispose();

            // Assert
            mockStream.Verify(s => s.Close(), Times.Once());
        }
예제 #9
0
        private static bool CheckPartCompletion(MimeBodyPart part, List <HttpContent> result)
        {
            Contract.Assert(part != null, "part cannot be null.");
            Contract.Assert(result != null, "result cannot be null.");
            if (part.IsComplete)
            {
                if (part.HttpContent != null)
                {
                    result.Add(part.HttpContent);
                }

                bool isFinal = part.IsFinal;
                part.Dispose();
                return(isFinal);
            }

            return(false);
        }
        /// <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);

            this._mimeParser = new MimeMultipartParser(boundary, maxMessageSize);
            this._currentBodyPart = new MimeBodyPart(streamProvider, maxBodyPartHeaderSize, content);
            this._content = content;
            this._maxBodyPartHeaderSize = maxBodyPartHeaderSize;

            this._streamProvider = streamProvider;
        }
예제 #11
0
        public void Dispose_SetsPositionToZeroOnMemoryStream()
        {
            // Arrange
            HttpContent parent = new StringContent("hello");
            Mock<MemoryStream> mockStream = new Mock<MemoryStream> { CallBase = true };
            Mock<MultipartStreamProvider> mockStreamProvider = new Mock<MultipartStreamProvider>();
            mockStreamProvider.Setup(sp => sp.GetStream(It.IsAny<HttpContent>(), It.IsAny<HttpContentHeaders>())).Returns(mockStream.Object);
            MimeBodyPart bodypart = new MimeBodyPart(mockStreamProvider.Object, 1024, parent);
            bodypart.Segments.Add(new ArraySegment<byte>(new byte[] { 1 }));
            bodypart.WriteSegment(bodypart.Segments[0]).Wait();
            bodypart.IsComplete = true;

            // Act
            bodypart.GetCompletedHttpContent();
            bodypart.Dispose();

            // Assert
            mockStream.VerifySet(s => s.Position = 0);
        }
예제 #12
0
        public void Dispose_ClosesOutputStreamOnNonMemoryStream()
        {
            // Arrange
            HttpContent   parent     = new StringContent("hello");
            Mock <Stream> mockStream = new Mock <Stream>();

            mockStream.Setup(s => s.CanWrite).Returns(true);
            Mock <MultipartStreamProvider> mockStreamProvider = new Mock <MultipartStreamProvider>();

            mockStreamProvider.Setup(sp => sp.GetStream(It.IsAny <HttpContent>(), It.IsAny <HttpContentHeaders>())).Returns(mockStream.Object);
            MimeBodyPart bodypart = new MimeBodyPart(mockStreamProvider.Object, 1024);

            // Act
            bodypart.GetOutputStream(parent);
            bodypart.Dispose();

            // Assert
            mockStream.Verify(s => s.Close(), Times.Once());
        }
예제 #13
0
        public void Dispose_SetsPositionToZeroOnMemoryStream()
        {
            // Arrange
            HttpContent         parent     = new StringContent("hello");
            Mock <MemoryStream> mockStream = new Mock <MemoryStream> {
                CallBase = true
            };
            Mock <MultipartStreamProvider> mockStreamProvider = new Mock <MultipartStreamProvider>();

            mockStreamProvider.Setup(sp => sp.GetStream(It.IsAny <HttpContent>(), It.IsAny <HttpContentHeaders>())).Returns(mockStream.Object);
            MimeBodyPart bodypart = new MimeBodyPart(mockStreamProvider.Object, 1024);

            // Act
            bodypart.GetOutputStream(parent);
            bodypart.Dispose();

            // Assert
            mockStream.VerifySet(s => s.Position = 0);
        }
예제 #14
0
        public void Dispose_ClosesOutputStreamOnNonMemoryStream()
        {
            // Arrange
            HttpContent parent = new StringContent("hello");
            Mock<Stream> mockStream = new Mock<Stream>() { CallBase = true };
            mockStream.Setup(s => s.CanWrite).Returns(true);
            Mock<MultipartStreamProvider> mockStreamProvider = new Mock<MultipartStreamProvider>();
            mockStreamProvider.Setup(sp => sp.GetStream(It.IsAny<HttpContent>(), It.IsAny<HttpContentHeaders>())).Returns(mockStream.Object);
            MimeBodyPart bodypart = new MimeBodyPart(mockStreamProvider.Object, 1024, parent);
            bodypart.Segments.Add(new ArraySegment<byte>(new byte[] { 1 }));
            bodypart.WriteSegment(bodypart.Segments[0], CancellationToken.None).Wait();
            bodypart.IsComplete = true;

            // Act
            bodypart.GetCompletedHttpContent();
            bodypart.Dispose();

            // Assert
            mockStream.Verify(s => s.Close(), Times.Once());
        }
예제 #15
0
        public void Dispose_SetsPositionToZeroOnMemoryStream()
        {
            // Arrange
            HttpContent         parent     = new StringContent("hello");
            Mock <MemoryStream> mockStream = new Mock <MemoryStream> {
                CallBase = true
            };
            Mock <MultipartStreamProvider> mockStreamProvider = new Mock <MultipartStreamProvider>();

            mockStreamProvider.Setup(sp => sp.GetStream(It.IsAny <HttpContent>(), It.IsAny <HttpContentHeaders>())).Returns(mockStream.Object);
            MimeBodyPart bodypart = new MimeBodyPart(mockStreamProvider.Object, 1024, parent);

            bodypart.Segments.Add(new ArraySegment <byte>(new byte[] { 1 }));
            bodypart.WriteSegment(bodypart.Segments[0], CancellationToken.None).Wait();
            bodypart.IsComplete = true;

            // Act
            bodypart.GetCompletedHttpContent();
            bodypart.Dispose();

            // Assert
            mockStream.VerifySet(s => s.Position = 0);
        }
        private static bool CheckPartCompletion(MimeBodyPart part, List<HttpContent> result)
        {
            Contract.Assert(part != null, "part cannot be null.");
            Contract.Assert(result != null, "result cannot be null.");
            if (part.IsComplete)
            {
                if (part.HttpContent != null)
                {
                    result.Add(part.HttpContent);
                }

                bool isFinal = part.IsFinal;
                part.Dispose();
                return isFinal;
            }

            return false;
        }
 public void GetOutputStream_ThrowsOnInvalidStreamProvider(MultipartStreamProvider streamProvider)
 {
     HttpContent parent = new StringContent("hello");
     MimeBodyPart bodypart = new MimeBodyPart(streamProvider, 1024);
     Assert.Throws<InvalidOperationException>(() => bodypart.GetOutputStream(parent));
 }
 private void CleanupCurrentBodyPart()
 {
     if (this._currentBodyPart != null)
     {
         this._currentBodyPart.Dispose();
         this._currentBodyPart = null;
     }
 }
        /// <summary>
        /// Parses the data provided and generates parsed MIME body part bodies in the form of <see cref="ArraySegment{T}"/> which are ready to 
        /// write to the output stream.
        /// </summary>
        /// <param name="data">The data to parse</param>
        /// <param name="bytesRead">The number of bytes available in the input data</param>
        /// <returns>Parsed <see cref="MimeBodyPart"/> instances.</returns>
        public IEnumerable<MimeBodyPart> ParseBuffer(byte[] data, int bytesRead)
        {
            int bytesConsumed = 0;
            bool isFinal = false;

            // There's a special case here - if we've reached the end of the message and there's no optional
            // CRLF, then we're out of bytes to read, but we have finished the message. 
            //
            // If IsWaitingForEndOfMessage is true and we're at the end of the stream, then we're going to 
            // call into the parser again with an empty array as the buffer to signal the end of the parse. 
            // Then the final boundary segment will be marked as complete. 
            if (bytesRead == 0 && !this._mimeParser.IsWaitingForEndOfMessage)
            {
                this.CleanupCurrentBodyPart();
                throw new IOException(Resources.ReadAsMimeMultipartUnexpectedTermination);
            }

            // Make sure we remove an old array segments.
            this._currentBodyPart.Segments.Clear();

            while (this._mimeParser.CanParseMore(bytesRead, bytesConsumed))
            {
                this._mimeStatus = this._mimeParser.ParseBuffer(data, bytesRead, ref bytesConsumed, out this._parsedBodyPart[0], out this._parsedBodyPart[1], out isFinal);
                if (this._mimeStatus != MimeMultipartParser.State.BodyPartCompleted && this._mimeStatus != MimeMultipartParser.State.NeedMoreData)
                {
                    this.CleanupCurrentBodyPart();
                    throw Error.InvalidOperation(Resources.ReadAsMimeMultipartParseError, bytesConsumed, data);
                }

                // First body is empty preamble which we just ignore
                if (this._isFirst)
                {
                    if (this._mimeStatus == MimeMultipartParser.State.BodyPartCompleted)
                    {
                        this._isFirst = false;
                    }

                    continue;
                }

                // Parse the two array segments containing parsed body parts that the MIME parser gave us
                foreach (ArraySegment<byte> part in this._parsedBodyPart)
                {
                    if (part.Count == 0)
                    {
                        continue;
                    }

                    if (this._bodyPartHeaderStatus != ParserState.Done)
                    {
                        int headerConsumed = part.Offset;
                        this._bodyPartHeaderStatus = this._currentBodyPart.HeaderParser.ParseBuffer(part.Array, part.Count + part.Offset, ref headerConsumed);
                        if (this._bodyPartHeaderStatus == ParserState.Done)
                        {
                            // Add the remainder as body part content
                            this._currentBodyPart.Segments.Add(new ArraySegment<byte>(part.Array, headerConsumed, part.Count + part.Offset - headerConsumed));
                        }
                        else if (this._bodyPartHeaderStatus != ParserState.NeedMoreData)
                        {
                            this.CleanupCurrentBodyPart();
                            throw Error.InvalidOperation(Resources.ReadAsMimeMultipartHeaderParseError, headerConsumed, part.Array);
                        }
                    }
                    else
                    {
                        // Add the data as body part content
                        this._currentBodyPart.Segments.Add(part);
                    }
                }

                if (this._mimeStatus == MimeMultipartParser.State.BodyPartCompleted)
                {
                    // If body is completed then swap current body part
                    MimeBodyPart completed = this._currentBodyPart;
                    completed.IsComplete = true;
                    completed.IsFinal = isFinal;

                    this._currentBodyPart = new MimeBodyPart(this._streamProvider, this._maxBodyPartHeaderSize, this._content);

                    this._mimeStatus = MimeMultipartParser.State.NeedMoreData;
                    this._bodyPartHeaderStatus = ParserState.NeedMoreData;
                    yield return completed;
                }
                else
                {
                    // Otherwise return what we have 
                    yield return this._currentBodyPart;
                }
            }
        }