/// <summary>
        /// Initializes a new instance of the <see cref="MimeMultipartParser"/> class.
        /// </summary>
        /// <param name="boundary">Message boundary</param>
        /// <param name="maxMessageSize">Maximum length of entire MIME multipart message.</param>
        public MimeMultipartParser(string boundary, long maxMessageSize)
        {
            // The minimum length which would be an empty message terminated by CRLF
            if (maxMessageSize < MimeMultipartParser.MinMessageSize)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo("maxMessageSize", maxMessageSize, MinMessageSize);
            }

            if (String.IsNullOrWhiteSpace(boundary))
            {
                throw Error.ArgumentNull("boundary");
            }

            if (boundary.Length > MaxBoundarySize - 10)
            {
                throw Error.ArgumentMustBeLessThanOrEqualTo("boundary", boundary.Length, MaxBoundarySize - 10);
            }

            if (boundary.EndsWith(" ", StringComparison.Ordinal))
            {
                throw Error.Argument("boundary", Properties.Resources.MimeMultipartParserBadBoundary);
            }

            _maxMessageSize = maxMessageSize;
            _boundary = boundary;
            _currentBoundary = new CurrentBodyPartStore(_boundary);
            _bodyPartState = BodyPartState.AfterFirstLineFeed;
        }
Пример #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MimeMultipartParser"/> class.
        /// </summary>
        /// <param name="boundary">Message boundary</param>
        /// <param name="maxMessageSize">Maximum length of entire MIME multipart message.</param>
        public MimeMultipartParser(string boundary, long maxMessageSize)
        {
            // The minimum length which would be an empty message terminated by CRLF
            if (maxMessageSize < MimeMultipartParser.MinMessageSize)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo("maxMessageSize", maxMessageSize, MinMessageSize);
            }

            if (String.IsNullOrWhiteSpace(boundary))
            {
                throw Error.ArgumentNull("boundary");
            }

            if (boundary.Length > MaxBoundarySize - 10)
            {
                throw Error.ArgumentMustBeLessThanOrEqualTo("boundary", boundary.Length, MaxBoundarySize - 10);
            }

            if (boundary.EndsWith(" ", StringComparison.Ordinal))
            {
                throw Error.Argument("boundary", Resources.MimeMultipartParserBadBoundary);
            }

            this._maxMessageSize  = maxMessageSize;
            this._boundary        = boundary;
            this._currentBoundary = new CurrentBodyPartStore(this._boundary);
            this._bodyPartState   = BodyPartState.AfterFirstLineFeed;
        }
Пример #3
0
        public BodyPart()
        {
            // Sets up the body part's shape.
            this.Shape = new Polygon
            {
                HorizontalAlignment = HorizontalAlignment.Left,
                VerticalAlignment = VerticalAlignment.Top,
                StrokeThickness = 2.0,
                Fill = Brushes.Black,
                Stroke = Brushes.White
            };
            this.state = BodyPartState.PreGame;

            // Sets up the animation for the body part.
            this.FillAnimation = new Storyboard();
            ColorAnimation ca = new ColorAnimation(Colors.White, new Duration(BodyPart.AnimationDuration));
            Storyboard.SetTarget(ca, this.Shape);
            Storyboard.SetTargetProperty(ca, new PropertyPath("Fill.Color", new object[] { Polygon.FillProperty, SolidColorBrush.ColorProperty }));
            this.FillAnimation.Children.Add(ca);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MimeMultipartParser"/> class.
        /// </summary>
        /// <param name="boundary">Message boundary</param>
        /// <param name="maxMessageSize">Maximum length of entire MIME multipart message.</param>
        public MimeMultipartParser(string boundary, long maxMessageSize)
        {
            // The minimum length which would be an empty message terminated by CRLF
            if (maxMessageSize < MimeMultipartParser.MinMessageSize)
            {
                throw new ArgumentOutOfRangeException("maxMessageSize", maxMessageSize, RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, MimeMultipartParser.MinMessageSize));
            }

            if (String.IsNullOrWhiteSpace(boundary))
            {
                throw new ArgumentNullException("boundary");
            }

            if (boundary.EndsWith(" ", StringComparison.Ordinal))
            {
                throw new ArgumentException(Properties.Resources.MimeMultipartParserBadBoundary, "boundary");
            }

            _maxMessageSize  = maxMessageSize;
            _boundary        = boundary;
            _currentBoundary = new CurrentBodyPartStore(_boundary);
            _bodyPartState   = BodyPartState.AfterFirstLineFeed;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MimeMultipartParser"/> class.
        /// </summary>
        /// <param name="boundary">Message boundary</param>
        /// <param name="maxMessageSize">Maximum length of entire MIME multipart message.</param>
        public MimeMultipartParser(string boundary, long maxMessageSize)
        {
            // The minimum length which would be an empty message terminated by CRLF
            if (maxMessageSize < MimeMultipartParser.MinMessageSize)
            {
                throw new ArgumentOutOfRangeException("maxMessageSize", maxMessageSize, RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, MimeMultipartParser.MinMessageSize));
            }

            if (String.IsNullOrWhiteSpace(boundary))
            {
                throw new ArgumentNullException("boundary");
            }

            if (boundary.EndsWith(" ", StringComparison.Ordinal))
            {
                throw new ArgumentException(Properties.Resources.MimeMultipartParserBadBoundary, "boundary");
            }

            _maxMessageSize = maxMessageSize;
            _boundary = boundary;
            _currentBoundary = new CurrentBodyPartStore(_boundary);
            _bodyPartState = BodyPartState.AfterFirstLineFeed;
        }
        private static State ParseBodyPart(
            byte[] buffer,
            int bytesReady,
            ref int bytesConsumed,
            ref BodyPartState bodyPartState,
            long maximumMessageLength,
            ref long totalBytesConsumed,
            CurrentBodyPartStore currentBodyPart)
        {
            Contract.Assert((bytesReady - bytesConsumed) >= 0, "ParseBodyPart()|(bytesReady - bytesConsumed) < 0");
            Contract.Assert(maximumMessageLength <= 0 || totalBytesConsumed <= maximumMessageLength, "ParseBodyPart()|Message already read exceeds limit.");

            // Remember where we started.
            int segmentStart;
            int initialBytesParsed = bytesConsumed;

            // Set up parsing status with what will happen if we exceed the buffer.
            State parseStatus  = State.DataTooBig;
            long  effectiveMax = maximumMessageLength <= 0 ? Int64.MaxValue : (maximumMessageLength - totalBytesConsumed + bytesConsumed);

            if (bytesReady < effectiveMax)
            {
                parseStatus  = State.NeedMoreData;
                effectiveMax = bytesReady;
            }

            currentBodyPart.ResetBoundaryOffset();

            Contract.Assert(bytesConsumed < effectiveMax, "We have already consumed more than the max header length.");

            switch (bodyPartState)
            {
            case BodyPartState.BodyPart:
                while (buffer[bytesConsumed] != MimeMultipartParser.CR)
                {
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }
                }

                // Remember potential boundary
                currentBodyPart.AppendBoundary(MimeMultipartParser.CR);

                // Move past the CR
                bodyPartState = BodyPartState.AfterFirstCarriageReturn;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case BodyPartState.AfterFirstCarriageReturn;

            case BodyPartState.AfterFirstCarriageReturn:
                if (buffer[bytesConsumed] != MimeMultipartParser.LF)
                {
                    currentBodyPart.ResetBoundary();
                    bodyPartState = BodyPartState.BodyPart;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.BodyPart;
                }

                // Remember potential boundary
                currentBodyPart.AppendBoundary(MimeMultipartParser.LF);

                // Move past the CR
                bodyPartState = BodyPartState.AfterFirstLineFeed;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case BodyPartState.AfterFirstLineFeed;

            case BodyPartState.AfterFirstLineFeed:
                if (buffer[bytesConsumed] == MimeMultipartParser.CR)
                {
                    // Remember potential boundary
                    currentBodyPart.ResetBoundary();
                    currentBodyPart.AppendBoundary(MimeMultipartParser.CR);

                    // Move past the CR
                    bodyPartState = BodyPartState.AfterFirstCarriageReturn;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.AfterFirstCarriageReturn;
                }

                if (buffer[bytesConsumed] != MimeMultipartParser.Dash)
                {
                    currentBodyPart.ResetBoundary();
                    bodyPartState = BodyPartState.BodyPart;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.BodyPart;
                }

                // Remember potential boundary
                currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);

                // Move past the Dash
                bodyPartState = BodyPartState.AfterFirstDash;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case BodyPartState.AfterFirstDash;

            case BodyPartState.AfterFirstDash:
                if (buffer[bytesConsumed] != MimeMultipartParser.Dash)
                {
                    currentBodyPart.ResetBoundary();
                    bodyPartState = BodyPartState.BodyPart;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.BodyPart;
                }

                // Remember potential boundary
                currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);

                // Move past the Dash
                bodyPartState = BodyPartState.Boundary;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case BodyPartState.Boundary;

            case BodyPartState.Boundary:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != MimeMultipartParser.CR)
                {
                    if (++bytesConsumed == effectiveMax)
                    {
                        currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart);
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart);
                }

                // Remember potential boundary
                currentBodyPart.AppendBoundary(MimeMultipartParser.CR);

                // Move past the CR
                bodyPartState = BodyPartState.AfterSecondCarriageReturn;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case BodyPartState.AfterSecondCarriageReturn;

            case BodyPartState.AfterSecondCarriageReturn:
                if (buffer[bytesConsumed] != MimeMultipartParser.LF)
                {
                    currentBodyPart.ResetBoundary();
                    bodyPartState = BodyPartState.BodyPart;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.BodyPart;
                }

                // Remember potential boundary
                currentBodyPart.AppendBoundary(MimeMultipartParser.LF);

                // Move past the LF
                bytesConsumed++;

                bodyPartState = BodyPartState.BodyPart;
                if (currentBodyPart.IsBoundaryValid())
                {
                    parseStatus = State.BodyPartCompleted;
                }
                else
                {
                    currentBodyPart.ResetBoundary();
                    if (bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.BodyPart;
                }

                goto quit;
            }

quit:
            if (initialBytesParsed < bytesConsumed)
            {
                int boundaryLength = currentBodyPart.BoundaryDelta;
                if (boundaryLength > 0 && parseStatus != State.BodyPartCompleted)
                {
                    currentBodyPart.HasPotentialBoundaryLeftOver = true;
                }

                int bodyPartEnd = bytesConsumed - initialBytesParsed - boundaryLength;

                currentBodyPart.BodyPart = new ArraySegment <byte>(buffer, initialBytesParsed, bodyPartEnd);
            }

            totalBytesConsumed += bytesConsumed - initialBytesParsed;
            return(parseStatus);
        }
Пример #7
0
        private static State ParseBodyPart(
            byte[] buffer,
            int bytesReady,
            ref int bytesConsumed,
            ref BodyPartState bodyPartState,
            long maximumMessageLength,
            ref long totalBytesConsumed,
            CurrentBodyPartStore currentBodyPart)
        {
            Contract.Assert((bytesReady - bytesConsumed) >= 0, "ParseBodyPart()|(bytesReady - bytesConsumed) < 0");
            Contract.Assert(maximumMessageLength <= 0 || totalBytesConsumed <= maximumMessageLength, "ParseBodyPart()|Message already read exceeds limit.");

            // Remember where we started.
            int segmentStart;
            int initialBytesParsed = bytesConsumed;

            if (bytesReady == 0 && bodyPartState == BodyPartState.AfterBoundary && currentBodyPart.IsFinal)
            {
                // We've seen the end of the stream - the final body part has no trailing CRLF
                return(State.BodyPartCompleted);
            }

            // Set up parsing status with what will happen if we exceed the buffer.
            State parseStatus  = State.DataTooBig;
            long  effectiveMax = maximumMessageLength <= 0 ? Int64.MaxValue : (maximumMessageLength - totalBytesConsumed + bytesConsumed);

            if (effectiveMax == 0)
            {
                // effectiveMax is based on our max message size - if we've arrrived at the max size, then we need
                // to stop parsing.
                return(State.DataTooBig);
            }

            if (bytesReady <= effectiveMax)
            {
                parseStatus  = State.NeedMoreData;
                effectiveMax = bytesReady;
            }

            currentBodyPart.ResetBoundaryOffset();

            Contract.Assert(bytesConsumed < effectiveMax, "We have already consumed more than the max header length.");

            switch (bodyPartState)
            {
            case BodyPartState.BodyPart:
                while (buffer[bytesConsumed] != MimeMultipartParser.CR)
                {
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }
                }

                // Remember potential boundary
                currentBodyPart.AppendBoundary(MimeMultipartParser.CR);

                // Move past the CR
                bodyPartState = BodyPartState.AfterFirstCarriageReturn;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case BodyPartState.AfterFirstCarriageReturn;

            case BodyPartState.AfterFirstCarriageReturn:
                if (buffer[bytesConsumed] != MimeMultipartParser.LF)
                {
                    currentBodyPart.ResetBoundary();
                    bodyPartState = BodyPartState.BodyPart;
                    goto case BodyPartState.BodyPart;
                }

                // Remember potential boundary
                currentBodyPart.AppendBoundary(MimeMultipartParser.LF);

                // Move past the CR
                bodyPartState = BodyPartState.AfterFirstLineFeed;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case BodyPartState.AfterFirstLineFeed;

            case BodyPartState.AfterFirstLineFeed:
                if (buffer[bytesConsumed] == MimeMultipartParser.CR)
                {
                    // Remember potential boundary
                    currentBodyPart.ResetBoundary();
                    currentBodyPart.AppendBoundary(MimeMultipartParser.CR);

                    // Move past the CR
                    bodyPartState = BodyPartState.AfterFirstCarriageReturn;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.AfterFirstCarriageReturn;
                }

                if (buffer[bytesConsumed] != MimeMultipartParser.Dash)
                {
                    currentBodyPart.ResetBoundary();
                    bodyPartState = BodyPartState.BodyPart;
                    goto case BodyPartState.BodyPart;
                }

                // Remember potential boundary
                currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);

                // Move past the Dash
                bodyPartState = BodyPartState.AfterFirstDash;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case BodyPartState.AfterFirstDash;

            case BodyPartState.AfterFirstDash:
                if (buffer[bytesConsumed] != MimeMultipartParser.Dash)
                {
                    currentBodyPart.ResetBoundary();
                    bodyPartState = BodyPartState.BodyPart;
                    goto case BodyPartState.BodyPart;
                }

                // Remember potential boundary
                currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);

                // Move past the Dash
                bodyPartState = BodyPartState.Boundary;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case BodyPartState.Boundary;

            case BodyPartState.Boundary:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != MimeMultipartParser.CR)
                {
                    if (++bytesConsumed == effectiveMax)
                    {
                        if (currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart))
                        {
                            if (currentBodyPart.IsBoundaryComplete())
                            {
                                // At this point we've seen the end of a boundary segment that is aligned at the end
                                // of the buffer - this might be because we have another segment coming or it might
                                // truly be the end of the message.
                                bodyPartState = BodyPartState.AfterBoundary;
                            }
                        }
                        else
                        {
                            currentBodyPart.ResetBoundary();
                            bodyPartState = BodyPartState.BodyPart;
                        }
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    if (!currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart))
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        goto case BodyPartState.BodyPart;
                    }
                }

                goto case BodyPartState.AfterBoundary;

            case BodyPartState.AfterBoundary:

                // This state means that we just saw the end of a boundary. It might by a 'normal' boundary, in which
                // case it's followed by optional whitespace and a CRLF. Or it might be the 'final' boundary and will
                // be followed by '--', optional whitespace and an optional CRLF.
                if (buffer[bytesConsumed] == MimeMultipartParser.Dash && !currentBodyPart.IsFinal)
                {
                    currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);
                    if (++bytesConsumed == effectiveMax)
                    {
                        bodyPartState = BodyPartState.AfterSecondDash;
                        goto quit;
                    }

                    goto case BodyPartState.AfterSecondDash;
                }

                // Capture optional whitespace
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != MimeMultipartParser.CR)
                {
                    if (++bytesConsumed == effectiveMax)
                    {
                        if (!currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart))
                        {
                            // It's an unexpected character
                            currentBodyPart.ResetBoundary();
                            bodyPartState = BodyPartState.BodyPart;
                        }

                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    if (!currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart))
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        goto case BodyPartState.BodyPart;
                    }
                }

                if (buffer[bytesConsumed] == MimeMultipartParser.CR)
                {
                    currentBodyPart.AppendBoundary(MimeMultipartParser.CR);
                    if (++bytesConsumed == effectiveMax)
                    {
                        bodyPartState = BodyPartState.AfterSecondCarriageReturn;
                        goto quit;
                    }

                    goto case BodyPartState.AfterSecondCarriageReturn;
                }
                else
                {
                    // It's an unexpected character
                    currentBodyPart.ResetBoundary();
                    bodyPartState = BodyPartState.BodyPart;
                    goto case BodyPartState.BodyPart;
                }

            case BodyPartState.AfterSecondDash:
                if (buffer[bytesConsumed] == MimeMultipartParser.Dash)
                {
                    currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);
                    bytesConsumed++;

                    if (currentBodyPart.IsBoundaryComplete())
                    {
                        Debug.Assert(currentBodyPart.IsFinal);

                        // If we get in here, it means we've see the trailing '--' of the last boundary - in order to consume all of the
                        // remaining bytes, we don't mark the parse as complete again - wait until this method is called again with the
                        // empty buffer to do that.
                        bodyPartState = BodyPartState.AfterBoundary;
                        parseStatus   = State.NeedMoreData;
                        goto quit;
                    }
                    else
                    {
                        currentBodyPart.ResetBoundary();
                        if (bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case BodyPartState.BodyPart;
                    }
                }
                else
                {
                    currentBodyPart.ResetBoundary();
                    bodyPartState = BodyPartState.BodyPart;
                    goto case BodyPartState.BodyPart;
                }

            case BodyPartState.AfterSecondCarriageReturn:
                if (buffer[bytesConsumed] != MimeMultipartParser.LF)
                {
                    currentBodyPart.ResetBoundary();
                    bodyPartState = BodyPartState.BodyPart;
                    goto case BodyPartState.BodyPart;
                }

                currentBodyPart.AppendBoundary(MimeMultipartParser.LF);
                bytesConsumed++;

                bodyPartState = BodyPartState.BodyPart;
                if (currentBodyPart.IsBoundaryComplete())
                {
                    parseStatus = State.BodyPartCompleted;
                    goto quit;
                }
                else
                {
                    currentBodyPart.ResetBoundary();
                    if (bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.BodyPart;
                }
            }

quit:
            if (initialBytesParsed < bytesConsumed)
            {
                int boundaryLength = currentBodyPart.BoundaryDelta;
                if (boundaryLength > 0 && parseStatus != State.BodyPartCompleted)
                {
                    currentBodyPart.HasPotentialBoundaryLeftOver = true;
                }

                int bodyPartEnd = bytesConsumed - initialBytesParsed - boundaryLength;

                currentBodyPart.BodyPart = new ArraySegment <byte>(buffer, initialBytesParsed, bodyPartEnd);
            }

            totalBytesConsumed += bytesConsumed - initialBytesParsed;
            return(parseStatus);
        }
        private static State ParseBodyPart(
            byte[] buffer,
            int bytesReady,
            ref int bytesConsumed,
            ref BodyPartState bodyPartState,
            long maximumMessageLength,
            ref long totalBytesConsumed,
            CurrentBodyPartStore currentBodyPart)
        {
            Contract.Assert((bytesReady - bytesConsumed) >= 0, "ParseBodyPart()|(bytesReady - bytesConsumed) < 0");
            Contract.Assert(maximumMessageLength <= 0 || totalBytesConsumed <= maximumMessageLength, "ParseBodyPart()|Message already read exceeds limit.");

            // Remember where we started.
            int segmentStart;
            int initialBytesParsed = bytesConsumed;

            // Set up parsing status with what will happen if we exceed the buffer.
            State parseStatus = State.DataTooBig;
            long effectiveMax = maximumMessageLength <= 0 ? Int64.MaxValue : (maximumMessageLength - totalBytesConsumed + bytesConsumed);
            if (bytesReady < effectiveMax)
            {
                parseStatus = State.NeedMoreData;
                effectiveMax = bytesReady;
            }

            currentBodyPart.ResetBoundaryOffset();

            Contract.Assert(bytesConsumed < effectiveMax, "We have already consumed more than the max header length.");

            switch (bodyPartState)
            {
                case BodyPartState.BodyPart:
                    while (buffer[bytesConsumed] != MimeMultipartParser.CR)
                    {
                        if (++bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }
                    }

                    // Remember potential boundary
                    currentBodyPart.AppendBoundary(MimeMultipartParser.CR);

                    // Move past the CR
                    bodyPartState = BodyPartState.AfterFirstCarriageReturn;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.AfterFirstCarriageReturn;

                case BodyPartState.AfterFirstCarriageReturn:
                    if (buffer[bytesConsumed] != MimeMultipartParser.LF)
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        if (++bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case BodyPartState.BodyPart;
                    }

                    // Remember potential boundary
                    currentBodyPart.AppendBoundary(MimeMultipartParser.LF);

                    // Move past the CR
                    bodyPartState = BodyPartState.AfterFirstLineFeed;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.AfterFirstLineFeed;

                case BodyPartState.AfterFirstLineFeed:
                    if (buffer[bytesConsumed] == MimeMultipartParser.CR)
                    {
                        // Remember potential boundary
                        currentBodyPart.ResetBoundary();
                        currentBodyPart.AppendBoundary(MimeMultipartParser.CR);

                        // Move past the CR
                        bodyPartState = BodyPartState.AfterFirstCarriageReturn;
                        if (++bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case BodyPartState.AfterFirstCarriageReturn;
                    }

                    if (buffer[bytesConsumed] != MimeMultipartParser.Dash)
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        if (++bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case BodyPartState.BodyPart;
                    }

                    // Remember potential boundary
                    currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);

                    // Move past the Dash
                    bodyPartState = BodyPartState.AfterFirstDash;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.AfterFirstDash;

                case BodyPartState.AfterFirstDash:
                    if (buffer[bytesConsumed] != MimeMultipartParser.Dash)
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        if (++bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case BodyPartState.BodyPart;
                    }

                    // Remember potential boundary
                    currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);

                    // Move past the Dash
                    bodyPartState = BodyPartState.Boundary;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.Boundary;

                case BodyPartState.Boundary:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != MimeMultipartParser.CR)
                    {
                        if (++bytesConsumed == effectiveMax)
                        {
                            currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart);
                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart);
                    }

                    // Remember potential boundary
                    currentBodyPart.AppendBoundary(MimeMultipartParser.CR);

                    // Move past the CR
                    bodyPartState = BodyPartState.AfterSecondCarriageReturn;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.AfterSecondCarriageReturn;

                case BodyPartState.AfterSecondCarriageReturn:
                    if (buffer[bytesConsumed] != MimeMultipartParser.LF)
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        if (++bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case BodyPartState.BodyPart;
                    }

                    // Remember potential boundary
                    currentBodyPart.AppendBoundary(MimeMultipartParser.LF);

                    // Move past the LF
                    bytesConsumed++;

                    bodyPartState = BodyPartState.BodyPart;
                    if (currentBodyPart.IsBoundaryValid())
                    {
                        parseStatus = State.BodyPartCompleted;
                    }
                    else
                    {
                        currentBodyPart.ResetBoundary();
                        if (bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case BodyPartState.BodyPart;
                    }

                    goto quit;
            }

        quit:
            if (initialBytesParsed < bytesConsumed)
            {
                int boundaryLength = currentBodyPart.BoundaryDelta;
                if (boundaryLength > 0 && parseStatus != State.BodyPartCompleted)
                {
                    currentBodyPart.HasPotentialBoundaryLeftOver = true;
                }

                int bodyPartEnd = bytesConsumed - initialBytesParsed - boundaryLength;

                currentBodyPart.BodyPart = new ArraySegment<byte>(buffer, initialBytesParsed, bodyPartEnd);
            }

            totalBytesConsumed += bytesConsumed - initialBytesParsed;
            return parseStatus;
        }
        private static State ParseBodyPart(
            byte[] buffer,
            int bytesReady,
            ref int bytesConsumed,
            ref BodyPartState bodyPartState,
            long maximumMessageLength,
            ref long totalBytesConsumed,
            CurrentBodyPartStore currentBodyPart)
        {
            Contract.Assert((bytesReady - bytesConsumed) >= 0, "ParseBodyPart()|(bytesReady - bytesConsumed) < 0");
            Contract.Assert(maximumMessageLength <= 0 || totalBytesConsumed <= maximumMessageLength, "ParseBodyPart()|Message already read exceeds limit.");

            // Remember where we started.
            int segmentStart;
            int initialBytesParsed = bytesConsumed;

            if (bytesReady == 0 && bodyPartState == BodyPartState.AfterBoundary && currentBodyPart.IsFinal)
            {
                // We've seen the end of the stream - the final body part has no trailing CRLF
                return State.BodyPartCompleted;
            }

            // Set up parsing status with what will happen if we exceed the buffer.
            State parseStatus = State.DataTooBig;
            long effectiveMax = maximumMessageLength <= 0 ? Int64.MaxValue : (maximumMessageLength - totalBytesConsumed + bytesConsumed);
            if (effectiveMax == 0)
            {
                // effectiveMax is based on our max message size - if we've arrrived at the max size, then we need
                // to stop parsing.
                return State.DataTooBig;
            }

            if (bytesReady <= effectiveMax)
            {
                parseStatus = State.NeedMoreData;
                effectiveMax = bytesReady;
            }

            currentBodyPart.ResetBoundaryOffset();

            Contract.Assert(bytesConsumed < effectiveMax, "We have already consumed more than the max header length.");

            switch (bodyPartState)
            {
                case BodyPartState.BodyPart:
                    while (buffer[bytesConsumed] != MimeMultipartParser.CR)
                    {
                        if (++bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }
                    }

                    // Remember potential boundary
                    currentBodyPart.AppendBoundary(MimeMultipartParser.CR);

                    // Move past the CR
                    bodyPartState = BodyPartState.AfterFirstCarriageReturn;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.AfterFirstCarriageReturn;

                case BodyPartState.AfterFirstCarriageReturn:
                    if (buffer[bytesConsumed] != MimeMultipartParser.LF)
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        goto case BodyPartState.BodyPart;
                    }

                    // Remember potential boundary
                    currentBodyPart.AppendBoundary(MimeMultipartParser.LF);

                    // Move past the CR
                    bodyPartState = BodyPartState.AfterFirstLineFeed;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.AfterFirstLineFeed;

                case BodyPartState.AfterFirstLineFeed:
                    if (buffer[bytesConsumed] == MimeMultipartParser.CR)
                    {
                        // Remember potential boundary
                        currentBodyPart.ResetBoundary();
                        currentBodyPart.AppendBoundary(MimeMultipartParser.CR);

                        // Move past the CR
                        bodyPartState = BodyPartState.AfterFirstCarriageReturn;
                        if (++bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case BodyPartState.AfterFirstCarriageReturn;
                    }

                    if (buffer[bytesConsumed] != MimeMultipartParser.Dash)
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        goto case BodyPartState.BodyPart;
                    }

                    // Remember potential boundary
                    currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);

                    // Move past the Dash
                    bodyPartState = BodyPartState.AfterFirstDash;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.AfterFirstDash;

                case BodyPartState.AfterFirstDash:
                    if (buffer[bytesConsumed] != MimeMultipartParser.Dash)
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        goto case BodyPartState.BodyPart;
                    }

                    // Remember potential boundary
                    currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);

                    // Move past the Dash
                    bodyPartState = BodyPartState.Boundary;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case BodyPartState.Boundary;

                case BodyPartState.Boundary:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != MimeMultipartParser.CR)
                    {
                        if (++bytesConsumed == effectiveMax)
                        {
                            if (currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart))
                            {
                                if (currentBodyPart.IsBoundaryComplete())
                                {
                                    // At this point we've seen the end of a boundary segment that is aligned at the end
                                    // of the buffer - this might be because we have another segment coming or it might
                                    // truly be the end of the message.
                                    bodyPartState = BodyPartState.AfterBoundary;
                                }
                            }
                            else
                            {
                                currentBodyPart.ResetBoundary();
                                bodyPartState = BodyPartState.BodyPart;
                            }
                            goto quit;
                        }
                    }
                    
                    if (bytesConsumed > segmentStart)
                    {
                        if (!currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart))
                        {
                            currentBodyPart.ResetBoundary();
                            bodyPartState = BodyPartState.BodyPart;
                            goto case BodyPartState.BodyPart;
                        }
                    }

                    goto case BodyPartState.AfterBoundary;

                case BodyPartState.AfterBoundary:

                    // This state means that we just saw the end of a boundary. It might by a 'normal' boundary, in which
                    // case it's followed by optional whitespace and a CRLF. Or it might be the 'final' boundary and will 
                    // be followed by '--', optional whitespace and an optional CRLF.
                    if (buffer[bytesConsumed] == MimeMultipartParser.Dash && !currentBodyPart.IsFinal)
                    {
                        currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);
                        if (++bytesConsumed == effectiveMax)
                        {
                            bodyPartState = BodyPartState.AfterSecondDash;
                            goto quit;
                        }

                        goto case BodyPartState.AfterSecondDash;
                    }

                    // Capture optional whitespace
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != MimeMultipartParser.CR)
                    {
                        if (++bytesConsumed == effectiveMax)
                        {
                            if (!currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart))
                            {
                                // It's an unexpected character
                                currentBodyPart.ResetBoundary();
                                bodyPartState = BodyPartState.BodyPart;
                            }

                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        if (!currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart))
                        {
                            currentBodyPart.ResetBoundary();
                            bodyPartState = BodyPartState.BodyPart;
                            goto case BodyPartState.BodyPart;
                        }
                    }

                    if (buffer[bytesConsumed] == MimeMultipartParser.CR)
                    {
                        currentBodyPart.AppendBoundary(MimeMultipartParser.CR);
                        if (++bytesConsumed == effectiveMax)
                        {
                            bodyPartState = BodyPartState.AfterSecondCarriageReturn;
                            goto quit;
                        }

                        goto case BodyPartState.AfterSecondCarriageReturn;
                    }
                    else
                    {
                        // It's an unexpected character
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        goto case BodyPartState.BodyPart;
                    }

                case BodyPartState.AfterSecondDash:
                    if (buffer[bytesConsumed] == MimeMultipartParser.Dash)
                    {
                        currentBodyPart.AppendBoundary(MimeMultipartParser.Dash);
                        bytesConsumed++;
                        
                        if (currentBodyPart.IsBoundaryComplete())
                        {
                            Debug.Assert(currentBodyPart.IsFinal);

                            // If we get in here, it means we've see the trailing '--' of the last boundary - in order to consume all of the 
                            // remaining bytes, we don't mark the parse as complete again - wait until this method is called again with the 
                            // empty buffer to do that.
                            bodyPartState = BodyPartState.AfterBoundary;
                            parseStatus = State.NeedMoreData;
                            goto quit;
                        }
                        else
                        {
                            currentBodyPart.ResetBoundary();
                            if (bytesConsumed == effectiveMax)
                            {
                                goto quit;
                            }

                            goto case BodyPartState.BodyPart;
                        }
                    }
                    else
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        goto case BodyPartState.BodyPart;
                    }

                case BodyPartState.AfterSecondCarriageReturn:
                    if (buffer[bytesConsumed] != MimeMultipartParser.LF)
                    {
                        currentBodyPart.ResetBoundary();
                        bodyPartState = BodyPartState.BodyPart;
                        goto case BodyPartState.BodyPart;
                    }

                    currentBodyPart.AppendBoundary(MimeMultipartParser.LF);
                    bytesConsumed++;

                    bodyPartState = BodyPartState.BodyPart;
                    if (currentBodyPart.IsBoundaryComplete())
                    {
                        parseStatus = State.BodyPartCompleted;
                        goto quit;
                    }
                    else
                    {
                        currentBodyPart.ResetBoundary();
                        if (bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case BodyPartState.BodyPart;
                    }
            }

        quit:
            if (initialBytesParsed < bytesConsumed)
            {
                int boundaryLength = currentBodyPart.BoundaryDelta;
                if (boundaryLength > 0 && parseStatus != State.BodyPartCompleted)
                {
                    currentBodyPart.HasPotentialBoundaryLeftOver = true;
                }

                int bodyPartEnd = bytesConsumed - initialBytesParsed - boundaryLength;

                currentBodyPart.BodyPart = new ArraySegment<byte>(buffer, initialBytesParsed, bodyPartEnd);
            }

            totalBytesConsumed += bytesConsumed - initialBytesParsed;
            return parseStatus;
        }