Beispiel #1
0
        protected virtual void Parse()
        {
            int             unparsed    = 0;
            DataParseStatus parseStatus = DataParseStatus.Invalid;

            try
            {
                // Step 1. Parse header [1/23/2004]
                parseStatus = _headers.ParseHeaders(_EMailBinaryData.GetBuffer(), (int)_EMailBinaryData.Length, ref unparsed);
                if (parseStatus == DataParseStatus.Done)
                {
                    // Step 2. Parse Messagy Body [1/23/2004]
                    parseStatus = _mimeEntries.ParseMimeEntries(_EMailBinaryData.GetBuffer(), (int)_EMailBinaryData.Length, ref unparsed, this.Headers);
                }
            }
            catch (Exception ex)
            {
                throw new Pop3ServerIncorectEMailFormatException("Internal Parser Error", ex);
            }

            if (parseStatus != DataParseStatus.Done)
            {
                throw new Pop3ServerIncorectEMailFormatException();
            }
        }
Beispiel #2
0
        private void ParseHeaders(string responseHeaders)
        {
            if (string.IsNullOrEmpty(responseHeaders))
            {
                return;
            }

            byte[]        buffer = System.Text.Encoding.UTF8.GetBytes(responseHeaders);
            WebParseError error  = new WebParseError();
            int           totalResponseHeadersLength = 0;
            int           offset          = 0;
            int           maxHeaderLength = 64000;

            try
            {
                DataParseStatus result = this.headers.ParseHeaders(buffer, buffer.Length, ref offset, ref totalResponseHeadersLength, maxHeaderLength, ref error);

                if (result != DataParseStatus.Done)
                {
                    throw WebException.CreateInternal("HttpWebResponse.ParseHeaders");
                }
            }
            catch (WebException)
            {
                throw;
            }
            catch (Exception e)
            {
                string message = System.Data.Services.Client.Strings.HttpWeb_Internal("HttpWebResponse.ParseHeaders.2");
                throw new WebException(message, e);
            }
        }
Beispiel #3
0
        private DataParseStatus ParsePayloadEnd()
        {
            Contract.Assert(currentChunkBytesRead == currentChunkLength);

            DataParseStatus crlfResult = ParseCRLF(ref bufferCurrentPos);

            if (crlfResult != DataParseStatus.ContinueParsing)
            {
                return(crlfResult);
            }

            currentChunkLength    = noChunkLength;
            currentChunkBytesRead = 0;

            readState = ReadState.ChunkLength;

            return(DataParseStatus.ContinueParsing);
        }
Beispiel #4
0
        private DataParseStatus ParseExtension()
        {
            int currentPos = bufferCurrentPos;

            // After the chunk length we can only have <space> or <tab> chars. A LWS with CRLF would be ambiguous since
            // CRLF also delimits the chunk length from chunk data.
            DataParseStatus result = ParseWhitespaces(ref currentPos);

            if (result != DataParseStatus.ContinueParsing)
            {
                return(result);
            }

            result = ParseExtensionNameValuePairs(ref currentPos);
            if (result != DataParseStatus.ContinueParsing)
            {
                return(result);
            }

            result = ParseCRLF(ref currentPos);
            if (result != DataParseStatus.ContinueParsing)
            {
                return(result);
            }

            bufferCurrentPos = currentPos;

            if (currentChunkLength == 0)
            {
                // zero-chunk read. We're done with the response. Consume trailer and complete.
                readState = ReadState.Trailer;
            }
            else
            {
                readState = ReadState.Payload;
            }

            return(DataParseStatus.ContinueParsing);
        }
Beispiel #5
0
        protected virtual void ParseHeaderAndBody()
        {
            DataParseStatus parseStatus = DataParseStatus.Invalid;

            try
            {
                // Step 1. Parse header [1/23/2004]
                parseStatus = _headers.ParseHeaders(_BinaryData.GetBuffer(), (int)_BinaryData.Length, ref _BodyOffset);
                if (parseStatus == DataParseStatus.Done)
                {
                    ParseBody();
                }
            }
            catch (Exception ex)
            {
                throw new Pop3ServerIncorectEMailFormatException("Internal Parser Error: " + ex.Message, ex);
            }

            if (parseStatus != DataParseStatus.Done)
            {
                throw new Pop3ServerIncorectEMailFormatException();
            }
        }
Beispiel #6
0
        protected virtual void ParseBody()
        {
            string strFullConentType = _headers["Content-Type"];

            if (strFullConentType == null)
            {
                strFullConentType = "";
            }

            //string strContentTypeValue	= null;

            Hashtable parametrs;

            MimeEntry.ParseHeader(strFullConentType, out _contentType, out parametrs);

            // Step 2. Parse Messagy Body [1/23/2004]
            if (!_contentType.StartsWith("multipart/"))
            {
                _charSet = (string)parametrs["charset"];

                if (_charSet == null)
                {
                    _charSet = Encoding.Default.HeaderName;
                }

                string ContentEncoding = _headers["Content-Transfer-Encoding"];

                if (ContentEncoding == null)
                {
                    ContentEncoding = "8bit";
                }

                string strDisposition = _headers["Content-Disposition"];

                if (strDisposition != null)
                {
                    Hashtable DispositionParameters;
                    string    DispositionType;
                    MimeEntry.ParseHeader(strDisposition, out DispositionType, out DispositionParameters);

                    DispositionType = DispositionType.ToLower();

                    if (DispositionType == "attachment")
                    {
                        this._disposition = Disposition.Attachment;
                    }
                    else if (DispositionType == "inline")
                    {
                        this._disposition = Disposition.Inline;
                    }

                    _fileName = (string)DispositionParameters["filename"];
                    if (_fileName != null)
                    {
                        _fileName = Rfc822HeaderCollection.DeocodeHeaderValue(_fileName);
                    }
                }

                //string BodyString = Encoding.Default.GetString(this._BinaryData.GetBuffer(),this._BodyOffset,(int)(this._BinaryData.Length  - this._BodyOffset));
                Encoding encoding = null;
                try
                {
                    encoding = Encoding.GetEncoding(CharSet);
                }
                catch
                {
                    encoding = Encoding.Default;
                }


                string BodyString = encoding.GetString(this._BinaryData.GetBuffer(), this._BodyOffset, (int)(this._BinaryData.Length - this._BodyOffset));

                //string BodyString = Encoding.ASCII.GetString(this._BinaryData.GetBuffer(),this._BodyOffset,(int)(this._BinaryData.Length  - this._BodyOffset));
                //string BodyString2 = Encoding.UTF8.GetString(this._BinaryData.GetBuffer(),this._BodyOffset,(int)(this._BinaryData.Length  - this._BodyOffset));

                switch (ContentEncoding.ToLower())
                {
                case "quoted-printable":
                    _body = encoding.GetBytes(MimeEntry.QDecode(encoding, BodyString));
                    break;

                case "7bit":
                    //_body = Encoding.ASCII.GetBytes(BodyString);
                    _body = encoding.GetBytes(BodyString);
                    break;

                default:
                case "8bit":
                    _body = encoding.GetBytes(BodyString);
                    break;

                case "base64":
                    BodyString = BodyString.Trim();

                    if (BodyString.Length > 0)
                    {
                        int base64FixCount = 0;

                        // Fix If Base 64 is broken
                        while (true)
                        {
                            try
                            {
                                _body = Convert.FromBase64String(BodyString);
                                break;
                            }
                            catch (System.FormatException)
                            {
                                // Remove not supported chars
                                if (base64FixCount == 0)
                                {
                                    BodyString = Regex.Replace(BodyString, "[^a-zA-Z0-9+/=]+", string.Empty);
                                }
                                else if (base64FixCount == 1)
                                {
                                    BodyString += "=";
                                }
                                else
                                {
                                    BodyString = BodyString.Substring(0, BodyString.Length - 1);
                                }

                                if (BodyString.Length == 0 || base64FixCount == 25)                                         // Max 25 Attempts to fix chars
                                {
                                    _body = new byte[] { };
                                    break;
                                }

                                base64FixCount++;
                            }
                        }
                    }
                    else
                    {
                        _body = new byte[] {}
                    };
                    break;

                case "binary":
                    _body = encoding.GetBytes(BodyString);
                    break;
                    //default:
                    //    throw new Pop3ServerIncorectEMailFormatException("Not supported content-encoding " + ContentEncoding + " !");
                }
            }
            else
            {
                DataParseStatus parseStatus = _mimeEntries.ParseMimeEntries(_BinaryData.GetBuffer(), (int)_BinaryData.Length, ref _BodyOffset, this.Headers);
            }
        }
Beispiel #7
0
        internal DataParseStatus ParseHeaders(
            byte[] byteBuffer,
            int size,
            ref int unparsed,
            ref int totalResponseHeadersLength,
            int maximumResponseHeadersLength,
            ref WebParseError parseError)
        {
            if (byteBuffer.Length < size)
            {
                return(DataParseStatus.NeedMoreData);
            }

            char   ch;
            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;

            int localTotalResponseHeadersLength = totalResponseHeadersLength;

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


            for (;;)
            {
                headerName           = string.Empty;
                headerValue          = string.Empty;
                spaceAfterLf         = false;
                headerMultiLineValue = null;

                if (this.Count == 0)
                {
                    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)
                    {
                        parseStatus = DataParseStatus.NeedMoreData;
                        goto quit;
                    }
                }

                headerNameStartOffset = index;

                while (index < size)
                {
                    ch = (char)byteBuffer[index];
                    if (ch != ':' && ch != '\n')
                    {
                        if (ch > ' ')
                        {
                            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)
                {
                    parseStatus = DataParseStatus.NeedMoreData;
                    goto quit;
                }

startOfValue:
                numberOfLf = (this.Count == 0 && headerNameEndOffset < 0) ? 1 : 0;
                while (index < size && numberOfLf < 2)
                {
                    ch = (char)byteBuffer[index];
                    if (ch <= ' ')
                    {
                        if (ch == '\n')
                        {
                            numberOfLf++;

                            if (numberOfLf == 1)
                            {
                                if (index + 1 == size)
                                {
                                    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))
                {
                    goto addHeader;
                }

                if (index == size)
                {
                    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)
                {
                    parseStatus = DataParseStatus.NeedMoreData;
                    goto quit;
                }

                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)
                {
                    parseStatus = DataParseStatus.NeedMoreData;
                    goto quit;
                }

addHeader:
                if (headerValueStartOffset >= 0 && headerValueStartOffset > headerNameEndOffset && headerValueEndOffset >= headerValueStartOffset)
                {
                    headerValue = System.Text.Encoding.UTF8.GetString(byteBuffer, headerValueStartOffset, headerValueEndOffset - headerValueStartOffset + 1);
                }

                headerMultiLineValue = (headerMultiLineValue == null ? headerValue : headerMultiLineValue + " " + headerValue);

                if (index < size && numberOfLf == 1)
                {
                    ch = (char)byteBuffer[index];
                    if (ch == ' ' || ch == '\t')
                    {
                        ++index;
                        if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                        {
                            parseStatus = DataParseStatus.DataTooBig;
                            goto quit;
                        }

                        goto startOfValue;
                    }
                }

                if (headerNameStartOffset >= 0 && headerNameEndOffset >= headerNameStartOffset)
                {
                    headerName = System.Text.Encoding.UTF8.GetString(byteBuffer, headerNameStartOffset, headerNameEndOffset - headerNameStartOffset + 1);
                }

                if (headerName.Length > 0)
                {
                    this.Add(headerName, headerMultiLineValue);
                }

                totalResponseHeadersLength = localTotalResponseHeadersLength;
                unparsed = index;

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

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

            return(parseStatus);
        }
        internal DataParseStatus ParseHeaders(byte[] buffer, int size, ref int unparsed, ref int totalResponseHeadersLength, int maximumResponseHeadersLength)
        {
            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;

            DataParseStatus parseStatus = DataParseStatus.Invalid;

            GlobalLog.Enter("WebHeaderCollection::ParseHeaders(): size:" + size.ToString() + ", unparsed:" + unparsed.ToString() + " buffer:[" + Encoding.ASCII.GetString(buffer, unparsed, Math.Min(256, size - unparsed)) + "]");
            //GlobalLog.Print("WebHeaderCollection::ParseHeaders(): advancing. index=" + index.ToString() + " current character='" + ((char)buffer[index]).ToString() + "':" + ((int)buffer[index]).ToString() + " next character='" + ((char)buffer[index+1]).ToString() + "':" + ((int)buffer[index+1]).ToString());
            //GlobalLog.Print("WebHeaderCollection::ParseHeaders(): headerName:[" + headerName + "], headerValue:[" + headerValue + "], headerMultiLineValue:[" + headerMultiLineValue + "] numberOfLf=" + numberOfLf.ToString() + " index=" + index.ToString());
            //GlobalLog.Print("WebHeaderCollection::ParseHeaders(): headerNameStartOffset=" + headerNameStartOffset + " headerNameEndOffset=" + headerNameEndOffset + " headerValueStartOffset=" + headerValueStartOffset + " headerValueEndOffset=" + headerValueEndOffset);

            //
            // 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 && (buffer[index] == ' ' || buffer[index] == '\t'))
                    {
                        index++;
                        if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                        {
                            parseStatus = DataParseStatus.DataTooBig;
                            goto quit;
                        }
                    }
                    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 && (buffer[index] != ':' && buffer[index] != '\n'))
                {
                    if (buffer[index] > ' ')
                    {
                        //
                        // if thre'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;
                    }
                }
                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 && (buffer[index] <= ' ' || buffer[index] == ':'))
                {
                    if (buffer[index] == '\n')
                    {
                        numberOfLf++;
                        spaceAfterLf = index + 1 < size && (buffer[index + 1] == ' ' || buffer[index + 1] == '\t');
                    }
                    index++;
                    if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                    {
                        parseStatus = DataParseStatus.DataTooBig;
                        goto quit;
                    }
                }
                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 && buffer[index] != '\n')
                {
                    if (buffer[index] > ' ')
                    {
                        headerValueEndOffset = index;
                    }
                    index++;
                    if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                    {
                        parseStatus = DataParseStatus.DataTooBig;
                        goto quit;
                    }
                }
                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 && (buffer[index] == '\r' || buffer[index] == '\n'))
                {
                    if (buffer[index] == '\n')
                    {
                        numberOfLf++;
                    }
                    index++;
                    if (maximumResponseHeadersLength >= 0 && ++localTotalResponseHeadersLength >= maximumResponseHeadersLength)
                    {
                        parseStatus = DataParseStatus.DataTooBig;
                        goto quit;
                    }
                }
                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(buffer, 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 && (buffer[index] == ' ' || buffer[index] == '\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(buffer, 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 base.Add() key:[" + headerName + "], value:[" + headerMultiLineValue + "]");
                    base.Add(headerName, headerMultiLineValue);
                }

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

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

quit:
            GlobalLog.Leave("WebHeaderCollection::ParseHeaders() returning parseStatus:" + parseStatus.ToString());
            return(parseStatus);
        }