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));
                }
            }
        }
Example #4
0
        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);
        }