/// <summary> /// Add allowed URL protocols for an element's URL attribute. /// </summary> /// <remarks> /// This restricts the possible values of the attribute to /// URLs with the defined protocol. /// <p/> /// E.g.: <c>AddProtocols("a", "href", "ftp", "http", "https")</c> /// </remarks> /// <param name="tag">Tag the URL protocol is for</param> /// <param name="key">Attribute key</param> /// <param name="protocols">List of valid protocols</param> /// <returns>this, for chaining</returns> public Whitelist AddProtocols(string tag, string key, params string[] protocols) { Validate.NotEmpty(tag); Validate.NotEmpty(key); Validate.NotNull(protocols); Whitelist.TagName tagName = Whitelist.TagName.ValueOf(tag); Whitelist.AttributeKey attrKey = Whitelist.AttributeKey.ValueOf(key); IDictionary <Whitelist.AttributeKey, ICollection <Whitelist.Protocol> > attrMap; ICollection <Whitelist.Protocol> protSet; if (this.protocols.ContainsKey(tagName)) { attrMap = this.protocols[tagName]; } else { attrMap = new Dictionary <Whitelist.AttributeKey, ICollection <Whitelist.Protocol> >(); this.protocols[tagName] = attrMap; } if (attrMap.ContainsKey(attrKey)) { protSet = attrMap[attrKey]; } else { protSet = new HashSet <Whitelist.Protocol>(); attrMap[attrKey] = protSet; } foreach (string protocol in protocols) { Validate.NotEmpty(protocol); Whitelist.Protocol prot = Whitelist.Protocol.ValueOf(protocol); protSet.Add(prot); } return(this); }
/// <summary> /// Test if the supplied attribute is allowed by this whitelist for this tag /// </summary> /// <param name="tagName">tag to consider allowing the attribute in</param> /// <param name="el">element under test, to confirm protocol</param> /// <param name="attr">attribute under test</param> /// <returns>true if allowed</returns> internal bool IsSafeAttribute(string tagName, Element el, Nodes.Attribute attr) { Whitelist.TagName tag = Whitelist.TagName.ValueOf(tagName); Whitelist.AttributeKey key = Whitelist.AttributeKey.ValueOf(attr.Key); if (attributes.ContainsKey(tag)) { if (attributes[tag].Contains(key)) { if (protocols.ContainsKey(tag)) { IDictionary <Whitelist.AttributeKey, ICollection <Whitelist.Protocol> > attrProts = protocols[tag]; // ok if not defined protocol; otherwise test return(!attrProts.ContainsKey(key) || TestValidProtocol(el, attr, attrProts[key])); } else { // attribute found, no protocols defined, so OK return(true); } } } // no attributes defined for tag, try :all tag return(!tagName.Equals(":all") && IsSafeAttribute(":all", el, attr)); }
/// <summary> /// Add an enforced attribute to a tag. /// </summary> /// <remarks> /// An enforced attribute will always be added to the element. If the element /// already has the attribute set, it will be overridden. /// <p/> /// E.g.: <c>AddEnforcedAttribute("a", "rel", "nofollow")</c> will make all <c>a</c> tags output as /// <c><a href="..." rel="nofollow"></c> /// </remarks> /// <param name="tag">The tag the enforced attribute is for. The tag will be added to the allowed tag list if necessary. /// </param> /// <param name="key">The attribute key</param> /// <param name="value">The enforced attribute value</param> /// <returns>this (for chaining)</returns> public Whitelist AddEnforcedAttribute(string tag, string key, string value) { Validate.NotEmpty(tag); Validate.NotEmpty(key); Validate.NotEmpty(value); Whitelist.TagName tagName = Whitelist.TagName.ValueOf(tag); if (!tagNames.Contains(tagName)) { tagNames.Add(tagName); } Whitelist.AttributeKey attrKey = Whitelist.AttributeKey.ValueOf(key); Whitelist.AttributeValue attrVal = Whitelist.AttributeValue.ValueOf(value); if (enforcedAttributes.ContainsKey(tagName)) { enforcedAttributes[tagName][attrKey] = attrVal; } else { IDictionary <Whitelist.AttributeKey, Whitelist.AttributeValue> attrMap = new Dictionary <Whitelist.AttributeKey, Whitelist.AttributeValue>(); attrMap[attrKey] = attrVal; enforcedAttributes[tagName] = attrMap; } return(this); }