public void EqualMatchesEntireSubstring()
 {
     var segment = new StringSegment("abcdefghij", 2, 6);
     segment.Equals("cdefgh", StringComparison.Ordinal).ShouldBe(true);
     segment.Equals("cdefg", StringComparison.Ordinal).ShouldBe(false);
     segment.Equals("cdefghi", StringComparison.Ordinal).ShouldBe(false);
     segment.Equals("cDefgh", StringComparison.Ordinal).ShouldBe(false);
     segment.Equals("cDefgh", StringComparison.OrdinalIgnoreCase).ShouldBe(true);
 }
Пример #2
0
 /// <summary>
 /// Gets a value indicating whether the string has the specified property.
 /// </summary>
 /// <param name="prop">The name of the property to evaluate.</param>
 /// <returns><c>true</c> if the string has the specified property; otherwise, <c>false</c>.</returns>
 public Boolean HasPropertyRef(ref StringSegment prop)
 {
     foreach (var kvp in properties)
     {
         if (prop.Equals(kvp.Key))
         {
             return true;
         }
     }
     return false;
 }
Пример #3
0
    /// <summary>
    /// Compares against another <see cref="EntityTagHeaderValue"/> to see if they match under the RFC specifications (https://tools.ietf.org/html/rfc7232#section-2.3.2).
    /// </summary>
    /// <param name="other">The other <see cref="EntityTagHeaderValue"/> to compare against.</param>
    /// <param name="useStrongComparison"><c>true</c> to use a strong comparison, <c>false</c> to use a weak comparison</param>
    /// <returns>
    /// <c>true</c> if the <see cref="EntityTagHeaderValue"/> match for the given comparison type,
    /// <c>false</c> if the other value is null or the comparison failed.
    /// </returns>
    public bool Compare(EntityTagHeaderValue?other, bool useStrongComparison)
    {
        if (other == null)
        {
            return(false);
        }

        if (useStrongComparison)
        {
            return(!IsWeak && !other.IsWeak && StringSegment.Equals(Tag, other.Tag, StringComparison.Ordinal));
        }
        else
        {
            return(StringSegment.Equals(Tag, other.Tag, StringComparison.Ordinal));
        }
    }
Пример #4
0
        // Header contains a comma-separated collection of key / value pairs. Get all values for the "v1" key.
        private IEnumerable <StringSegment> GetSignatures(string header)
        {
            var pairs = new TrimmingTokenizer(header, CommaSeparator);

            foreach (var pair in pairs)
            {
                var keyValuePair = new TrimmingTokenizer(pair, EqualSeparator, maxCount: 2);
                var enumerator   = keyValuePair.GetEnumerator();
                enumerator.MoveNext();
                if (StringSegment.Equals(enumerator.Current, StripeConstants.SignatureKey, StringComparison.Ordinal))
                {
                    enumerator.MoveNext();
                    yield return(enumerator.Current);
                }
            }
        }
Пример #5
0
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            IList <MediaTypeHeaderValue> acceptHeaders = context.HttpContext.Request.GetTypedHeaders().Accept;

            bool acceptable = false;

            // Validate the accept headers has one of the specified accepted media types.
            if (acceptHeaders != null && acceptHeaders.Count > 0)
            {
                foreach (MediaTypeHeaderValue acceptHeader in acceptHeaders)
                {
                    if (_allowMultiple && StringSegment.Equals(acceptHeader.MediaType, KnownContentTypes.MultipartRelated, StringComparison.InvariantCultureIgnoreCase))
                    {
                        NameValueHeaderValue typeParameterValue = acceptHeader.Parameters.FirstOrDefault(
                            parameter => StringSegment.Equals(parameter.Name, TypeParameter, StringComparison.InvariantCultureIgnoreCase));

                        if (typeParameterValue != null &&
                            MediaTypeHeaderValue.TryParse(HeaderUtilities.RemoveQuotes(typeParameterValue.Value), out MediaTypeHeaderValue parsedValue) &&
                            _mediaTypes.Contains(parsedValue))
                        {
                            acceptable = true;
                            break;
                        }
                    }

                    if (_allowSingle)
                    {
                        string[]      split         = acceptHeader.ToString().Split(';');
                        List <string> stringHeaders = _mediaTypes.Select(x => x.ToString()).ToList();
                        if (split.Any(x => stringHeaders.Contains(x, StringComparer.InvariantCultureIgnoreCase)))
                        {
                            acceptable = true;
                            break;
                        }
                    }
                }
            }

            if (!acceptable)
            {
                context.Result = new StatusCodeResult(NotAcceptableResponseCode);
            }

            base.OnActionExecuting(context);
        }
        private static CultureInfo GetCultureInfo(StringSegment name, IList <CultureInfo> supportedCultures)
        {
            // Allow only known culture names as this API is called with input from users (HTTP requests) and
            // creating CultureInfo objects is expensive and we don't want it to throw either.
            if (name == null || supportedCultures == null)
            {
                return(null);
            }
            var culture = supportedCultures.FirstOrDefault(
                supportedCulture => StringSegment.Equals(supportedCulture.Name, name, StringComparison.OrdinalIgnoreCase));

            if (culture == null)
            {
                return(null);
            }

            return(CultureInfo.ReadOnly(culture));
        }
        // Header contains a comma-separated collection of key / value pairs. Get the value for the "t" key.
        private StringSegment GetTimestamp(string header)
        {
            var pairs = new TrimmingTokenizer(header, CommaSeparator);

            foreach (var pair in pairs)
            {
                var keyValuePair = new TrimmingTokenizer(pair, EqualSeparator, maxCount: 2);
                var enumerator   = keyValuePair.GetEnumerator();
                enumerator.MoveNext();
                if (StringSegment.Equals(enumerator.Current, StripeConstants.TimestampKey, StringComparison.Ordinal))
                {
                    enumerator.MoveNext();
                    return(enumerator.Current);
                }
            }

            return(StringSegment.Empty);
        }
Пример #8
0
        /// <inheritdoc />
        public virtual ICompressionProvider GetCompressionProvider(HttpContext context)
        {
            IList <StringWithQualityHeaderValue> unsorted;

            // e.g. Accept-Encoding: gzip, deflate, sdch
            var accept = context.Request.Headers[HeaderNames.AcceptEncoding];

            if (!StringValues.IsNullOrEmpty(accept) &&
                StringWithQualityHeaderValue.TryParseList(accept, out unsorted) &&
                unsorted != null && unsorted.Count > 0)
            {
                // TODO PERF: clients don't usually include quality values so this sort will not have any effect. Fast-path?
                var sorted = unsorted
                             .Where(s => s.Quality.GetValueOrDefault(1) > 0)
                             .OrderByDescending(s => s.Quality.GetValueOrDefault(1));

                foreach (var encoding in sorted)
                {
                    // There will rarely be more than three providers, and there's only one by default
                    foreach (var provider in _providers)
                    {
                        if (StringSegment.Equals(provider.EncodingName, encoding.Value, StringComparison.OrdinalIgnoreCase))
                        {
                            return(provider);
                        }
                    }

                    // Uncommon but valid options
                    if (StringSegment.Equals("*", encoding.Value, StringComparison.Ordinal))
                    {
                        // Any
                        return(_providers[0]);
                    }
                    if (StringSegment.Equals("identity", encoding.Value, StringComparison.OrdinalIgnoreCase))
                    {
                        // No compression
                        return(null);
                    }
                }
            }

            return(null);
        }
        public override bool Equals(object obj)
        {
            var other = obj as SetCookieHeaderValue;

            if (other == null)
            {
                return(false);
            }

            return(StringSegment.Equals(_name, other._name, StringComparison.OrdinalIgnoreCase) &&
                   StringSegment.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase) &&
                   Expires.Equals(other.Expires) &&
                   MaxAge.Equals(other.MaxAge) &&
                   StringSegment.Equals(Domain, other.Domain, StringComparison.OrdinalIgnoreCase) &&
                   StringSegment.Equals(Path, other.Path, StringComparison.OrdinalIgnoreCase) &&
                   Secure == other.Secure &&
                   SameSite == other.SameSite &&
                   HttpOnly == other.HttpOnly);
        }
        private static Encoding?GetEncodingFromCharset(StringSegment charset)
        {
            if (charset.Equals("utf-8", StringComparison.OrdinalIgnoreCase))
            {
                // This is an optimization for utf-8 that prevents the Substring caused by
                // charset.Value
                return(Encoding.UTF8);
            }

            try
            {
                // charset.Value might be an invalid encoding name as in charset=invalid.
                return(charset.HasValue ? Encoding.GetEncoding(charset.Value) : null);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"Unable to read the request as JSON because the request content type charset '{charset}' is not a known encoding.", ex);
            }
        }
Пример #11
0
        public RavenConfiguration CreateDatabaseConfiguration(StringSegment databaseName, bool ignoreDisabledDatabase = false)
        {
            if (databaseName.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(databaseName), "Database name cannot be empty");
            }
            if (databaseName.Equals("<system>")) // This is here to guard against old ravendb tests
            {
                throw new ArgumentNullException(nameof(databaseName), "Database name cannot be <system>. Using of <system> database indicates outdated code that was targeted RavenDB 3.5.");
            }

            var document = GetDatabaseDocument(databaseName, ignoreDisabledDatabase);

            if (document == null)
            {
                return(null);
            }

            return(CreateConfiguration(databaseName, document, RavenConfiguration.GetKey(x => x.Core.DataDirectory)));
        }
        /// <summary>
        /// Compares two <see cref="StringWithQualityHeaderValue"/> based on their quality value
        /// (a.k.a their "q-value").
        /// Values with identical q-values are considered equal (i.e the result is 0) with the exception of wild-card
        /// values (i.e. a value of "*") which are considered less than non-wild-card values. This allows to sort
        /// a sequence of <see cref="StringWithQualityHeaderValue"/> following their q-values ending up with any
        /// wild-cards at the end.
        /// </summary>
        /// <param name="stringWithQuality1">The first value to compare.</param>
        /// <param name="stringWithQuality2">The second value to compare</param>
        /// <returns>The result of the comparison.</returns>
        public int Compare(
            StringWithQualityHeaderValue stringWithQuality1,
            StringWithQualityHeaderValue stringWithQuality2)
        {
            if (stringWithQuality1 == null)
            {
                throw new ArgumentNullException(nameof(stringWithQuality1));
            }

            if (stringWithQuality2 == null)
            {
                throw new ArgumentNullException(nameof(stringWithQuality2));
            }

            var quality1          = stringWithQuality1.Quality ?? HeaderQuality.Match;
            var quality2          = stringWithQuality2.Quality ?? HeaderQuality.Match;
            var qualityDifference = quality1 - quality2;

            if (qualityDifference < 0)
            {
                return(-1);
            }
            else if (qualityDifference > 0)
            {
                return(1);
            }

            if (!StringSegment.Equals(stringWithQuality1.Value, stringWithQuality2.Value, StringComparison.OrdinalIgnoreCase))
            {
                if (StringSegment.Equals(stringWithQuality1.Value, "*", StringComparison.Ordinal))
                {
                    return(-1);
                }
                else if (StringSegment.Equals(stringWithQuality2.Value, "*", StringComparison.Ordinal))
                {
                    return(1);
                }
            }

            return(0);
        }
Пример #13
0
        public static void UseErrorLocalization(this IApplicationBuilder app)
        {
            var supportedCultures   = new[] { "en-US", "zh-CN" };
            var localizationOptions = new RequestLocalizationOptions().SetDefaultCulture(supportedCultures[0])
                                      .AddSupportedCultures(supportedCultures)
                                      .AddSupportedUICultures(supportedCultures);

            // Use official request localization
            app.UseRequestLocalization(localizationOptions);

            // Custom language process
            app.Use(async(context, next) =>
            {
                context.Request.Query.TryGetValue("lang", out StringValues queryLanguages);
                context.Request.Headers.TryGetValue("language", out StringValues languages);

                string language = null;

                if (queryLanguages.Count > 0)
                {
                    language = queryLanguages.Last();
                }
                else if (languages.Count > 0)
                {
                    language = languages.Last();
                }

                if (!string.IsNullOrEmpty(language))
                {
                    var culture = localizationOptions.SupportedCultures.FirstOrDefault(
                        supportedCulture => StringSegment.Equals(supportedCulture.Name, language, StringComparison.OrdinalIgnoreCase));
                    if (culture != null)
                    {
                        CultureInfo.CurrentCulture   = culture;
                        CultureInfo.CurrentUICulture = culture;
                    }
                }

                await next.Invoke();
            });
        }
        public override ICompressionProvider GetCompressionProvider(HttpContext context)
        {
            // e.g. Accept-Encoding: gzip, deflate, sdch
            var accept = context.Request.Headers[HeaderNames.AcceptEncoding];

            if (!StringValues.IsNullOrEmpty(accept) &&
                StringWithQualityHeaderValue.TryParseList(accept, out var unsorted) &&
                unsorted != null && unsorted.Count > 0)
            {
                foreach (var provider in _providers)
                {
                    if (unsorted.Any(
                            x => StringSegment.Equals(provider.EncodingName, x.Value, StringComparison.Ordinal)))
                    {
                        return(provider);
                    }
                }
            }

            return(base.GetCompressionProvider(context));
        }
Пример #15
0
    private static Encoding?GetEncodingFromCharset(StringSegment charset)
    {
        if (charset.Equals("utf-8", StringComparison.OrdinalIgnoreCase))
        {
            // This is an optimization for utf-8 that prevents the Substring caused by
            // charset.Value
            return(Encoding.UTF8);
        }

        try
        {
            // charset.Value might be an invalid encoding name as in charset=invalid.
            // For that reason, we catch the exception thrown by Encoding.GetEncoding
            // and return null instead.
            return(charset.HasValue ? Encoding.GetEncoding(charset.Value) : null);
        }
        catch (Exception)
        {
            return(null);
        }
    }
    public static bool SatisfiesTagName(StringSegment tagNameWithoutPrefix, TagMatchingRuleDescriptor rule)
    {
        if (StringSegment.IsNullOrEmpty(tagNameWithoutPrefix))
        {
            return(false);
        }

        if (tagNameWithoutPrefix[0] == ElementOptOutCharacter)
        {
            // TagHelpers can never satisfy tag names that are prefixed with the opt-out character.
            return(false);
        }

        if (rule.TagName != ElementCatchAllName &&
            rule.TagName != null &&
            !tagNameWithoutPrefix.Equals(rule.TagName, rule.CaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))
        {
            return(false);
        }

        return(true);
    }
Пример #17
0
        public RavenConfiguration CreateDatabaseConfiguration(StringSegment databaseName, bool ignoreDisabledDatabase = false, bool ignoreBeenDeleted = false, bool ignoreNotRelevant = false)
        {
            if (databaseName.Trim().Length == 0)
            {
                throw new ArgumentNullException(nameof(databaseName), "Database name cannot be empty");
            }
            if (databaseName.Equals("<system>")) // This is here to guard against old ravendb tests
            {
                throw new ArgumentNullException(nameof(databaseName),
                                                "Database name cannot be <system>. Using of <system> database indicates outdated code that was targeted RavenDB 3.5.");
            }

            Debug.Assert(_serverStore.Disposed == false);

            using (_serverStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
            {
                context.OpenReadTransaction();

                var doc = _serverStore.Cluster.Read(context, "db/" + databaseName.Value.ToLowerInvariant());
                if (doc == null)
                {
                    return(null);
                }

                var databaseRecord = JsonDeserializationCluster.DatabaseRecord(doc);

                if (databaseRecord.Encrypted)
                {
                    if (_serverStore.Server.WebUrl?.StartsWith("https:", StringComparison.OrdinalIgnoreCase) == false)
                    {
                        throw new DatabaseDisabledException(
                                  $"The database {databaseName.Value} is encrypted, and must be accessed only via HTTPS, but the web url used is {_serverStore.Server.WebUrl}");
                    }
                }

                return(CreateDatabaseConfiguration(databaseName, ignoreDisabledDatabase, ignoreBeenDeleted, ignoreNotRelevant, databaseRecord));
            }
        }
Пример #18
0
    private void NegotiateEncoding(HttpContext context)
    {
        var accept = context.Request.Headers.AcceptEncoding;

        if (StringValues.IsNullOrEmpty(accept))
        {
            return;
        }

        if (!StringWithQualityHeaderValue.TryParseList(accept, out var encodings) || encodings.Count == 0)
        {
            return;
        }

        var selectedEncoding        = StringSegment.Empty;
        var selectedEncodingQuality = .0;

        foreach (var encoding in encodings)
        {
            var encodingName = encoding.Value;
            var quality      = encoding.Quality.GetValueOrDefault(1);

            if (quality >= double.Epsilon && quality >= selectedEncodingQuality)
            {
                if (quality == selectedEncodingQuality)
                {
                    selectedEncoding = PickPreferredEncoding(context, selectedEncoding, encoding);
                }
                else if (_encodingExtensionMap.TryGetValue(encodingName, out var encodingExtension) && ResourceExists(context, encodingExtension))
                {
                    selectedEncoding        = encodingName;
                    selectedEncodingQuality = quality;
                }

                if (StringSegment.Equals("*", encodingName, StringComparison.Ordinal))
                {
                    // If we *, pick the first preferrent encoding for which a resource exists.
                    selectedEncoding        = PickPreferredEncoding(context, default, encoding);
Пример #19
0
    /// <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;
    }
        public void ComparisonsTest(string a, string b)
        {
            Assert.AreEqual(a == b, a.AsSegment() == b.AsSegment());

            foreach (StringComparison comparison in Enum <StringComparison> .GetValues())
            {
                Assert.AreEqual(String.Equals(a, b, comparison), StringSegment.Equals(a, b, comparison));
                Assert.AreEqual(Math.Sign(String.Compare(a, b, comparison)), Math.Sign(StringSegment.Compare(a, b, comparison)));
            }

            Assert.AreEqual(StringComparer.Ordinal.Equals(a, b), StringSegmentComparer.Ordinal.Equals(a, b));
            Assert.AreEqual(StringComparer.Ordinal.Equals(a, b), StringSegmentComparer.Ordinal.Equals((object)a, b));
            Assert.AreEqual(StringComparer.Ordinal.Equals(a, b), StringSegmentComparer.Ordinal.Equals((object)a, (StringSegment)b));
            Assert.AreEqual(Math.Sign(StringComparer.Ordinal.Compare(a, b)), Math.Sign(StringSegmentComparer.Ordinal.Compare(a, b)));
            Assert.AreEqual(Math.Sign(StringComparer.Ordinal.Compare(a, b)), Math.Sign(StringSegmentComparer.Ordinal.Compare((object)a, b)));
            Assert.AreEqual(Math.Sign(StringComparer.Ordinal.Compare(a, b)), Math.Sign(StringSegmentComparer.Ordinal.Compare((object)a, (StringSegment)b)));
            Assert.AreEqual(StringComparer.OrdinalIgnoreCase.Equals(a, b), StringSegmentComparer.OrdinalIgnoreCase.Equals(a, b));
            Assert.AreEqual(Math.Sign(StringComparer.OrdinalIgnoreCase.Compare(a, b)), Math.Sign(StringSegmentComparer.OrdinalIgnoreCase.Compare(a, b)));
            Assert.AreEqual(StringComparer.CurrentCulture.Equals(a, b), StringSegmentComparer.CurrentCulture.Equals(a, b));
            Assert.AreEqual(Math.Sign(StringComparer.CurrentCulture.Compare(a, b)), Math.Sign(StringSegmentComparer.CurrentCulture.Compare(a, b)));
            Assert.AreEqual(StringComparer.CurrentCultureIgnoreCase.Equals(a, b), StringSegmentComparer.CurrentCultureIgnoreCase.Equals(a, b));
            Assert.AreEqual(Math.Sign(StringComparer.CurrentCultureIgnoreCase.Compare(a, b)), Math.Sign(StringSegmentComparer.CurrentCultureIgnoreCase.Compare(a, b)));
        }
Пример #21
0
        private bool MatchesParameters(MediaTypeHeaderValue set)
        {
            if (set._parameters != null && set._parameters.Count != 0)
            {
                // Make sure all parameters in the potential superset are included locally. Fine to have additional
                // parameters locally; they make this one more specific.
                foreach (var parameter in set._parameters)
                {
                    if (parameter.Name.Equals(WildcardString, StringComparison.OrdinalIgnoreCase))
                    {
                        // A parameter named "*" has no effect on media type matching, as it is only used as an indication
                        // that the entire media type string should be treated as a wildcard.
                        continue;
                    }

                    if (parameter.Name.Equals(QualityString, StringComparison.OrdinalIgnoreCase))
                    {
                        // "q" and later parameters are not involved in media type matching. Quoting the RFC: The first
                        // "q" parameter (if any) separates the media-range parameter(s) from the accept-params.
                        break;
                    }

                    var localParameter = NameValueHeaderValue.Find(_parameters, parameter.Name);
                    if (localParameter == null)
                    {
                        // Not found.
                        return(false);
                    }

                    if (!StringSegment.Equals(parameter.Value, localParameter.Value, StringComparison.OrdinalIgnoreCase))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
        public bool IsAcceptable(AcceptHeader acceptHeader, out string transferSyntax)
        {
            EnsureArg.IsNotNull(acceptHeader, nameof(acceptHeader));
            transferSyntax = null;

            // Check if payload type match
            if ((PayloadType & acceptHeader.PayloadType) == PayloadTypes.None)
            {
                return(false);
            }

            if (!StringSegment.Equals(acceptHeader.MediaType, MediaType, StringComparison.InvariantCultureIgnoreCase))
            {
                return(false);
            }

            if (StringSegment.IsNullOrEmpty(acceptHeader.TransferSyntax))
            {
                if (IsTransferSyntaxMandatory)
                {
                    return(false);
                }

                // when transfer syntax is missed from accept header, use default one
                transferSyntax = TransferSyntaxWhenMissing;
                return(true);
            }

            if (AcceptableTransferSyntaxes.Contains(acceptHeader.TransferSyntax.Value))
            {
                transferSyntax = acceptHeader.TransferSyntax.Value;
                return(true);
            }

            return(false);
        }
Пример #23
0
 public void EqualsString(string content, string content2, bool expected)
 {
     var segment = new StringSegment(content);
     Assert.Equal(expected, segment.Equals(content2));
 }
Пример #24
0
 /// <summary>
 /// Gets a value indicating whether the string variant has the specified property.
 /// </summary>
 /// <param name="prop">The name of the property to evaluate.</param>
 /// <returns><see langword="true"/> if the string variant has the specified property; otherwise, <see langword="false"/>.</returns>
 public Boolean HasPropertyRef(ref StringSegment prop)
 {
     foreach (var property in properties)
     {
         if (prop.Equals(property))
             return true;
     }
     return parent.HasPropertyRef(ref prop);
 }
Пример #25
0
 /// <summary>
 /// Gets the specified string variant.
 /// </summary>
 /// <param name="group">The name of the variant group of the variant to retrieve.</param>
 /// <returns>The specified string variant.</returns>
 public LocalizedStringVariant GetVariant(ref StringSegment group)
 {
     foreach (var kvp in variants)
     {
         if (group.Equals(kvp.Key))
         {
             return kvp.Value;
         }
     }
     return null;
 }
Пример #26
0
        public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (next == null)
            {
                throw new ArgumentNullException(nameof(next));
            }

            if (!this.IsRequestApplicable(context.RouteData) && HttpMethods.IsPost(context.HttpContext.Request.Method))
            {
                await next();

                return;
            }

            IActionResult ErrorResult = base.EnsureSecureConnection(this.ReceiverName, context.HttpContext.Request);

            if (ErrorResult != null)
            {
                context.Result = ErrorResult;

                return;
            }

            string Header = base.GetRequestHeader(context.HttpContext.Request, BitbucketConstants.SignatureHeaderName, out ErrorResult);

            if (ErrorResult != null)
            {
                context.Result = ErrorResult;

                return;
            }

            TrimmingTokenizer Values = new TrimmingTokenizer(Header, SEPARATORS);

            TrimmingTokenizer.Enumerator Enumerator = Values.GetEnumerator();

            Enumerator.MoveNext();

            StringSegment HeaderKey = Enumerator.Current;

            if (Values.Count != 2 || !StringSegment.Equals(HeaderKey, BitbucketConstants.SignatureHeaderKey, StringComparison.OrdinalIgnoreCase))
            {
                string ErrorMessage = string.Format(CultureInfo.CurrentCulture, Resources.SignatureFilter_BadHeaderValue,
                                                    BitbucketConstants.SignatureHeaderName, BitbucketConstants.SignatureHeaderKey, "<value>");

                base.Logger.LogError(1, ErrorMessage);
                context.Result = new BadRequestObjectResult(ErrorMessage);

                return;
            }

            Enumerator.MoveNext();
            string HeaderValue = Enumerator.Current.Value;

            byte[] ExpectedHash = base.FromHex(HeaderValue, BitbucketConstants.SignatureHeaderName);
            if (ExpectedHash == null)
            {
                context.Result = base.CreateBadHexEncodingResult(BitbucketConstants.SignatureHeaderName);

                return;
            }

            byte[] Secret = this.GetSecret(this.ReceiverName, context.RouteData);
            if (Secret == null)
            {
                context.Result = new NotFoundResult();

                return;
            }

            byte[] ActualHash = await base.ComputeRequestBodySha256HashAsync(context.HttpContext.Request, Secret);

            if (!BitbucketVerifySignatureFilter.SecretEqual(ExpectedHash, ActualHash))
            {
                context.Result = base.CreateBadSignatureResult(BitbucketConstants.SignatureHeaderName);

                return;
            }

            await next();
        }
        private IActionResult ValidateHeader(string header)
        {
            var hasTimestamp = false;
            var hasSignature = false;
            var pairs        = new TrimmingTokenizer(header, CommaSeparator);

            foreach (var pair in pairs)
            {
                var keyValuePair = new TrimmingTokenizer(pair, EqualSeparator, maxCount: 2);
                if (keyValuePair.Count != 2)
                {
                    // Header is not formatted correctly.
                    Logger.LogWarning(
                        0,
                        $"The '{StripeConstants.SignatureHeaderName}' header value is invalid. '{{InvalidPair}}' " +
                        "should be a 'key=value' pair.",
                        pair);

                    var message = string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.SignatureFilter_InvalidHeaderFormat,
                        StripeConstants.SignatureHeaderName);
                    return(new BadRequestObjectResult(message));
                }

                var enumerator = keyValuePair.GetEnumerator();
                enumerator.MoveNext();

                var key = enumerator.Current;
                if (StringSegment.Equals(key, StripeConstants.SignatureKey, StringComparison.Ordinal))
                {
                    enumerator.MoveNext();
                    hasSignature = !StringSegment.IsNullOrEmpty(enumerator.Current);
                }
                else if (StringSegment.Equals(key, StripeConstants.TimestampKey, StringComparison.Ordinal))
                {
                    enumerator.MoveNext();
                    hasTimestamp = !StringSegment.IsNullOrEmpty(enumerator.Current);
                }
            }

            if (!hasSignature)
            {
                Logger.LogWarning(
                    1,
                    $"The '{StripeConstants.SignatureHeaderName}' header value is invalid. Does not contain a " +
                    $"timestamp ('{StripeConstants.SignatureKey}') value.");
            }

            if (!hasTimestamp)
            {
                Logger.LogWarning(
                    2,
                    $"The '{StripeConstants.SignatureHeaderName}' header value is invalid. Does not contain a " +
                    $"signature ('{StripeConstants.TimestampKey}') value.");
            }

            if (!hasSignature || !hasTimestamp)
            {
                var message = string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.SignatureFilter_HeaderMissingValue,
                    StripeConstants.SignatureHeaderName,
                    StripeConstants.TimestampKey,
                    StripeConstants.SignatureKey);
                return(new BadRequestObjectResult(message));
            }

            // Success
            return(null);
        }
Пример #28
0
        public void EqualsString(string content, string content2, bool expected)
        {
            var segment = new StringSegment(content);

            Assert.Equal(expected, segment.Equals(content2));
        }
Пример #29
0
 public void TestEquals(string content)
 {
     var segment = new StringSegment(content);
     Assert.True(segment.Equals(segment));
 }
Пример #30
0
        public void StringSegment_EqualsString_Invalid()
        {
            // Arrange
            var segment = new StringSegment();

            // Act
            var result = segment.Equals(string.Empty, StringComparison.Ordinal);

            // Assert
            Assert.False(result);
        }
Пример #31
0
 /// <summary>
 /// Check against another <see cref="EntityTagHeaderValue"/> for equality.
 /// This equality check should not be used to determine if two values match under the RFC specifications (https://tools.ietf.org/html/rfc7232#section-2.3.2).
 /// </summary>
 /// <param name="obj">The other value to check against for equality.</param>
 /// <returns>
 /// <c>true</c> if the strength and tag of the two values match,
 /// <c>false</c> if the other value is null, is not an <see cref="EntityTagHeaderValue"/>, or if there is a mismatch of strength or tag between the two values.
 /// </returns>
 public override bool Equals(object?obj)
 {
     // Since the tag is a quoted-string we treat it case-sensitive.
     return(obj is EntityTagHeaderValue other && _isWeak == other._isWeak && StringSegment.Equals(_tag, other._tag, StringComparison.Ordinal));
 }
Пример #32
0
        /// <inheritdoc />
        public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (next == null)
            {
                throw new ArgumentNullException(nameof(next));
            }

            var request = context.HttpContext.Request;

            if (HttpMethods.IsPost(request.Method))
            {
                // 1. Confirm a secure connection.
                var errorResult = EnsureSecureConnection(ReceiverName, context.HttpContext.Request);
                if (errorResult != null)
                {
                    context.Result = errorResult;
                    return;
                }

                // 2. Get the expected hash from the signature header.
                var header = GetRequestHeader(request, ZoomConstants.SignatureHeaderName, out errorResult);
                if (errorResult != null)
                {
                    context.Result = errorResult;
                    return;
                }

                var values     = new TrimmingTokenizer(header, PairSeparators);
                var enumerator = values.GetEnumerator();
                enumerator.MoveNext();
                var headerKey = enumerator.Current;
                if (values.Count != 2 ||
                    !StringSegment.Equals(
                        headerKey,
                        ZoomConstants.SignatureHeaderKey,
                        StringComparison.OrdinalIgnoreCase))
                {
                    Logger.LogWarning(
                        0,
                        $"Invalid '{ZoomConstants.SignatureHeaderName}' header value. Expecting a value of " +
                        $"'{ZoomConstants.SignatureHeaderKey}=<value>'.");

                    var message = string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.SignatureFilter_BadHeaderValue,
                        ZoomConstants.SignatureHeaderName,
                        ZoomConstants.SignatureHeaderKey,
                        "<value>");
                    errorResult = new BadRequestObjectResult(message);

                    context.Result = errorResult;
                    return;
                }

                enumerator.MoveNext();
                var headerValue = enumerator.Current.Value;

                var expectedHash = FromHex(headerValue, ZoomConstants.SignatureHeaderName);
                if (expectedHash == null)
                {
                    context.Result = CreateBadHexEncodingResult(ZoomConstants.SignatureHeaderKey);
                    return;
                }

                // 3. Get the configured secret key.
                var secretKey = GetSecretKey(ReceiverName, context.RouteData, ZoomConstants.SecretKeyMinLength);
                if (secretKey == null)
                {
                    context.Result = new NotFoundResult();
                    return;
                }

                var secret = Encoding.UTF8.GetBytes(secretKey);

                // 4. Get the actual hash of the request body.
                var actualHash = await ComputeRequestBodySha1HashAsync(request, secret);

                // 5. Verify that the actual hash matches the expected hash.
                if (!SecretEqual(expectedHash, actualHash))
                {
                    // Log about the issue and short-circuit remainder of the pipeline.
                    errorResult = CreateBadSignatureResult(ZoomConstants.SignatureHeaderName);

                    context.Result = errorResult;
                    return;
                }
            }

            await next();
        }
Пример #33
0
        /// <summary>
        /// Matches a source string to a target variant according to the specified culture and rule.
        /// </summary>
        private static String MatchVariantInternal(String culture, LocalizedString source, LocalizedStringVariant target, StringSegment rule)
        {
            Dictionary<String, LocalizationMatchEvaluator> registry;
            if (!registeredMatchEvaluators.TryGetValue(culture, out registry))
                return null;

            foreach (var kvp in registry)
            {
                if (rule.Equals(kvp.Key))
                {
                    return (kvp.Value == null) ? null : kvp.Value(source, target);
                }
            }
            return null;
        }
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            output.TagName = null;

            if (String.IsNullOrWhiteSpace(Include) && String.IsNullOrWhiteSpace(Exclude))
            {
                return;
            }

            string currentProtocol = ViewContext.HttpContext.Request.Protocol;

            if (Exclude != null)
            {
                StringTokenizer excludeTokenizer = new StringTokenizer(Exclude, PROTOCOLS_SEPARATOR);

                foreach (StringSegment excludeToken in excludeTokenizer)
                {
                    StringSegment excludedProtocol = excludeToken.Trim();

                    if (excludedProtocol.HasValue && excludedProtocol.Length > 0)
                    {
                        if (excludedProtocol.Equals(currentProtocol, StringComparison.OrdinalIgnoreCase))
                        {
                            output.SuppressOutput();
                            return;
                        }
                    }
                }
            }

            bool hasIncludeProtocols = false;

            if (Include != null)
            {
                StringTokenizer includeTokenizer = new StringTokenizer(Include, PROTOCOLS_SEPARATOR);

                foreach (StringSegment includedToken in includeTokenizer)
                {
                    StringSegment includedProtocol = includedToken.Trim();

                    if (includedProtocol.HasValue && includedProtocol.Length > 0)
                    {
                        hasIncludeProtocols = true;

                        if (includedProtocol.Equals(currentProtocol, StringComparison.OrdinalIgnoreCase))
                        {
                            return;
                        }
                    }
                }
            }

            if (hasIncludeProtocols)
            {
                output.SuppressOutput();
            }
        }
Пример #35
0
 public bool Equals(HeaderSegment other)
 {
     return(_formatting.Equals(other._formatting) && _data.Equals(other._data));
 }
        // name=value; expires=Sun, 06 Nov 1994 08:49:37 GMT; max-age=86400; domain=domain1; path=path1; secure; samesite={Strict|Lax}; httponly
        private static int GetSetCookieLength(StringSegment input, int startIndex, out SetCookieHeaderValue parsedValue)
        {
            Contract.Requires(startIndex >= 0);
            var offset = startIndex;

            parsedValue = null;

            if (StringSegment.IsNullOrEmpty(input) || (offset >= input.Length))
            {
                return(0);
            }

            var result = new SetCookieHeaderValue();

            // The caller should have already consumed any leading whitespace, commas, etc..

            // Name=value;

            // Name
            var itemLength = HttpRuleParser.GetTokenLength(input, offset);

            if (itemLength == 0)
            {
                return(0);
            }
            result._name = input.Subsegment(offset, itemLength);
            offset      += itemLength;

            // = (no spaces)
            if (!ReadEqualsSign(input, ref offset))
            {
                return(0);
            }

            // value or "quoted value"
            // The value may be empty
            result._value = CookieHeaderValue.GetCookieValue(input, ref offset);

            // *(';' SP cookie-av)
            while (offset < input.Length)
            {
                if (input[offset] == ',')
                {
                    // Divider between headers
                    break;
                }
                if (input[offset] != ';')
                {
                    // Expecting a ';' between parameters
                    return(0);
                }
                offset++;

                offset += HttpRuleParser.GetWhitespaceLength(input, offset);

                //  cookie-av = expires-av / max-age-av / domain-av / path-av / secure-av / samesite-av / httponly-av / extension-av
                itemLength = HttpRuleParser.GetTokenLength(input, offset);
                if (itemLength == 0)
                {
                    // Trailing ';' or leading into garbage. Let the next parser fail.
                    break;
                }
                var token = input.Subsegment(offset, itemLength);
                offset += itemLength;

                //  expires-av = "Expires=" sane-cookie-date
                if (StringSegment.Equals(token, ExpiresToken, StringComparison.OrdinalIgnoreCase))
                {
                    // = (no spaces)
                    if (!ReadEqualsSign(input, ref offset))
                    {
                        return(0);
                    }
                    var            dateString = ReadToSemicolonOrEnd(input, ref offset);
                    DateTimeOffset expirationDate;
                    if (!HttpRuleParser.TryStringToDate(dateString, out expirationDate))
                    {
                        // Invalid expiration date, abort
                        return(0);
                    }
                    result.Expires = expirationDate;
                }
                // max-age-av = "Max-Age=" non-zero-digit *DIGIT
                else if (StringSegment.Equals(token, MaxAgeToken, StringComparison.OrdinalIgnoreCase))
                {
                    // = (no spaces)
                    if (!ReadEqualsSign(input, ref offset))
                    {
                        return(0);
                    }

                    itemLength = HttpRuleParser.GetNumberLength(input, offset, allowDecimal: false);
                    if (itemLength == 0)
                    {
                        return(0);
                    }
                    var  numberString = input.Subsegment(offset, itemLength);
                    long maxAge;
                    if (!HeaderUtilities.TryParseNonNegativeInt64(numberString, out maxAge))
                    {
                        // Invalid expiration date, abort
                        return(0);
                    }
                    result.MaxAge = TimeSpan.FromSeconds(maxAge);
                    offset       += itemLength;
                }
                // domain-av = "Domain=" domain-value
                // domain-value = <subdomain> ; defined in [RFC1034], Section 3.5, as enhanced by [RFC1123], Section 2.1
                else if (StringSegment.Equals(token, DomainToken, StringComparison.OrdinalIgnoreCase))
                {
                    // = (no spaces)
                    if (!ReadEqualsSign(input, ref offset))
                    {
                        return(0);
                    }
                    // We don't do any detailed validation on the domain.
                    result.Domain = ReadToSemicolonOrEnd(input, ref offset);
                }
                // path-av = "Path=" path-value
                // path-value = <any CHAR except CTLs or ";">
                else if (StringSegment.Equals(token, PathToken, StringComparison.OrdinalIgnoreCase))
                {
                    // = (no spaces)
                    if (!ReadEqualsSign(input, ref offset))
                    {
                        return(0);
                    }
                    // We don't do any detailed validation on the path.
                    result.Path = ReadToSemicolonOrEnd(input, ref offset);
                }
                // secure-av = "Secure"
                else if (StringSegment.Equals(token, SecureToken, StringComparison.OrdinalIgnoreCase))
                {
                    result.Secure = true;
                }
                // samesite-av = "SameSite" / "SameSite=" samesite-value
                // samesite-value = "Strict" / "Lax"
                else if (StringSegment.Equals(token, SameSiteToken, StringComparison.OrdinalIgnoreCase))
                {
                    if (!ReadEqualsSign(input, ref offset))
                    {
                        result.SameSite = SameSiteMode.Strict;
                    }
                    else
                    {
                        var enforcementMode = ReadToSemicolonOrEnd(input, ref offset);

                        if (StringSegment.Equals(enforcementMode, SameSiteLaxToken, StringComparison.OrdinalIgnoreCase))
                        {
                            result.SameSite = SameSiteMode.Lax;
                        }
                        else
                        {
                            result.SameSite = SameSiteMode.Strict;
                        }
                    }
                }
                // httponly-av = "HttpOnly"
                else if (StringSegment.Equals(token, HttpOnlyToken, StringComparison.OrdinalIgnoreCase))
                {
                    result.HttpOnly = true;
                }
                // extension-av = <any CHAR except CTLs or ";">
                else
                {
                    // TODO: skip it? Store it in a list?
                }
            }

            parsedValue = result;
            return(offset - startIndex);
        }
        /// <inheritdoc />
        public virtual ICompressionProvider?GetCompressionProvider(HttpContext context)
        {
            // e.g. Accept-Encoding: gzip, deflate, sdch
            var accept = context.Request.Headers.AcceptEncoding;

            // Note this is already checked in CheckRequestAcceptsCompression which _should_ prevent any of these other methods from being called.
            if (StringValues.IsNullOrEmpty(accept))
            {
                Debug.Assert(false, "Duplicate check failed.");
                _logger.NoAcceptEncoding();
                return(null);
            }

            if (!StringWithQualityHeaderValue.TryParseList(accept, out var encodings) || encodings.Count == 0)
            {
                _logger.NoAcceptEncoding();
                return(null);
            }

            var candidates = new HashSet <ProviderCandidate>();

            foreach (var encoding in encodings)
            {
                var encodingName = encoding.Value;
                var quality      = encoding.Quality.GetValueOrDefault(1);

                if (quality < double.Epsilon)
                {
                    continue;
                }

                for (int i = 0; i < _providers.Length; i++)
                {
                    var provider = _providers[i];

                    if (StringSegment.Equals(provider.EncodingName, encodingName, StringComparison.OrdinalIgnoreCase))
                    {
                        candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider));
                    }
                }

                // Uncommon but valid options
                if (StringSegment.Equals("*", encodingName, StringComparison.Ordinal))
                {
                    for (int i = 0; i < _providers.Length; i++)
                    {
                        var provider = _providers[i];

                        // Any provider is a candidate.
                        candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider));
                    }

                    break;
                }

                if (StringSegment.Equals("identity", encodingName, StringComparison.OrdinalIgnoreCase))
                {
                    // We add 'identity' to the list of "candidates" with a very low priority and no provider.
                    // This will allow it to be ordered based on its quality (and priority) later in the method.
                    candidates.Add(new ProviderCandidate(encodingName.Value, quality, priority: int.MaxValue, provider: null));
                }
            }

            ICompressionProvider?selectedProvider = null;

            if (candidates.Count <= 1)
            {
                selectedProvider = candidates.FirstOrDefault().Provider;
            }
            else
            {
                selectedProvider = candidates
                                   .OrderByDescending(x => x.Quality)
                                   .ThenBy(x => x.Priority)
                                   .First().Provider;
            }

            if (selectedProvider == null)
            {
                // "identity" would match as a candidate but not have a provider implementation
                _logger.NoCompressionProvider();
                return(null);
            }

            _logger.CompressingWith(selectedProvider.EncodingName);
            return(selectedProvider);
        }
Пример #38
0
        public void TestEquals(string content)
        {
            var segment = new StringSegment(content);

            Assert.True(segment.Equals(segment));
        }
Пример #39
0
        public void StringSegment_Equals_String_Valid(StringSegment candidate, StringComparison comparison, bool expectedResult)
        {
            // Arrange
            var segment = new StringSegment("Hello, World!", 1, 4);

            // Act
            var result = segment.Equals(candidate, comparison);

            // Assert
            Assert.Equal(expectedResult, result);
        }
Пример #40
0
        public void StringSegment_EqualsStringSegment_Invalid()
        {
            // Arrange
            var segment = new StringSegment();
            var candidate = new StringSegment("Hello, World!", 3, 2);

            // Act
            var result = segment.Equals(candidate, StringComparison.Ordinal);

            // Assert
            Assert.False(result);
        }