public override bool TryParseValue(string value, object storeValue, ref int index, out object parsedValue)
        {
            parsedValue = null;

            // Some headers support empty/null values. This one doesn't.
            if (string.IsNullOrEmpty(value) || (index == value.Length))
            {
                return(false);
            }

            ReadOnlySpan <char> dateString = value;

            if (index > 0)
            {
                dateString = value.AsSpan(index);
            }

            DateTimeOffset date;

            if (!HttpDateParser.TryStringToDate(dateString, out date))
            {
                return(false);
            }

            index       = value.Length;
            parsedValue = date;
            return(true);
        }
        private static bool TryReadDate(string input, ref int current, out DateTimeOffset?date)
        {
            date = null;

            // Make sure we have at least one whitespace between <text> and <date> (if we have <date>)
            int whitespaceLength = HttpRuleParser.GetWhitespaceLength(input, current);

            current = current + whitespaceLength;

            // Read <date> in '<code> <agent> <text> ["<date>"]'
            if ((current < input.Length) && (input[current] == '"'))
            {
                if (whitespaceLength == 0)
                {
                    return(false); // we have characters after <text> but they were not separated by a whitespace
                }

                current++; // skip opening '"'

                // Find the closing '"'
                int dateStartIndex = current;
                while (current < input.Length)
                {
                    if (input[current] == '"')
                    {
                        break;
                    }
                    current++;
                }

                if ((current == input.Length) || (current == dateStartIndex))
                {
                    return(false); // we couldn't find the closing '"' or we have an empty quoted string.
                }

                DateTimeOffset temp;
                if (!HttpDateParser.TryStringToDate(input.Substring(dateStartIndex, current - dateStartIndex), out temp))
                {
                    return(false);
                }

                date = temp;

                current++; // skip closing '"'
                current = current + HttpRuleParser.GetWhitespaceLength(input, current);
            }

            return(true);
        }
Beispiel #3
0
        private DateTimeOffset?GetDate(string parameter)
        {
            NameValueHeaderValue valueHeaderValue = NameValueHeaderValue.Find(this._parameters, parameter);

            if (valueHeaderValue != null)
            {
                ReadOnlySpan <char> input = (ReadOnlySpan <char>)valueHeaderValue.Value;
                if (ContentDispositionHeaderValue.IsQuoted(input))
                {
                    input = input.Slice(1, input.Length - 2);
                }
                DateTimeOffset result;
                if (HttpDateParser.TryStringToDate(input, out result))
                {
                    return(new DateTimeOffset?(result));
                }
            }
            return(new DateTimeOffset?());
        }
Beispiel #4
0
        // Gets a parameter of the given name and attempts to extract a date.
        // Returns null if the parameter is not present or the format is incorrect.
        private DateTimeOffset?GetDate(string parameter)
        {
            NameValueHeaderValue dateParameter = NameValueHeaderValue.Find(_parameters, parameter);
            DateTimeOffset       date;

            if (dateParameter != null)
            {
                ReadOnlySpan <char> dateString = dateParameter.Value;
                // Should have quotes, remove them.
                if (IsQuoted(dateString))
                {
                    dateString = dateString.Slice(1, dateString.Length - 2);
                }
                if (HttpDateParser.TryStringToDate(dateString, out date))
                {
                    return(date);
                }
            }
            return(null);
        }
Beispiel #5
0
        internal static int GetRangeConditionLength(string input, int startIndex, out object parsedValue)
        {
            Debug.Assert(startIndex >= 0);

            parsedValue = null;

            // Make sure we have at least 2 characters
            if (string.IsNullOrEmpty(input) || (startIndex + 1 >= input.Length))
            {
                return(0);
            }

            int current = startIndex;

            // Caller must remove leading whitespace.
            DateTimeOffset       date      = DateTimeOffset.MinValue;
            EntityTagHeaderValue entityTag = null;

            // Entity tags are quoted strings optionally preceded by "W/". By looking at the first two character we
            // can determine whether the string is en entity tag or a date.
            char firstChar  = input[current];
            char secondChar = input[current + 1];

            if ((firstChar == '\"') || (((firstChar == 'w') || (firstChar == 'W')) && (secondChar == '/')))
            {
                // trailing whitespace is removed by GetEntityTagLength()
                int entityTagLength = EntityTagHeaderValue.GetEntityTagLength(input, current, out entityTag);

                if (entityTagLength == 0)
                {
                    return(0);
                }

                current = current + entityTagLength;

                // RangeConditionHeaderValue only allows 1 value. There must be no delimiter/other chars after an
                // entity tag.
                if (current != input.Length)
                {
                    return(0);
                }
            }
            else
            {
                if (!HttpDateParser.TryStringToDate(input.AsSpan(current), out date))
                {
                    return(0);
                }

                // If we got a valid date, then the parser consumed the whole string (incl. trailing whitespace).
                current = input.Length;
            }

            RangeConditionHeaderValue result = new RangeConditionHeaderValue();

            if (entityTag == null)
            {
                result._date = date;
            }
            else
            {
                result._entityTag = entityTag;
            }

            parsedValue = result;
            return(current - startIndex);
        }
Beispiel #6
0
        internal static int GetRetryConditionLength(string input, int startIndex, out object parsedValue)
        {
            Debug.Assert(startIndex >= 0);

            parsedValue = null;

            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
            {
                return(0);
            }

            int current = startIndex;

            // Caller must remove leading whitespace.
            DateTimeOffset date         = DateTimeOffset.MinValue;
            int            deltaSeconds = -1; // use -1 to indicate that the value was not set. 'delta' values are always >=0

            // We either have a timespan or a date/time value. Determine which one we have by looking at the first char.
            // If it is a number, we have a timespan, otherwise we assume we have a date.
            char firstChar = input[current];

            if ((firstChar >= '0') && (firstChar <= '9'))
            {
                int deltaStartIndex = current;
                int deltaLength     = HttpRuleParser.GetNumberLength(input, current, false);

                // The value must be in the range 0..2^31
                if ((deltaLength == 0) || (deltaLength > HttpRuleParser.MaxInt32Digits))
                {
                    return(0);
                }

                current = current + deltaLength;
                current = current + HttpRuleParser.GetWhitespaceLength(input, current);

                // RetryConditionHeaderValue only allows 1 value. There must be no delimiter/other chars after 'delta'
                if (current != input.Length)
                {
                    return(0);
                }

                if (!HeaderUtilities.TryParseInt32(input, deltaStartIndex, deltaLength, out deltaSeconds))
                {
                    return(0); // int.TryParse() may return 'false' if the value has 10 digits and is > Int32.MaxValue.
                }
            }
            else
            {
                if (!HttpDateParser.TryStringToDate(input.Substring(current), out date))
                {
                    return(0);
                }

                // If we got a valid date, then the parser consumed the whole string (incl. trailing whitespace).
                current = input.Length;
            }

            RetryConditionHeaderValue result = new RetryConditionHeaderValue();

            if (deltaSeconds == -1) // we didn't change delta, so we must have found a date.
            {
                result._date = date;
            }
            else
            {
                result._delta = new TimeSpan(0, 0, deltaSeconds);
            }

            parsedValue = result;
            return(current - startIndex);
        }
Beispiel #7
0
 public static void TryStringToDate_UseInvalidDateTimeString(string invalid)
 {
     Assert.False(HttpDateParser.TryStringToDate(",Sun, 06 Nov 1994 08:49:37 GMT", out var result));
 }
Beispiel #8
0
 // We don't need extensive tests, since we let DateTimeOffset do the parsing. This test is just
 // to validate that we use the correct parameters when calling into DateTimeOffset.ToString().
 public static void TryStringToDate_UseOfValidDateTimeStringsInDifferentFormats_ParsedCorrectly(string input, DateTimeOffset expected)
 {
     Assert.True(HttpDateParser.TryStringToDate(input, out var result));
     Assert.Equal(expected, result);
 }
Beispiel #9
0
 public static void TryStringToDate_UseInvalidDateTimeString(string invalid)
 {
     Assert.False(HttpDateParser.TryStringToDate(invalid, out var result));
     Assert.Equal(default, result);