Ejemplo n.º 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="InternetMessageFormatHeaderParser"/> class.
        /// </summary>
        /// <param name="headers">
        /// Concrete <see cref="HttpHeaders"/> instance where header fields are added as they are parsed.
        /// </param>
        /// <param name="maxHeaderSize">
        /// Maximum length of complete header containing all the individual header fields.
        /// </param>
        /// <param name="ignoreHeaderValidation">
        /// Will validate content and names of headers if set to <c>false</c>.
        /// </param>
        public InternetMessageFormatHeaderParser(
            HttpHeaders headers,
            int maxHeaderSize,
            bool ignoreHeaderValidation
            )
        {
            // The minimum length which would be an empty header terminated by CRLF
            if (maxHeaderSize < InternetMessageFormatHeaderParser.MinHeaderSize)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo(
                          "maxHeaderSize",
                          maxHeaderSize,
                          MinHeaderSize
                          );
            }

            if (headers == null)
            {
                throw Error.ArgumentNull("headers");
            }

            _headers                = headers;
            _maxHeaderSize          = maxHeaderSize;
            _ignoreHeaderValidation = ignoreHeaderValidation;
            _currentHeader          = new CurrentHeaderFieldStore();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="InternetMessageFormatHeaderParser"/> class.
        /// </summary>
        /// <param name="headers">Concrete <see cref="HttpHeaders"/> instance where header fields are added as they are parsed.</param>
        /// <param name="maxHeaderSize">Maximum length of complete header containing all the individual header fields.</param>
        public InternetMessageFormatHeaderParser(HttpHeaders headers, int maxHeaderSize)
        {
            // The minimum length which would be an empty header terminated by CRLF
            if (maxHeaderSize < InternetMessageFormatHeaderParser.MinHeaderSize)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo("maxHeaderSize", maxHeaderSize, MinHeaderSize);
            }

            if (headers == null)
            {
                throw Error.ArgumentNull("headers");
            }

            _headers = headers;
            _maxHeaderSize = maxHeaderSize;
            _currentHeader = new CurrentHeaderFieldStore();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="InternetMessageFormatHeaderParser"/> class.
        /// </summary>
        /// <param name="headers">Concrete <see cref="HttpHeaders"/> instance where header fields are added as they are parsed.</param>
        /// <param name="maxHeaderSize">Maximum length of complete header containing all the individual header fields.</param>
        public InternetMessageFormatHeaderParser(HttpHeaders headers, int maxHeaderSize)
        {
            // The minimum length which would be an empty header terminated by CRLF
            if (maxHeaderSize < InternetMessageFormatHeaderParser.MinHeaderSize)
            {
                throw new ArgumentOutOfRangeException("maxHeaderSize", maxHeaderSize, RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, InternetMessageFormatHeaderParser.MinHeaderSize));
            }

            if (headers == null)
            {
                throw new ArgumentNullException("headers");
            }

            _headers = headers;
            _maxHeaderSize = maxHeaderSize;
            _currentHeader = new CurrentHeaderFieldStore();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="InternetMessageFormatHeaderParser"/> class.
        /// </summary>
        /// <param name="headers">Concrete <see cref="HttpHeaders"/> instance where header fields are added as they are parsed.</param>
        /// <param name="maxHeaderSize">Maximum length of complete header containing all the individual header fields.</param>
        public InternetMessageFormatHeaderParser(HttpHeaders headers, int maxHeaderSize)
        {
            // The minimum length which would be an empty header terminated by CRLF
            if (maxHeaderSize < InternetMessageFormatHeaderParser.MinHeaderSize)
            {
                throw new ArgumentOutOfRangeException("maxHeaderSize", maxHeaderSize, RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, InternetMessageFormatHeaderParser.MinHeaderSize));
            }

            if (headers == null)
            {
                throw new ArgumentNullException("headers");
            }

            _headers       = headers;
            _maxHeaderSize = maxHeaderSize;
            _currentHeader = new CurrentHeaderFieldStore();
        }
        private static ParserState ParseHeaderFields(
            byte[] buffer,
            int bytesReady,
            ref int bytesConsumed,
            ref HeaderFieldState requestHeaderState,
            int maximumHeaderLength,
            ref int totalBytesConsumed,
            CurrentHeaderFieldStore currentField,
            HttpHeaders headers)
        {
            Contract.Assert((bytesReady - bytesConsumed) >= 0, "ParseHeaderFields()|(inputBufferLength - bytesParsed) < 0");
            Contract.Assert(maximumHeaderLength <= 0 || totalBytesConsumed <= maximumHeaderLength, "ParseHeaderFields()|Headers already read exceeds limit.");

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

            // Set up parsing status with what will happen if we exceed the buffer.
            ParserState parseStatus = ParserState.DataTooBig;
            int effectiveMax = maximumHeaderLength <= 0 ? Int32.MaxValue : maximumHeaderLength - totalBytesConsumed + initialBytesParsed;
            if (bytesReady < effectiveMax)
            {
                parseStatus = ParserState.NeedMoreData;
                effectiveMax = bytesReady;
            }

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

            switch (requestHeaderState)
            {
                case HeaderFieldState.Name:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != ':')
                    {
                        if (buffer[bytesConsumed] == '\r')
                        {
                            if (!currentField.IsEmpty())
                            {
                                parseStatus = ParserState.Invalid;
                                goto quit;
                            }
                            else
                            {
                                // Move past the '\r'
                                requestHeaderState = HeaderFieldState.AfterCarriageReturn;
                                if (++bytesConsumed == effectiveMax)
                                {
                                    goto quit;
                                }

                                goto case HeaderFieldState.AfterCarriageReturn;
                            }
                        }

                        if (++bytesConsumed == effectiveMax)
                        {
                            string headerFieldName = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                            currentField.Name.Append(headerFieldName);
                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        string headerFieldName = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentField.Name.Append(headerFieldName);
                    }

                    // Move past the ':'
                    requestHeaderState = HeaderFieldState.Value;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HeaderFieldState.Value;

                case HeaderFieldState.Value:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != '\r')
                    {
                        if (++bytesConsumed == effectiveMax)
                        {
                            string headerFieldValue = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                            currentField.Value.Append(headerFieldValue);
                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        string headerFieldValue = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentField.Value.Append(headerFieldValue);
                    }

                    // Move past the CR
                    requestHeaderState = HeaderFieldState.AfterCarriageReturn;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HeaderFieldState.AfterCarriageReturn;

                case HeaderFieldState.AfterCarriageReturn:
                    if (buffer[bytesConsumed] != '\n')
                    {
                        parseStatus = ParserState.Invalid;
                        goto quit;
                    }

                    if (currentField.IsEmpty())
                    {
                        parseStatus = ParserState.Done;
                        bytesConsumed++;
                        goto quit;
                    }

                    requestHeaderState = HeaderFieldState.FoldingLine;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HeaderFieldState.FoldingLine;

                case HeaderFieldState.FoldingLine:
                    if (buffer[bytesConsumed] != ' ' && buffer[bytesConsumed] != '\t')
                    {
                        currentField.CopyTo(headers);
                        requestHeaderState = HeaderFieldState.Name;
                        if (bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case HeaderFieldState.Name;
                    }

                    // Unfold line by inserting SP instead
                    currentField.Value.Append(' ');

                    // Continue parsing header field value
                    requestHeaderState = HeaderFieldState.Value;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HeaderFieldState.Value;
            }

        quit:
            totalBytesConsumed += bytesConsumed - initialBytesParsed;
            return parseStatus;
        }
        private static ParserState ParseHeaderFields(
            byte[] buffer,
            int bytesReady,
            ref int bytesConsumed,
            ref HeaderFieldState requestHeaderState,
            int maximumHeaderLength,
            ref int totalBytesConsumed,
            CurrentHeaderFieldStore currentField,
            HttpHeaders headers)
        {
            Contract.Assert((bytesReady - bytesConsumed) >= 0, "ParseHeaderFields()|(inputBufferLength - bytesParsed) < 0");
            Contract.Assert(maximumHeaderLength <= 0 || totalBytesConsumed <= maximumHeaderLength, "ParseHeaderFields()|Headers already read exceeds limit.");

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

            // Set up parsing status with what will happen if we exceed the buffer.
            ParserState parseStatus  = ParserState.DataTooBig;
            int         effectiveMax = maximumHeaderLength <= 0 ? Int32.MaxValue : maximumHeaderLength - totalBytesConsumed + initialBytesParsed;

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

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

            switch (requestHeaderState)
            {
            case HeaderFieldState.Name:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != ':')
                {
                    if (buffer[bytesConsumed] == '\r')
                    {
                        if (!currentField.IsEmpty())
                        {
                            parseStatus = ParserState.Invalid;
                            goto quit;
                        }
                        else
                        {
                            // Move past the '\r'
                            requestHeaderState = HeaderFieldState.AfterCarriageReturn;
                            if (++bytesConsumed == effectiveMax)
                            {
                                goto quit;
                            }

                            goto case HeaderFieldState.AfterCarriageReturn;
                        }
                    }

                    if (++bytesConsumed == effectiveMax)
                    {
                        string headerFieldName = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentField.Name.Append(headerFieldName);
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    string headerFieldName = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                    currentField.Name.Append(headerFieldName);
                }

                // Move past the ':'
                requestHeaderState = HeaderFieldState.Value;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HeaderFieldState.Value;

            case HeaderFieldState.Value:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != '\r')
                {
                    if (++bytesConsumed == effectiveMax)
                    {
                        string headerFieldValue = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentField.Value.Append(headerFieldValue);
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    string headerFieldValue = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                    currentField.Value.Append(headerFieldValue);
                }

                // Move past the CR
                requestHeaderState = HeaderFieldState.AfterCarriageReturn;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HeaderFieldState.AfterCarriageReturn;

            case HeaderFieldState.AfterCarriageReturn:
                if (buffer[bytesConsumed] != '\n')
                {
                    parseStatus = ParserState.Invalid;
                    goto quit;
                }

                if (currentField.IsEmpty())
                {
                    parseStatus = ParserState.Done;
                    bytesConsumed++;
                    goto quit;
                }

                requestHeaderState = HeaderFieldState.FoldingLine;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HeaderFieldState.FoldingLine;

            case HeaderFieldState.FoldingLine:
                if (buffer[bytesConsumed] != ' ' && buffer[bytesConsumed] != '\t')
                {
                    currentField.CopyTo(headers);
                    requestHeaderState = HeaderFieldState.Name;
                    if (bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HeaderFieldState.Name;
                }

                // Unfold line by inserting SP instead
                currentField.Value.Append(' ');

                // Continue parsing header field value
                requestHeaderState = HeaderFieldState.Value;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HeaderFieldState.Value;
            }

quit:
            totalBytesConsumed += bytesConsumed - initialBytesParsed;
            return(parseStatus);
        }