Esempio n. 1
0
        // ParseHeaders -
        // Routine Description:
        //
        // This code is optimized for the case in which all the headers fit in the buffer.
        // we support multiple re-entrance, but we won't save intermediate
        // state, we will just roll back all the parsing done for the current header if we can't
        // parse a whole one (including multiline) or decide something else ("invalid data" or "done parsing").
        //
        // we're going to cycle through the loop until we
        //
        // 1) find an HTTP violation (in this case we return DataParseStatus.Invalid)
        // 2) we need more data (in this case we return DataParseStatus.NeedMoreData)
        // 3) we found the end of the headers and the beginning of the entity body (in this case we return DataParseStatus.Done)
        //
        //
        // Arguments:
        //
        // buffer - buffer containing the data to be parsed
        // size - size of the buffer
        // unparsed - offset of data yet to be parsed
        //
        // Return Value:
        //
        // DataParseStatus - status of parsing
        //
        // Revision:
        //
        // 02/13/2001 rewrote the method from scratch.
        //
        // BreakPoint:
        //
        // b system.dll!System.Net.WebHeaderCollection::ParseHeaders
        internal unsafe DataParseStatus ParseHeaders(byte[] buffer, int size, ref int unparsed, ref int totalResponseHeadersLength, int maximumResponseHeadersLength, ref WebParseError parseError)
        {
            fixed (byte* byteBuffer = buffer)
            {

                char ch;

                // quick check in the boundaries (as we use unsafe pointer)
                if (buffer.Length < size)
                {
                    return DataParseStatus.NeedMoreData;
                }

                int headerNameStartOffset = -1;
                int headerNameEndOffset = -1;
                int headerValueStartOffset = -1;
                int headerValueEndOffset = -1;
                int numberOfLf = -1;
                int index = unparsed;
                bool spaceAfterLf;
                string headerMultiLineValue;
                string headerName;
                string headerValue;

                // we need this because this method is entered multiple times.
                int localTotalResponseHeadersLength = totalResponseHeadersLength;

                WebParseErrorCode parseErrorCode = WebParseErrorCode.Generic;
                DataParseStatus parseStatus = DataParseStatus.Invalid;

                //
                // according to RFC216 a header can have the following syntax:
                //
                // message-header = field-name ":" [ field-value ]
                // field-name = token
                // field-value = *( field-content | LWS )
                // field-content = <the OCTETs making up the field-value and consisting of either *TEXT or combinations of token, separators, and quoted-string>
                // TEXT = <any OCTET except CTLs, but including LWS>
                // CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
                // SP = <US-ASCII SP, space (32)>
                // HT = <US-ASCII HT, horizontal-tab (9)>
                // CR = <US-ASCII CR, carriage return (13)>
                // LF = <US-ASCII LF, linefeed (10)>
                // LWS = [CR LF] 1*( SP | HT )
                // CHAR = <any US-ASCII character (octets 0 - 127)>
                // token = 1*<any CHAR except CTLs or separators>
                // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
                // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
                // qdtext = <any TEXT except <">>
                // quoted-pair = "\" CHAR
                //

                //
                // At each iteration of the following loop we expect to parse a single HTTP header entirely.
                //
                for (; ; )
                {
                    //
                    // trim leading whitespaces (LWS) just for extra robustness, in fact if there are leading white spaces then:
                    // 1) it could be that after the status line we might have spaces. handle this.
                    // 2) this should have been detected to be a multiline header so there'll be no spaces and we'll spend some time here.
                    //
                    headerName = string.Empty;
                    headerValue = string.Empty;
                    spaceAfterLf = false;
                    headerMultiLineValue = null;

                    if (Count == 0)
                    {
                        //
                        // so, restrict this extra trimming only on the first header line
                        //
                        while (index < size)
                        {
                            ch = (char)byteBuffer[index];
                            if (ch == ' ' || ch == '\t')
                            {
                                ++index;
                                if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                                {
                                    parseStatus = DataParseStatus.DataTooBig;
                                    goto quit;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }

                        if (index == size)
                        {
                            //
                            // we reached the end of the buffer. ask for more data.
                            //
                            parseStatus = DataParseStatus.NeedMoreData;
                            goto quit;
                        }
                    }

                    //
                    // what we have here is the beginning of a new header
                    //
                    headerNameStartOffset = index;

                    while (index < size)
                    {
                        ch = (char)byteBuffer[index];
                        if (ch != ':' && ch != '\n')
                        {
                            if (ch > ' ')
                            {
                                //
                                // if there's an illegal character we should return DataParseStatus.Invalid
                                // instead we choose to be flexible, try to trim it, but include it in the string
                                //
                                headerNameEndOffset = index;
                            }
                            ++index;
                            if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                            {
                                parseStatus = DataParseStatus.DataTooBig;
                                goto quit;
                            }
                        }
                        else
                        {
                            if (ch == ':')
                            {
                                ++index;
                                if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                                {
                                    parseStatus = DataParseStatus.DataTooBig;
                                    goto quit;
                                }
                            }
                            break;
                        }
                    }
                    if (index == size)
                    {
                        //
                        // we reached the end of the buffer. ask for more data.
                        //
                        parseStatus = DataParseStatus.NeedMoreData;
                        goto quit;
                    }
                startOfValue:

                    //
                    // skip all [' ','\t','\r','\n'] characters until HeaderValue starts
                    // if we didn't find any headers yet, we set numberOfLf to 1
                    // so that we take the '\n' from the status line into account
                    //

                    numberOfLf = (Count == 0 && headerNameEndOffset < 0) ? 1 : 0;
                    while (index < size && numberOfLf < 2)
                    {
                        ch = (char)byteBuffer[index];
                        if (ch <= ' ')
                        {
                            if (ch == '\n')
                            {
                                numberOfLf++;
                                // In this case, need to check for a space.
                                if (numberOfLf == 1)
                                {
                                    if (index + 1 == size)
                                    {
                                        //
                                        // we reached the end of the buffer. ask for more data.
                                        // need to be able to peek after the \n and see if there's some space.
                                        //
                                        parseStatus = DataParseStatus.NeedMoreData;
                                        goto quit;
                                    }
                                    spaceAfterLf = (char)byteBuffer[index + 1] == ' ' || (char)byteBuffer[index + 1] == '\t';
                                }
                            }
                            ++index;
                            if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                            {
                                parseStatus = DataParseStatus.DataTooBig;
                                goto quit;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (numberOfLf == 2 || (numberOfLf == 1 && !spaceAfterLf))
                    {
                        //
                        // if we've counted two '\n' we got at the end of the headers even if we're past the end of the buffer
                        // if we've counted one '\n' and the first character after that was a ' ' or a '\t'
                        // no matter if we found a ':' or not, treat this as an empty header name.
                        //
                        goto addHeader;
                    }
                    if (index == size)
                    {
                        //
                        // we reached the end of the buffer. ask for more data.
                        //
                        parseStatus = DataParseStatus.NeedMoreData;
                        goto quit;
                    }

                    headerValueStartOffset = index;

                    while (index < size)
                    {
                        ch = (char)byteBuffer[index];
                        if (ch != '\n')
                        {
                            if (ch > ' ')
                            {
                                headerValueEndOffset = index;
                            }
                            ++index;
                            if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                            {
                                parseStatus = DataParseStatus.DataTooBig;
                                goto quit;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (index == size)
                    {
                        //
                        // we reached the end of the buffer. ask for more data.
                        //
                        parseStatus = DataParseStatus.NeedMoreData;
                        goto quit;
                    }

                    //
                    // at this point we found either a '\n' or the end of the headers
                    // hence we are at the end of the Header Line. 4 options:
                    // 1) need more data
                    // 2) if we find two '\n' => end of headers
                    // 3) if we find one '\n' and a ' ' or a '\t' => multiline header
                    // 4) if we find one '\n' and a valid char => next header
                    //
                    numberOfLf = 0;
                    while (index < size && numberOfLf < 2)
                    {
                        ch = (char)byteBuffer[index];
                        if (ch == '\r' || ch == '\n')
                        {
                            if (ch == '\n')
                            {
                                numberOfLf++;
                            }
                            ++index;
                            if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                            {
                                parseStatus = DataParseStatus.DataTooBig;
                                goto quit;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (index == size && numberOfLf < 2)
                    {
                        //
                        // we reached the end of the buffer but not of the headers. ask for more data.
                        //
                        parseStatus = DataParseStatus.NeedMoreData;
                        goto quit;
                    }
                addHeader:

                    if (headerValueStartOffset >= 0 && headerValueStartOffset > headerNameEndOffset && headerValueEndOffset >= headerValueStartOffset)
                    {
                        //
                        // Encoding fastest way to build the UNICODE string off the byte[]
                        //
                        headerValue = HeaderEncoding.GetString(byteBuffer + headerValueStartOffset, headerValueEndOffset - headerValueStartOffset + 1);
                    }

                    //
                    // if we got here from the beginning of the for loop, headerMultiLineValue will be null
                    // otherwise it will contain the headerValue constructed for the multiline header
                    // add this line as well to it, separated by a single space
                    //
                    headerMultiLineValue = (headerMultiLineValue == null ? headerValue : headerMultiLineValue + " " + headerValue);

                    if (index < size && numberOfLf == 1)
                    {
                        ch = (char)byteBuffer[index];
                        if (ch == ' ' || ch == '\t')
                        {
                            //
                            // since we found only one Lf and the next header line begins with a Lws,
                            // this is the beginning of a multiline header.
                            // parse the next line into headerValue later it will be added to headerMultiLineValue
                            //
                            ++index;
                            if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                            {
                                parseStatus = DataParseStatus.DataTooBig;
                                goto quit;
                            }
                            goto startOfValue;
                        }
                    }

                    if (headerNameStartOffset >= 0 && headerNameEndOffset >= headerNameStartOffset)
                    {
                        //
                        // Encoding is the fastest way to build the UNICODE string off the byte[]
                        //
                        headerName = HeaderEncoding.GetString(byteBuffer + headerNameStartOffset, headerNameEndOffset - headerNameStartOffset + 1);
                    }

                    //
                    // now it's finally safe to add the header if we have a name for it
                    //
                    if (headerName.Length > 0)
                    {
                        //
                        // the base clasee will check for pre-existing headerValue and append
                        // it using commas as indicated in the RFC
                        //
                        GlobalLog.Print("WebHeaderCollection::ParseHeaders() calling AddInternal() key:[" + headerName + "], value:[" + headerMultiLineValue + "]");
                        AddInternal(headerName, headerMultiLineValue);
                    }

                    //
                    // and update unparsed
                    //
                    totalResponseHeadersLength = localTotalResponseHeadersLength;
                    unparsed = index;

                    if (numberOfLf == 2)
                    {
                        parseStatus = DataParseStatus.Done;
                        goto quit;
                    }

                }
            quit:
                // for (;;)
                GlobalLog.Leave("WebHeaderCollection::ParseHeaders() returning parseStatus:" + parseStatus.ToString());
                if (parseStatus == DataParseStatus.Invalid)
                {
                    parseError.Section = WebParseErrorSection.ResponseHeader;
                    parseError.Code = parseErrorCode;
                }

                return parseStatus;
            }
        }
Esempio n. 2
0
        internal unsafe DataParseStatus ParseHeadersStrict(byte[] buffer, int size, ref int unparsed, ref int totalResponseHeadersLength, int maximumResponseHeadersLength, ref WebParseError parseError)
        {
            GlobalLog.Enter("WebHeaderCollection::ParseHeadersStrict(): size:" + size.ToString() + ", unparsed:" + unparsed.ToString() + " buffer:[" + Encoding.ASCII.GetString(buffer, unparsed, Math.Min(256, size - unparsed)) + "]");

            WebParseErrorCode parseErrorCode = WebParseErrorCode.Generic;
            DataParseStatus parseStatus = DataParseStatus.Invalid;

            int i = unparsed;
            RfcChar ch;
            int effectiveSize = maximumResponseHeadersLength <= 0 ? Int32.MaxValue : maximumResponseHeadersLength - totalResponseHeadersLength + i;
            DataParseStatus sizeError = DataParseStatus.DataTooBig;
            if (size < effectiveSize)
            {
                effectiveSize = size;
                sizeError = DataParseStatus.NeedMoreData;
            }

            // Verify the size.
            if (i >= effectiveSize)
            {
                parseStatus = sizeError;
                goto quit;
            }

            fixed (byte* byteBuffer = buffer)
            {
                while (true)
                {
                    // If this is CRLF, actually we're done.
                    if (byteBuffer[i] == '\r')
                    {
                        if (++i == effectiveSize)
                        {
                            parseStatus = sizeError;
                            goto quit;
                        }

                        if (byteBuffer[i++] == '\n')
                        {
                            totalResponseHeadersLength += i - unparsed;
                            unparsed = i;
                            parseStatus = DataParseStatus.Done;
                            goto quit;
                        }

                        parseStatus = DataParseStatus.Invalid;
                        parseErrorCode = WebParseErrorCode.CrLfError;
                        goto quit;
                    }

                    // Find the header name; only regular characters allowed.
                    int iBeginName = i;
                    for (; i < effectiveSize && (ch = byteBuffer[i] > 127 ? RfcChar.High : RfcCharMap[byteBuffer[i]]) == RfcChar.Reg; i++)
                        ;
                    if (i == effectiveSize)
                    {
                        parseStatus = sizeError;
                        goto quit;
                    }
                    if (i == iBeginName)
                    {
                        parseStatus = DataParseStatus.Invalid;
                        parseErrorCode = WebParseErrorCode.InvalidHeaderName;
                        goto quit;
                    }

                    // Read to a colon.
                    int iEndName = i - 1;
                    int crlf = 0;
                    // 1 = cr, 2 = crlf
                    for (; i < effectiveSize && (ch = byteBuffer[i] > 127 ? RfcChar.High : RfcCharMap[byteBuffer[i]]) != RfcChar.Colon; i++)
                    {
                        switch (ch)
                        {
                            case RfcChar.WS:
                                if (crlf == 1)
                                {
                                    break;
                                }

                                crlf = 0;
                                continue;
                            case RfcChar.CR:

                                if (crlf == 0)
                                {
                                    crlf = 1;
                                    continue;
                                }

                                break;
                            case RfcChar.LF:

                                if (crlf == 1)
                                {
                                    crlf = 2;
                                    continue;
                                }

                                break;
                        }
                        parseStatus = DataParseStatus.Invalid;
                        parseErrorCode = WebParseErrorCode.CrLfError;
                        goto quit;
                    }
                    if (i == effectiveSize)
                    {
                        parseStatus = sizeError;
                        goto quit;
                    }
                    if (crlf != 0)
                    {
                        parseStatus = DataParseStatus.Invalid;
                        parseErrorCode = WebParseErrorCode.IncompleteHeaderLine;
                        goto quit;
                    }

                    // Skip the colon.
                    if (++i == effectiveSize)
                    {
                        parseStatus = sizeError;
                        goto quit;
                    }

                    // Read the value. crlf = 3 means in the whitespace after a CRLF
                    int iBeginValue = -1;
                    int iEndValue = -1;
                    StringBuilder valueAccumulator = null;
                    for (; i < effectiveSize && ((ch = byteBuffer[i] > 127 ? RfcChar.High : RfcCharMap[byteBuffer[i]]) == RfcChar.WS || crlf != 2); i++)
                    {
                        switch (ch)
                        {
                            case RfcChar.WS:
                                if (crlf == 1)
                                {
                                    break;
                                }

                                if (crlf == 2)
                                {
                                    crlf = 3;
                                }

                                continue;
                            case RfcChar.CR:

                                if (crlf == 0)
                                {
                                    crlf = 1;
                                    continue;
                                }

                                break;
                            case RfcChar.LF:

                                if (crlf == 1)
                                {
                                    crlf = 2;
                                    continue;
                                }

                                break;
                            case RfcChar.High:
                            case RfcChar.Colon:
                            case RfcChar.Delim:
                            case RfcChar.Reg:

                                if (crlf == 1)
                                {
                                    break;
                                }

                                if (crlf == 3)
                                {
                                    crlf = 0;
                                    if (iBeginValue != -1)
                                    {
                                        string s = HeaderEncoding.GetString(byteBuffer + iBeginValue, iEndValue - iBeginValue + 1);
                                        if (valueAccumulator == null)
                                        {
                                            valueAccumulator = new StringBuilder(s, s.Length * 5);
                                        }
                                        else
                                        {
                                            valueAccumulator.Append(" ");
                                            valueAccumulator.Append(s);
                                        }
                                    }
                                    iBeginValue = -1;
                                }

                                if (iBeginValue == -1)
                                {
                                    iBeginValue = i;
                                }

                                iEndValue = i;
                                continue;
                        }
                        parseStatus = DataParseStatus.Invalid;
                        parseErrorCode = WebParseErrorCode.CrLfError;
                        goto quit;
                    }
                    if (i == effectiveSize)
                    {
                        parseStatus = sizeError;
                        goto quit;
                    }

                    // Make the value.
                    string sValue = iBeginValue == -1 ? "" : HeaderEncoding.GetString(byteBuffer + iBeginValue, iEndValue - iBeginValue + 1);
                    if (valueAccumulator != null)
                    {
                        if (sValue.Length != 0)
                        {
                            valueAccumulator.Append(" ");
                            valueAccumulator.Append(sValue);
                        }
                        sValue = valueAccumulator.ToString();
                    }

                    // Make the name. See if it's a common header first.
                    string sName = null;
                    int headerNameLength = iEndName - iBeginName + 1;
                    if (m_CommonHeaders != null)
                    {
                        int iHeader = s_CommonHeaderHints[byteBuffer[iBeginName] & 31];
                        if (iHeader >= 0)
                        {
                            while (true)
                            {
                                string s = s_CommonHeaderNames[iHeader++];

                                // Not found if we get to a shorter header or one with a different first character.
                                if (s.Length < headerNameLength || CaseInsensitiveAscii.AsciiToLower[byteBuffer[iBeginName]] != CaseInsensitiveAscii.AsciiToLower[s[0]])
                                    break;

                                // Keep looking if the common header is too long.
                                if (s.Length > headerNameLength)
                                    continue;

                                int j;
                                byte* pBuffer = byteBuffer + iBeginName + 1;
                                for (j = 1; j < s.Length; j++)
                                {
                                    // Avoid the case-insensitive compare in the common case where they match.
                                    if (*(pBuffer++) != s[j] && CaseInsensitiveAscii.AsciiToLower[*(pBuffer - 1)] != CaseInsensitiveAscii.AsciiToLower[s[j]])
                                        break;
                                }
                                if (j == s.Length)
                                {
                                    // Set it to the appropriate index.
                                    m_NumCommonHeaders++;
                                    iHeader--;
                                    if (m_CommonHeaders[iHeader] == null)
                                    {
                                        m_CommonHeaders[iHeader] = sValue;
                                    }
                                    else
                                    {
                                        // Don't currently handle combining multiple header instances in the common header case.
                                        // Nothing to do but punt them all to the NameValueCollection.
                                        NormalizeCommonHeaders();
                                        AddInternalNotCommon(s, sValue);
                                    }

                                    sName = s;
                                    break;
                                }
                            }
                        }
                    }

                    // If it wasn't a common header, add it to the hash.
                    if (sName == null)
                    {
                        sName = HeaderEncoding.GetString(byteBuffer + iBeginName, headerNameLength);
                        AddInternalNotCommon(sName, sValue);
                    }

                    totalResponseHeadersLength += i - unparsed;
                    unparsed = i;
                }
            }
            quit:

            GlobalLog.Leave("WebHeaderCollection::ParseHeadersStrict() returning parseStatus:" + parseStatus.ToString());

            if (parseStatus == DataParseStatus.Invalid)
            {
                parseError.Section = WebParseErrorSection.ResponseHeader;
                parseError.Code = parseErrorCode;
            }

            return parseStatus;
        }
Esempio n. 3
0
 internal DataParseStatus ParseHeaders(byte[] byteBuffer, int size, ref int unparsed, ref int totalResponseHeadersLength, int maximumResponseHeadersLength, ref WebParseError parseError)
 {
     char ch;
     string str2;
     if (byteBuffer.Length < size)
     {
         return DataParseStatus.NeedMoreData;
     }
     int index = -1;
     int num2 = -1;
     int num3 = -1;
     int num4 = -1;
     int num5 = -1;
     int num6 = unparsed;
     int num7 = totalResponseHeadersLength;
     WebParseErrorCode generic = WebParseErrorCode.Generic;
     DataParseStatus invalid = DataParseStatus.Invalid;
 Label_0023:
     str2 = string.Empty;
     string str3 = string.Empty;
     bool flag = false;
     string str = null;
     if (this.Count == 0)
     {
         while (num6 < size)
         {
             ch = (char) byteBuffer[num6];
             if ((ch != ' ') && (ch != '\t'))
             {
                 break;
             }
             num6++;
             if ((maximumResponseHeadersLength >= 0) && (++num7 >= maximumResponseHeadersLength))
             {
                 invalid = DataParseStatus.DataTooBig;
                 goto Label_02E5;
             }
         }
         if (num6 == size)
         {
             invalid = DataParseStatus.NeedMoreData;
             goto Label_02E5;
         }
     }
     index = num6;
     while (num6 < size)
     {
         ch = (char) byteBuffer[num6];
         if ((ch != ':') && (ch != '\n'))
         {
             if (ch > ' ')
             {
                 num2 = num6;
             }
             num6++;
             if ((maximumResponseHeadersLength < 0) || (++num7 < maximumResponseHeadersLength))
             {
                 continue;
             }
             invalid = DataParseStatus.DataTooBig;
         }
         else
         {
             if (ch != ':')
             {
                 break;
             }
             num6++;
             if ((maximumResponseHeadersLength < 0) || (++num7 < maximumResponseHeadersLength))
             {
                 break;
             }
             invalid = DataParseStatus.DataTooBig;
         }
         goto Label_02E5;
     }
     if (num6 == size)
     {
         invalid = DataParseStatus.NeedMoreData;
         goto Label_02E5;
     }
 Label_00EF:;
     num5 = ((this.Count == 0) && (num2 < 0)) ? 1 : 0;
     while ((num6 < size) && (num5 < 2))
     {
         ch = (char) byteBuffer[num6];
         if (ch > ' ')
         {
             break;
         }
         if (ch == '\n')
         {
             num5++;
             if (num5 == 1)
             {
                 if ((num6 + 1) == size)
                 {
                     invalid = DataParseStatus.NeedMoreData;
                     goto Label_02E5;
                 }
                 flag = (byteBuffer[num6 + 1] == 32) || (byteBuffer[num6 + 1] == 9);
             }
         }
         num6++;
         if ((maximumResponseHeadersLength >= 0) && (++num7 >= maximumResponseHeadersLength))
         {
             invalid = DataParseStatus.DataTooBig;
             goto Label_02E5;
         }
     }
     if ((num5 != 2) && ((num5 != 1) || flag))
     {
         if (num6 == size)
         {
             invalid = DataParseStatus.NeedMoreData;
             goto Label_02E5;
         }
         num3 = num6;
         while (num6 < size)
         {
             ch = (char) byteBuffer[num6];
             if (ch == '\n')
             {
                 break;
             }
             if (ch > ' ')
             {
                 num4 = num6;
             }
             num6++;
             if ((maximumResponseHeadersLength >= 0) && (++num7 >= maximumResponseHeadersLength))
             {
                 invalid = DataParseStatus.DataTooBig;
                 goto Label_02E5;
             }
         }
         if (num6 == size)
         {
             invalid = DataParseStatus.NeedMoreData;
             goto Label_02E5;
         }
         num5 = 0;
         while ((num6 < size) && (num5 < 2))
         {
             ch = (char) byteBuffer[num6];
             if ((ch != '\r') && (ch != '\n'))
             {
                 break;
             }
             if (ch == '\n')
             {
                 num5++;
             }
             num6++;
             if ((maximumResponseHeadersLength >= 0) && (++num7 >= maximumResponseHeadersLength))
             {
                 invalid = DataParseStatus.DataTooBig;
                 goto Label_02E5;
             }
         }
         if ((num6 == size) && (num5 < 2))
         {
             invalid = DataParseStatus.NeedMoreData;
             goto Label_02E5;
         }
     }
     if (((num3 >= 0) && (num3 > num2)) && (num4 >= num3))
     {
         str3 = Encoding.UTF8.GetString(byteBuffer, num3, (num4 - num3) + 1);
     }
     str = (str == null) ? str3 : (str + " " + str3);
     if ((num6 < size) && (num5 == 1))
     {
         switch (((char) byteBuffer[num6]))
         {
             case ' ':
             case '\t':
                 num6++;
                 if ((maximumResponseHeadersLength < 0) || (++num7 < maximumResponseHeadersLength))
                 {
                     goto Label_00EF;
                 }
                 invalid = DataParseStatus.DataTooBig;
                 goto Label_02E5;
         }
     }
     if ((index >= 0) && (num2 >= index))
     {
         str2 = Encoding.UTF8.GetString(byteBuffer, index, (num2 - index) + 1);
     }
     if (str2.Length > 0)
     {
         this.Add(str2, str);
     }
     totalResponseHeadersLength = num7;
     unparsed = num6;
     if (num5 != 2)
     {
         goto Label_0023;
     }
     invalid = DataParseStatus.Done;
 Label_02E5:
     if (invalid == DataParseStatus.Invalid)
     {
         parseError.Section = WebParseErrorSection.ResponseHeader;
         parseError.Code = generic;
     }
     return invalid;
 }