internal static int GetValueLength(string input, int startIndex) { Debug.Assert(input != null); if (startIndex >= input.Length) { return(0); } int valueLength = HttpRuleParser.GetTokenLength(input, startIndex); if (valueLength == 0) { // A value can either be a token or a quoted string. Check if it is a quoted string. if (HttpRuleParser.GetQuotedStringLength(input, startIndex, out valueLength) != HttpParseResult.Parsed) { // We have an invalid value. Reset the name and return. return(0); } } return(valueLength); }
/// <summary> /// Initializes a new instance of the <see cref="EntityTagHeaderValue"/>. /// </summary> /// <param name="tag">A <see cref="StringSegment"/> that contains an <see cref="EntityTagHeaderValue"/>.</param> /// <param name="isWeak">A value that indicates if this entity-tag header is a weak validator.</param> public EntityTagHeaderValue(StringSegment tag, bool isWeak) { if (StringSegment.IsNullOrEmpty(tag)) { throw new ArgumentException("An empty string is not allowed.", nameof(tag)); } if (!isWeak && StringSegment.Equals(tag, "*", StringComparison.Ordinal)) { // * is valid, but W/* isn't. _tag = tag; } else if ((HttpRuleParser.GetQuotedStringLength(tag, 0, out var length) != HttpParseResult.Parsed) || (length != tag.Length)) { // Note that we don't allow 'W/' prefixes for weak ETags in the 'tag' parameter. If the user wants to // add a weak ETag, they can set 'isWeak' to true. throw new FormatException("Invalid ETag name"); } _tag = tag; _isWeak = isWeak; }
private static void CheckValueFormat(string?value) { // Either value is null/empty or a valid token/quoted string https://tools.ietf.org/html/rfc7230#section-3.2.6 if (string.IsNullOrEmpty(value)) { return; } // Trailing/leading space are not allowed if (value[0] == ' ' || value[0] == '\t' || value[^ 1] == ' ' || value[^ 1] == '\t') { throw new FormatException(SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_headers_invalid_value, value)); } // If it's not a token we check if it's a valid quoted string if (HttpRuleParser.GetTokenLength(value, 0) == 0) { HttpParseResult parseResult = HttpRuleParser.GetQuotedStringLength(value, 0, out int valueLength); if ((parseResult == HttpParseResult.Parsed && valueLength != value.Length) || parseResult != HttpParseResult.Parsed) { throw new FormatException(SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_headers_invalid_value, value)); } } }
internal static int GetEntityTagLength(string input, int startIndex, out EntityTagHeaderValue parsedValue) { Contract.Requires(startIndex >= 0); parsedValue = null; if (string.IsNullOrEmpty(input) || (startIndex >= input.Length)) { return(0); } // Caller must remove leading whitespaces. If not, we'll return 0. bool isWeak = false; int current = startIndex; char firstChar = input[startIndex]; if (firstChar == '*') { // We have '*' value, indicating "any" ETag. parsedValue = Any; current++; } else { // The RFC defines 'W/' as prefix, but we'll be flexible and also accept lower-case 'w'. if ((firstChar == 'W') || (firstChar == 'w')) { current++; // We need at least 3 more chars: the '/' character followed by two quotes. if ((current + 2 >= input.Length) || (input[current] != '/')) { return(0); } isWeak = true; current++; // we have a weak-entity tag. current = current + HttpRuleParser.GetWhitespaceLength(input, current); } int tagStartIndex = current; int tagLength = 0; if (HttpRuleParser.GetQuotedStringLength(input, current, out tagLength) != HttpParseResult.Parsed) { return(0); } parsedValue = new EntityTagHeaderValue(); if (tagLength == input.Length) { // Most of the time we'll have strong ETags without leading/trailing whitespaces. Debug.Assert(startIndex == 0); Debug.Assert(!isWeak); parsedValue._tag = input; parsedValue._isWeak = false; } else { parsedValue._tag = input.Substring(tagStartIndex, tagLength); parsedValue._isWeak = isWeak; } current = current + tagLength; } current = current + HttpRuleParser.GetWhitespaceLength(input, current); return(current - startIndex); }