/// <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); }