/// <summary>
        /// Parses typed literals.
        /// </summary>
        /// <param name="expressionLexer">The expression lexer.</param>
        /// <param name="targetTypeReference">Expected type to be parsed.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static object ParseTypedLiteral(this ExpressionLexer expressionLexer, IEdmPrimitiveTypeReference targetTypeReference)
        {
            object targetValue;
            string reason;

            if (!UriPrimitiveTypeParser.TryUriStringToPrimitive(expressionLexer.CurrentToken.Text, targetTypeReference, out targetValue, out reason))
            {
                string message;

                if (reason == null)
                {
                    message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteral(
                        targetTypeReference.FullName(),
                        expressionLexer.CurrentToken.Text,
                        expressionLexer.CurrentToken.Position,
                        expressionLexer.ExpressionText);
                }
                else
                {
                    message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteralWithReason(
                        targetTypeReference.FullName(),
                        expressionLexer.CurrentToken.Text,
                        expressionLexer.CurrentToken.Position,
                        expressionLexer.ExpressionText,
                        reason);
                }

                throw new ODataException(message);
            }

            expressionLexer.NextToken();
            return(targetValue);
        }
Пример #2
0
        public void TryUriStringToPrimitiveWithValidDurationLiteralShouldReturnValidTimeSpan()
        {
            object output;

            UriPrimitiveTypeParser.TryUriStringToPrimitive("duration'P1D'", EdmCoreModel.Instance.GetDuration(false /*isNullable*/), out output).Should().BeTrue();
            output.ShouldBeEquivalentTo(new TimeSpan(1, 0, 0, 0));
        }
Пример #3
0
            /// <summary>
            /// Tries to remove formatting specific to this parser's expected type.
            /// </summary>
            /// <param name="text">The text to remove formatting from.</param>
            /// <returns>Whether or not the expected formatting was found and succesfully removed.</returns>
            internal virtual bool TryRemoveFormatting(ref string text)
            {
                if (this.prefix != null)
                {
                    if (!WebConvert.TryRemovePrefix(this.prefix, ref text))
                    {
                        return(false);
                    }
                }

                bool shouldBeQuoted = this.prefix != null || ValueOfTypeCanContainQuotes(this.expectedType);

                if (shouldBeQuoted && !WebConvert.TryRemoveQuotes(ref text))
                {
                    return(false);
                }

                if (this.suffix != null)
                {
                    // we need to try to remove the literal even if it isn't required.
                    if (!TryRemoveLiteralSuffix(this.suffix, ref text) && this.suffixRequired)
                    {
                        return(false);
                    }
                }

                return(true);
            }
Пример #4
0
        private static bool TryParse <T>(string input, IEdmPrimitiveTypeReference asType, out T realResult)
        {
            object result;
            bool   parseSuceeded = UriPrimitiveTypeParser.TryUriStringToPrimitive(input, asType, out result);

            realResult = (T)result;
            return(parseSuceeded);
        }
Пример #5
0
            /// <summary>
            /// Tries to remove formatting specific to this parser's expected type.
            /// </summary>
            /// <param name="text">The text to remove formatting from.</param>
            /// <returns>
            /// Whether or not the expected formatting was found and succesfully removed.
            /// </returns>
            internal override bool TryRemoveFormatting(ref string text)
            {
                if (!WebConvert.TryRemovePrefix(XmlConstants.LiteralPrefixBinary, ref text))
                {
                    return(false);
                }

                if (!WebConvert.TryRemoveQuotes(ref text))
                {
                    return(false);
                }

                return(true);
            }
Пример #6
0
        public void InvalidTimeOfDayShouldReturnFalse()
        {
            object output;
            var    list = new string[]
            {
                "1:5:20,0",
                "-20:3:40.900",
                "24:14:40.090"
            };

            foreach (var s in list)
            {
                UriPrimitiveTypeParser.TryUriStringToPrimitive(s, EdmCoreModel.Instance.GetTimeOfDay(true), out output).Should().BeFalse();
            }
        }
Пример #7
0
        /// <summary>Parses a token that starts with a digit.</summary>
        /// <returns>The kind of token recognized.</returns>
        private ExpressionTokenKind ParseFromDigit()
        {
            Debug.Assert(this.IsValidDigit || ('-' == this.ch), "this.IsValidDigit || ('-' == this.ch)");
            ExpressionTokenKind result;
            int  tokenPos  = this.textPos;
            char startChar = this.ch.Value;

            this.NextChar();
            if (startChar == '0' && (this.ch == 'x' || this.ch == 'X'))
            {
                result = ExpressionTokenKind.BinaryLiteral;
                do
                {
                    this.NextChar();
                }while (this.ch.HasValue && UriPrimitiveTypeParser.IsCharHexDigit(this.ch.Value));
            }
            else
            {
                result = ExpressionTokenKind.IntegerLiteral;
                while (this.IsValidDigit)
                {
                    this.NextChar();
                }

                // DateTimeOffset and Guids will have '-' in them
                if (this.ch == '-')
                {
                    if (this.TryParseDateTimeoffset(tokenPos))
                    {
                        return(ExpressionTokenKind.DateTimeOffsetLiteral);
                    }
                    else if (this.TryParseGuid(tokenPos))
                    {
                        return(ExpressionTokenKind.GuidLiteral);
                    }
                }

                // Guids will have alpha-numeric characters along with '-', so if a letter is encountered
                // try to see if this is Guid or not.
                if (this.ch.HasValue && Char.IsLetter(this.ch.Value))
                {
                    if (this.TryParseGuid(tokenPos))
                    {
                        return(ExpressionTokenKind.GuidLiteral);
                    }
                }

                if (this.ch == '.')
                {
                    result = ExpressionTokenKind.DoubleLiteral;
                    this.NextChar();
                    this.ValidateDigit();

                    do
                    {
                        this.NextChar();
                    }while (this.IsValidDigit);
                }

                if (this.ch == 'E' || this.ch == 'e')
                {
                    result = ExpressionTokenKind.DoubleLiteral;
                    this.NextChar();
                    if (this.ch == '+' || this.ch == '-')
                    {
                        this.NextChar();
                    }

                    this.ValidateDigit();
                    do
                    {
                        this.NextChar();
                    }while (this.IsValidDigit);
                }

                if (this.ch == 'M' || this.ch == 'm')
                {
                    result = ExpressionTokenKind.DecimalLiteral;
                    this.NextChar();
                }
                else if (this.ch == 'd' || this.ch == 'D')
                {
                    result = ExpressionTokenKind.DoubleLiteral;
                    this.NextChar();
                }
                else if (this.ch == 'L' || this.ch == 'l')
                {
                    result = ExpressionTokenKind.Int64Literal;
                    this.NextChar();
                }
                else if (this.ch == 'f' || this.ch == 'F')
                {
                    result = ExpressionTokenKind.SingleLiteral;
                    this.NextChar();
                }
                else
                {
                    string valueStr = this.Text.Substring(tokenPos, this.textPos - tokenPos);
                    result = MakeBestGuessOnNoSuffixStr(valueStr, result);
                }
            }

            return(result);
        }
Пример #8
0
        public void TryUriStringToPrimitiveWithOverflowingDurationLiteralShouldReturnFalse()
        {
            object output;

            UriPrimitiveTypeParser.TryUriStringToPrimitive("duration'P999999999D'", EdmCoreModel.Instance.GetDuration(false /*isNullable*/), out output).Should().BeFalse();
        }
Пример #9
0
        public void InvalidDateShouldReturnFalse()
        {
            object output;

            UriPrimitiveTypeParser.TryUriStringToPrimitive("-1000-00-01", EdmCoreModel.Instance.GetDate(true), out output).Should().BeFalse();
        }
Пример #10
0
        public void InvalidDateTimeOffsetShouldReturnFalse()
        {
            object output;

            UriPrimitiveTypeParser.TryUriStringToPrimitive("Ct >dvDTrz", EdmCoreModel.Instance.GetDateTimeOffset(true), out output).Should().BeFalse();
        }
Пример #11
0
        /// <summary>
        /// Parses the <paramref name="queryUri"/> and returns a new instance of <see cref="SyntacticTree"/>
        /// describing the query specified by the uri.
        /// </summary>
        /// <param name="queryUri">The absolute URI which holds the query to parse. This must be a path relative to the <paramref name="serviceBaseUri"/>.</param>
        /// <param name="serviceBaseUri">The base URI of the service.</param>
        /// <param name="maxDepth">The maximum depth of any single query part. Security setting to guard against DoS attacks causing stack overflows and such.</param>
        /// <returns>A new instance of <see cref="SyntacticTree"/> which represents the query specified in the <paramref name="queryUri"/>.</returns>
        public static SyntacticTree ParseUri(Uri queryUri, Uri serviceBaseUri, int maxDepth)
        {
            ExceptionUtils.CheckArgumentNotNull(queryUri, "queryUri");
            if (!queryUri.IsAbsoluteUri)
            {
                throw new ArgumentException(Strings.SyntacticTree_UriMustBeAbsolute(queryUri), "queryUri");
            }

            ExceptionUtils.CheckArgumentNotNull(serviceBaseUri, "serviceBaseUri");
            if (!serviceBaseUri.IsAbsoluteUri)
            {
                throw new ArgumentException(Strings.SyntacticTree_UriMustBeAbsolute(serviceBaseUri), "serviceBaseUri");
            }

            if (maxDepth <= 0)
            {
                throw new ArgumentException(Strings.SyntacticTree_MaxDepthInvalid, "maxDepth");
            }


            UriPathParser pathParser = new UriPathParser(maxDepth);
            var           path       = pathParser.ParsePathIntoSegments(queryUri, serviceBaseUri);

            // COMPAT 32: Differencies in query options parsing in WCF DS
            //
            // We allow non-system $ query options in the lexical space.
            // We allow multiple instances of a custom or non-system $ query option in the lexical space.
            // TODO: we need to decide whether we want to allow multiple system $ query options with the same name (OIPI suggests that this is valid); we currently don't.
            List <CustomQueryOptionToken> queryOptions     = UriUtils.ParseQueryOptions(queryUri);
            IDictionary <string, string>  parameterAliases = queryOptions.GetParameterAliases();

            QueryToken filter      = null;
            string     filterQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FilterQueryOption);

            if (filterQuery != null)
            {
                UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth);
                filter = expressionParser.ParseFilter(filterQuery);
            }

            IEnumerable <OrderByToken> orderByTokens = null;
            string orderByQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.OrderByQueryOption);

            if (orderByQuery != null)
            {
                UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth);
                orderByTokens = expressionParser.ParseOrderBy(orderByQuery);
            }

            SelectToken select      = null;
            string      selectQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SelectQueryOption);

            if (selectQuery != null)
            {
                SelectExpandParser selectParser = new SelectExpandParser(selectQuery, ODataUriParserSettings.DefaultSelectExpandLimit);
                select = selectParser.ParseSelect();
            }

            ExpandToken expand      = null;
            string      expandQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.ExpandQueryOption);

            if (expandQuery != null)
            {
                SelectExpandParser expandParser = new SelectExpandParser(expandQuery, ODataUriParserSettings.DefaultSelectExpandLimit);
                expand = expandParser.ParseExpand();
            }

            int?   skip      = null;
            string skipQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SkipQueryOption);

            if (skipQuery != null)
            {
                int skipValue;
                if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(skipQuery, out skipValue))
                {
                    throw new ODataException(Strings.SyntacticTree_InvalidSkipQueryOptionValue(skipQuery));
                }

                skip = skipValue;
            }

            int?   top      = null;
            string topQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.TopQueryOption);

            if (topQuery != null)
            {
                int topValue;
                if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(topQuery, out topValue))
                {
                    throw new ODataException(Strings.SyntacticTree_InvalidTopQueryOptionValue(topQuery));
                }

                top = topValue;
            }

            string countQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.CountQueryOption);
            bool?  count      = ParseQueryCount(countQuery);

            string format = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FormatQueryOption);

            return(new SyntacticTree(
                       parameterAliases,
                       path,
                       filter,
                       orderByTokens,
                       select,
                       expand,
                       skip,
                       top,
                       count,
                       format,
                       queryOptions.Count == 0 ? null : new ReadOnlyCollection <CustomQueryOptionToken>(queryOptions)));
        }
Пример #12
0
 /// <summary>
 /// Tries to remove formatting specific to this parser's expected type.
 /// </summary>
 /// <param name="text">The text to remove formatting from.</param>
 /// <returns>
 /// Whether or not the expected formatting was found and succesfully removed.
 /// </returns>
 internal override bool TryRemoveFormatting(ref string text)
 {
     return(WebConvert.TryRemoveQuotes(ref text));
 }
Пример #13
0
        /// <summary>
        /// Parses the <paramref name="queryUri"/> and returns a new instance of <see cref="SyntacticTree"/>
        /// describing the query specified by the uri.
        /// </summary>
        /// <param name="queryUri">The absolute URI which holds the query to parse. This must be a path relative to the <paramref name="serviceBaseUri"/>.</param>
        /// <param name="serviceBaseUri">The base URI of the service.</param>
        /// <param name="maxDepth">The maximum depth of any single query part. Security setting to guard against DoS attacks causing stack overflows and such.</param>
        /// <returns>A new instance of <see cref="SyntacticTree"/> which represents the query specified in the <paramref name="queryUri"/>.</returns>
        public static SyntacticTree ParseUri(Uri queryUri, Uri serviceBaseUri, int maxDepth)
        {
            ExceptionUtils.CheckArgumentNotNull(queryUri, "queryUri");
            if (!queryUri.IsAbsoluteUri)
            {
                throw new ArgumentException(Strings.SyntacticTree_UriMustBeAbsolute(queryUri), "queryUri");
            }

            ExceptionUtils.CheckArgumentNotNull(serviceBaseUri, "serviceBaseUri");
            if (!serviceBaseUri.IsAbsoluteUri)
            {
                throw new ArgumentException(Strings.SyntacticTree_UriMustBeAbsolute(serviceBaseUri), "serviceBaseUri");
            }

            if (maxDepth <= 0)
            {
                throw new ArgumentException(Strings.SyntacticTree_MaxDepthInvalid, "maxDepth");
            }


            UriPathParser pathParser = new UriPathParser(maxDepth);
            var           path       = pathParser.ParsePathIntoSegments(queryUri, serviceBaseUri);

            List <CustomQueryOptionToken> queryOptions     = UriUtils.ParseQueryOptions(queryUri);
            IDictionary <string, string>  parameterAliases = queryOptions.GetParameterAliases();

            QueryToken filter      = null;
            string     filterQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FilterQueryOption);

            if (filterQuery != null)
            {
                UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth);
                filter = expressionParser.ParseFilter(filterQuery);
            }

            IEnumerable <OrderByToken> orderByTokens = null;
            string orderByQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.OrderByQueryOption);

            if (orderByQuery != null)
            {
                UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth);
                orderByTokens = expressionParser.ParseOrderBy(orderByQuery);
            }

            SelectToken select      = null;
            string      selectQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SelectQueryOption);

            if (selectQuery != null)
            {
                SelectExpandParser selectParser = new SelectExpandParser(selectQuery, ODataUriParserSettings.DefaultSelectExpandLimit);
                select = selectParser.ParseSelect();
            }

            ExpandToken expand      = null;
            string      expandQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.ExpandQueryOption);

            if (expandQuery != null)
            {
                SelectExpandParser expandParser = new SelectExpandParser(expandQuery, ODataUriParserSettings.DefaultSelectExpandLimit);
                expand = expandParser.ParseExpand();
            }

            int?   skip      = null;
            string skipQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SkipQueryOption);

            if (skipQuery != null)
            {
                int skipValue;
                if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(skipQuery, out skipValue))
                {
                    throw new ODataException(Strings.SyntacticTree_InvalidSkipQueryOptionValue(skipQuery));
                }

                skip = skipValue;
            }

            int?   top      = null;
            string topQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.TopQueryOption);

            if (topQuery != null)
            {
                int topValue;
                if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(topQuery, out topValue))
                {
                    throw new ODataException(Strings.SyntacticTree_InvalidTopQueryOptionValue(topQuery));
                }

                top = topValue;
            }

            string countQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.CountQueryOption);
            bool?  count      = QueryTokenUtils.ParseQueryCount(countQuery);

            string format = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FormatQueryOption);

            return(new SyntacticTree(
                       parameterAliases,
                       path,
                       filter,
                       orderByTokens,
                       select,
                       expand,
                       skip,
                       top,
                       count,
                       format,
                       queryOptions.Count == 0 ? null : new ReadOnlyCollection <CustomQueryOptionToken>(queryOptions)));
        }