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");
        }
Exemplo n.º 2
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);
        }
        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 (true)
            {
                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, "The last segment is not a final segment.");
            return state;
        }
Exemplo n.º 4
0
        /// <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 && !_mimeParser.IsWaitingForEndOfMessage)
            {
                CleanupCurrentBodyPart();
                throw new IOException(Properties.Resources.ReadAsMimeMultipartUnexpectedTermination);
            }

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

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

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

                    continue;
                }

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

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

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

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

                    _mimeStatus           = MimeMultipartParser.State.NeedMoreData;
                    _bodyPartHeaderStatus = ParserState.NeedMoreData;
                    yield return(completed);
                }
                else
                {
                    // Otherwise return what we have
                    yield return(_currentBodyPart);
                }
            }
        }
        /// <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;

            if (bytesRead == 0)
            {
                CleanupCurrentBodyPart();
                throw new IOException(Properties.Resources.ReadAsMimeMultipartUnexpectedTermination);
            }

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

            while (bytesConsumed < bytesRead)
            {
                _mimeStatus = _mimeParser.ParseBuffer(data, bytesRead, ref bytesConsumed, out _parsedBodyPart[0], out _parsedBodyPart[1], out isFinal);
                if (_mimeStatus != MimeMultipartParser.State.BodyPartCompleted && _mimeStatus != MimeMultipartParser.State.NeedMoreData)
                {
                    CleanupCurrentBodyPart();
                    throw new IOException(RS.Format(Properties.Resources.ReadAsMimeMultipartParseError, bytesConsumed, data));
                }

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

                    continue;
                }

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

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

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

                    _currentBodyPart      = new MimeBodyPart(_streamProvider, _maxBodyPartHeaderSize);
                    _mimeStatus           = MimeMultipartParser.State.NeedMoreData;
                    _bodyPartHeaderStatus = ParserState.NeedMoreData;
                    yield return(completed);
                }
                else
                {
                    // Otherwise return what we have
                    yield return(_currentBodyPart);
                }
            }
        }