public async Task ProcessAsync_Sha512SriNotCached_CachesSriAndReturnsIt()
        {
            var expectedSri = "sha512-NhX4DJ0pPtdAJof5SyLVjlKbjMeRb4+sf933+9WvTPd309eVp6AKFr9+fz+5Vh7puq5IDan+ehh2nnGIawPzFQ==";

            this.tagHelper.Source = "/foo.js";
            var attributes = new TagHelperAttributeList
            {
                { "src", "/foo.js" }
            };
            var context = new TagHelperContext(attributes, new Dictionary <object, object>(), Guid.NewGuid().ToString());
            var output  = new TagHelperOutput("script", attributes, (x, y) => throw new ArgumentException());

            this.distributedCacheMock
            .Setup(x => x.GetAsync("SRI:/foo.js", CancellationToken.None))
            .ReturnsAsync((byte[])null);
            this.webHostEnvironmentMock.SetupGet(x => x.ContentRootPath).Returns(@"C:\Foo\wwwroot");
            this.urlHelperMock.Setup(x => x.Content("/foo.js")).Returns(@"C:\Foo\wwwroot\foo.js");
            this.distributedCacheMock
            .Setup(x => x.SetAsync(
                       "SRI:/foo.js",
                       It.Is <byte[]>(y => string.Equals(Encoding.UTF8.GetString(y), expectedSri, StringComparison.Ordinal)),
                       It.IsAny <DistributedCacheEntryOptions>(),
                       CancellationToken.None))
            .Returns(Task.CompletedTask);

            await this.tagHelper.ProcessAsync(context, output);

            Assert.True(attributes.ContainsName("crossorigin"));
            Assert.Equal("anonymous", attributes["crossorigin"].Value);
            Assert.True(attributes.ContainsName("integrity"));
            var htmlString = Assert.IsType <HtmlString>(attributes["integrity"].Value);

            Assert.Equal(expectedSri, htmlString.Value);
        }
示例#2
0
        protected virtual TagHelperAttributeList GetInputAttributes(TagHelperContext context, TagHelperOutput output)
        {
            var groupPrefix = "group-";

            var tagHelperAttributes = output.Attributes.Where(a => !a.Name.StartsWith(groupPrefix)).ToList();

            var attrList = new TagHelperAttributeList();

            foreach (var tagHelperAttribute in tagHelperAttributes)
            {
                attrList.Add(tagHelperAttribute);
            }

            if (!TagHelper.InputTypeName.IsNullOrEmpty() && !attrList.ContainsName("type"))
            {
                attrList.Add("type", TagHelper.InputTypeName);
            }

            if (!TagHelper.Name.IsNullOrEmpty() && !attrList.ContainsName("name"))
            {
                attrList.Add("name", TagHelper.Name);
            }

            if (!TagHelper.Value.IsNullOrEmpty() && !attrList.ContainsName("value"))
            {
                attrList.Add("value", TagHelper.Value);
            }

            return(attrList);
        }
示例#3
0
        private void BuildFallbackBlock(TagHelperAttributeList attributes, DefaultTagHelperContent builder)
        {
            EnsureGlobbingUrlBuilder();

            var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude);

            if (fallbackSrcs.Any())
            {
                // Build the <script> tag that checks the test method and if it fails, renders the extra script.
                builder.Append(Environment.NewLine)
                .Append("<script>(")
                .Append(FallbackTestExpression)
                .Append("||document.write(\"");

                // May have no "src" attribute in the dictionary e.g. if Src and SrcInclude were not bound.
                if (!attributes.ContainsName(SrcAttributeName))
                {
                    // Need this entry to place each fallback source.
                    attributes.Add(new TagHelperAttribute(SrcAttributeName, value: null));
                }

                foreach (var src in fallbackSrcs)
                {
                    // Fallback "src" values come from bound attributes and globbing. Must always be non-null.
                    Debug.Assert(src != null);

                    builder.Append("<script");

                    foreach (var attribute in attributes)
                    {
                        if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
                        {
                            var encodedKey     = JavaScriptEncoder.JavaScriptStringEncode(attribute.Name);
                            var attributeValue = attribute.Value.ToString();
                            var encodedValue   = JavaScriptEncoder.JavaScriptStringEncode(attributeValue);

                            AppendAttribute(builder, encodedKey, encodedValue, escapeQuotes: true);
                        }
                        else
                        {
                            // Ignore attribute.Value; use src instead.
                            var attributeValue = src;
                            if (AppendVersion == true)
                            {
                                attributeValue = _fileVersionProvider.AddFileVersionToPath(attributeValue);
                            }

                            // attribute.Key ("src") does not need to be JavaScript-encoded.
                            var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue);

                            AppendAttribute(builder, attribute.Name, encodedValue, escapeQuotes: true);
                        }
                    }

                    builder.Append("><\\/script>");
                }

                builder.Append("\"));</script>");
            }
        }
示例#4
0
        /// <summary>
        ///     Sets an attribute value by name to 'value.ToString()'. If 'replace' is false, the attribute is only set if not
        ///     already set. If 'value' is null, the entry is removed from the list instead.
        /// </summary>
        /// <exception cref="ArgumentException"> Thrown if 'name' is null or empty. </exception>
        /// <param name="list"> The TagHelperAttributeList to merge an attribute value with. </param>
        /// <param name="name"> The key to set a value for. </param>
        /// <param name="value">
        ///     The value to set for the specified key, which will be converted to a string first. If null, any existing entry is
        ///     removed instead (if 'replace' is true).
        /// </param>
        /// <param name="replace">
        ///     (Optional) If true (the default) adds a new entry or replaces an existing entry, otherwise the request is ignored.
        ///     If this is false, nothing is removed, and any merge requests with existing keys will be ignored.
        /// </param>
        /// <param name="removeOnEmptyOrWhitespace">
        ///     (Optional) If true (default) any empty or whitespace-only values will remove the attribute. This is in addition to
        ///     'null', which always removes values.
        /// </param>
        /// <param name="replaceIfValueNotEmpty">
        ///     (Optional) If true, any existing entry is only replaced if the given value is not empty or whitespace only. Default
        ///     is false. This setting has no affect if the 'replace' parameter is false.
        /// </param>
        public static void MergeAttribute(this TagHelperAttributeList list, string name, object value, bool replace = true, bool removeOnEmptyOrWhitespace = true, bool replaceIfValueNotEmpty = false)
        {
            if (name == null)
            {
                throw new ArgumentException("Value cannot be null.", nameof(name));
            }
            else if (name is string && string.IsNullOrEmpty((string)(object)name))
            {
                throw new ArgumentException("Value cannot be null or empty.", nameof(name));
            }

            if (replace || value != null && !list.ContainsName(name))
            {
                var valueStr = value?.ToString().Trim();
                var isEmpty  = string.IsNullOrWhiteSpace(valueStr);
                if (valueStr == null || removeOnEmptyOrWhitespace && isEmpty)
                {
                    list.RemoveAll(name);
                }
                else if (!replaceIfValueNotEmpty || !isEmpty)
                {
                    list.Add(name, valueStr);
                }
            }
        }
 public static void AddIfNotContains(this TagHelperAttributeList attributes, string name, object value)
 {
     if (!attributes.ContainsName("method"))
     {
         attributes.Add("method", "post");
     }
 }
示例#6
0
 public static void AddIfNotContains(this TagHelperAttributeList attributes, string name, object value)
 {
     if (!attributes.ContainsName(name))
     {
         attributes.Add(name, value);
     }
 }
示例#7
0
 public static void AddClass(this TagHelperAttributeList attrs, string append_class)
 {
     if (attrs.ContainsName("class"))
     {
         append_class += " " + attrs["class"].Value;
     }
     attrs.SetAttribute("class", append_class);
 }
示例#8
0
        /// <summary>
        /// Adds a <see cref="TagHelperAttribute"/> with <paramref name="name"/> and the value of <paramref name="valueAccessor"/> to the end of the collection,
        /// but only if the attribute does not exist.
        /// </summary>
        /// <param name="name">
        /// The <see cref="TagHelperAttribute.Name"/> of the <see cref="TagHelperAttribute"/> to set.
        /// </param>
        /// <param name="valueAccessor">
        /// The <see cref="TagHelperAttribute.Value"/> to set.
        /// </param>
        /// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
        public static void SetAttributeNoReplace(this TagHelperAttributeList attributes, string name, Func <object> valueAccessor)
        {
            Guard.NotEmpty(name, nameof(name));

            if (!attributes.ContainsName(name))
            {
                attributes.SetAttribute(name, valueAccessor());
            }
        }
示例#9
0
        /// <summary>
        /// Adds a <see cref="TagHelperAttribute"/> with <paramref name="name"/> and <paramref name="value"/> to the end of the collection,
        /// but only if the attribute does not exist.
        /// </summary>
        /// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the <see cref="TagHelperAttribute"/> to set.</param>
        /// <param name="value">The <see cref="TagHelperAttribute.Value"/> to set.</param>
        /// <param name="ignoreNull"><c>false</c> = don't render attribute if value is null.</param>
        /// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
        public static void SetAttributeNoReplace(this TagHelperAttributeList attributes, string name, object value, bool ignoreNull = true)
        {
            Guard.NotEmpty(name, nameof(name));

            if (!attributes.ContainsName(name) && (value != null || !ignoreNull))
            {
                attributes.SetAttribute(name, value);
            }
        }
示例#10
0
        public static void AddOrIgnore(this TagHelperAttributeList attrs, string name, object value)
        {
            if (attrs.ContainsName(name))
            {
                return;
            }

            attrs.Add(name, value);
        }
示例#11
0
        public static void MergeClassAttributeValue(this TagHelperAttributeList attributes, string newClassValue)
        {
            string classValue = newClassValue;

            if (attributes.ContainsName("class"))
            {
                classValue = $"{attributes["class"].Value} {classValue}";
            }
            attributes.SetAttribute("class", classValue);
        }
 public static void AddOrUpdate(this TagHelperAttributeList attributes, string name, object value)
 {
     if (attributes.ContainsName(name))
     {
         attributes.SetAttribute(name, value);
     }
     else
     {
         attributes.Add(name, value);
     }
 }
        public async Task ProcessAsync_Sha256And384And512SriNotCached_CachesSriAndReturnsIt()
        {
            var expectedSri = "sha256-GF+NsyJx/iX1Yab8k4suJkMG7DBO2lGAB9F2SCY4GWk= " +
                              "sha384-NRn+WtLFlu/j4nam81G4/AsD24YXgkkNRfdZjr0Ktf1VIO0QLzjEpeyDTphmgDX8 " +
                              "sha512-NhX4DJ0pPtdAJof5SyLVjlKbjMeRb4+sf933+9WvTPd309eVp6AKFr9+fz+5Vh7puq5IDan+ehh2nnGIawPzFQ==";

            this.tagHelper.HashAlgorithms =
                SubresourceIntegrityHashAlgorithm.SHA256 |
                SubresourceIntegrityHashAlgorithm.SHA384 |
                SubresourceIntegrityHashAlgorithm.SHA512;
            this.tagHelper.Source = "/foo.js";
            var attributes = new TagHelperAttributeList
            {
                { "src", "/foo.js" }
            };
            var context = new TagHelperContext(attributes, new Dictionary <object, object>(), Guid.NewGuid().ToString());
            var output  = new TagHelperOutput("script", attributes, (x, y) => throw new ArgumentException());

            this.distributedCacheMock
            .Setup(x => x.GetAsync("SRI:/foo.js", CancellationToken.None))
            .ReturnsAsync((byte[])null);
            this.hostingEnvironmentMock.SetupGet(x => x.WebRootPath).Returns(@"C:\Foo\wwwroot");
            this.urlHelperMock.Setup(x => x.Content("/foo.js")).Returns(@"C:\Foo\wwwroot\foo.js");
            this.distributedCacheMock
            .Setup(x => x.SetAsync(
                       "SRI:/foo.js",
                       It.Is <byte[]>(y => string.Equals(Encoding.UTF8.GetString(y), expectedSri, StringComparison.Ordinal)),
                       It.IsAny <DistributedCacheEntryOptions>(),
                       CancellationToken.None))
            .Returns(Task.CompletedTask);

            await this.tagHelper.ProcessAsync(context, output);

            Assert.True(attributes.ContainsName("crossorigin"));
            Assert.Equal("anonymous", attributes["crossorigin"].Value);
            Assert.True(attributes.ContainsName("integrity"));
            var htmlString = Assert.IsType <HtmlString>(attributes["integrity"].Value);

            Assert.Equal(expectedSri, htmlString.Value);
        }
示例#14
0
        /// <summary>
        /// Adds a <see cref="TagHelperAttribute"/> with <paramref name="name"/> and the value of <paramref name="valueAccessor"/> to the end of the collection,
        /// but only if the attribute does not exist.
        /// </summary>
        /// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the <see cref="TagHelperAttribute"/> to set.</param>
        /// <param name="valueAccessor">The <see cref="TagHelperAttribute.Value"/> to set.</param>
        /// <param name="ignoreNull"><c>false</c> = don't render attribute if value is null.</param>
        /// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
        public static void SetAttributeNoReplace(this TagHelperAttributeList attributes, string name, Func <object> valueAccessor, bool ignoreNull = true)
        {
            Guard.NotEmpty(name, nameof(name));

            if (!attributes.ContainsName(name))
            {
                var value = valueAccessor();
                if (value != null || !ignoreNull)
                {
                    attributes.SetAttribute(name, valueAccessor());
                }
            }
        }
示例#15
0
    public void ContainsName_ReturnsExpectedResult(
        IEnumerable <TagHelperAttribute> initialAttributes,
        string nameToLookup,
        bool expected)
    {
        // Arrange
        var attributes = new TagHelperAttributeList(initialAttributes);

        // Act
        var contains = attributes.ContainsName(nameToLookup);

        // Assert
        Assert.Equal(expected, contains);
    }
        public async Task ProcessAsync_SriAlreadyCached_ReturnsCachedSri()
        {
            this.tagHelper.Source = "/foo.js";
            var attributes = new TagHelperAttributeList
            {
                { "src", "/foo.js" }
            };
            var context = new TagHelperContext(attributes, new Dictionary <object, object>(), Guid.NewGuid().ToString());
            var output  = new TagHelperOutput("script", attributes, (x, y) => throw new ArgumentException());

            this.distributedCacheMock
            .Setup(x => x.GetAsync("SRI:/foo.js", CancellationToken.None))
            .ReturnsAsync(Encoding.UTF8.GetBytes("SRI Value"));

            await this.tagHelper.ProcessAsync(context, output);

            Assert.True(attributes.ContainsName("crossorigin"));
            Assert.Equal("anonymous", attributes["crossorigin"].Value);
            Assert.True(attributes.ContainsName("integrity"));
            var htmlString = Assert.IsType <HtmlString>(attributes["integrity"].Value);

            Assert.Equal("SRI Value", htmlString.Value);
        }
        public static void AddOrUpdate(this TagHelperAttributeList attributes, string name, Func <object, object> valueFunc)
        {
            object value;

            if (attributes.ContainsName(name))
            {
                value = valueFunc(attributes[name].Value);
                attributes.SetAttribute(name, value);
            }
            else
            {
                value = valueFunc(null);
                attributes.Add(name, value);
            }
        }
示例#18
0
        public static TagHelperContext CreateTagHelperContext(this IWebPackObject webPack,
                                                              ReadOnlyTagHelperAttributeList allAttributes,
                                                              IDictionary <object, object> items,
                                                              string uniqueId)
        {
            var customAttributeList = new TagHelperAttributeList();
            var attributes          = webPack.Resolve();

            foreach (KeyValuePair <string, object> entry in attributes)
            {
                customAttributeList.Add(new TagHelperAttribute(entry.Key, entry.Value));
            }

            foreach (var item in allAttributes)
            {
                if (!customAttributeList.ContainsName(item.Name))
                {
                    customAttributeList.Add(new TagHelperAttribute(item.Name, item.Value));
                }
            }

            return(new TagHelperContext(customAttributeList, new Dictionary <object, object>(), uniqueId));
        }
 private bool CanBeActive(TagHelperAttributeList attributes)
 => ActiveClass != null && attributes.ContainsName("href") && attributes["href"].Value != null;
示例#20
0
        private void BuildFallbackBlock(TagHelperAttributeList attributes, DefaultTagHelperContent builder)
        {
            EnsureGlobbingUrlBuilder();

            var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude);
            if (fallbackSrcs.Any())
            {
                // Build the <script> tag that checks the test method and if it fails, renders the extra script.
                builder.AppendHtml(Environment.NewLine)
                       .AppendHtml("<script>(")
                       .AppendHtml(FallbackTestExpression)
                       .AppendHtml("||document.write(\"");

                // May have no "src" attribute in the dictionary e.g. if Src and SrcInclude were not bound.
                if (!attributes.ContainsName(SrcAttributeName))
                {
                    // Need this entry to place each fallback source.
                    attributes.Add(new TagHelperAttribute(SrcAttributeName, value: null));
                }

                foreach (var src in fallbackSrcs)
                {
                    // Fallback "src" values come from bound attributes and globbing. Must always be non-null.
                    Debug.Assert(src != null);

                    builder.AppendHtml("<script");

                    foreach (var attribute in attributes)
                    {
                        if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
                        {
                            var encodedKey = JavaScriptEncoder.JavaScriptStringEncode(attribute.Name);
                            var attributeValue = attribute.Value.ToString();
                            var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue);

                            AppendAttribute(builder, encodedKey, encodedValue, escapeQuotes: true);
                        }
                        else
                        {
                            // Ignore attribute.Value; use src instead.
                            var attributeValue = src;
                            if (AppendVersion == true)
                            {
                                attributeValue = _fileVersionProvider.AddFileVersionToPath(attributeValue);
                            }

                            // attribute.Key ("src") does not need to be JavaScript-encoded.
                            var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue);

                            AppendAttribute(builder, attribute.Name, encodedValue, escapeQuotes: true);
                        }
                    }

                    builder.AppendHtml("><\\/script>");
                }

                builder.AppendHtml("\"));</script>");
            }
        }
示例#21
0
        public void ContainsName_ReturnsExpectedResult(
            IEnumerable<TagHelperAttribute> initialAttributes,
            string nameToLookup,
            bool expected)
        {
            // Arrange
            var attributes = new TagHelperAttributeList(initialAttributes);

            // Act
            var contains = attributes.ContainsName(nameToLookup);

            // Assert
            Assert.Equal(expected, contains);
        }