/* * (non-Javadoc) * * @see org.w3c.css.sac.DocumentHandler#ignorableAtRule(java.lang.String) */ public virtual void ignorableAtRule(string atRule) { // this method is called when the parser hits an unrecognized // @-rule. Like the page/media/font declarations, this is // CSS2+ stuff //string msg = "The @-rule <u>" + HTMLEntityEncoder.htmlEntityEncode(atRule) + "</u> could not be processed for security reasons."; if (tagName != null) { /* * errorMessages.Add( * ErrorMessageUtil.getMessage(ErrorMessageUtil.ERROR_CSS_TAG_RULE_NOTFOUND, * new Object[] { * HTMLEntityEncoder.htmlEntityEncode(tagName), * HTMLEntityEncoder.htmlEntityEncode(atRule) * })); */ errorMessages.Add(HTMLEntityEncoder.htmlEntityEncode(tagName)); } else { /* * errorMessages.Add(ErrorMessageUtil.getMessage( * ErrorMessageUtil.ERROR_STYLESHEET_RULE_NOTFOUND, * new Object[] { * HTMLEntityEncoder.htmlEntityEncode(atRule) * })); */ } }
private void recursiveValidateTag(HtmlNode node) { int maxinputsize = int.Parse(policy.getDirective("maxInputSize")); num++; HtmlNode parentNode = node.ParentNode; HtmlNode tmp = null; string tagName = node.Name; //check this out //might not be robust enough if (tagName.ToLower().Equals("#text")) // || tagName.ToLower().Equals("#comment")) { return; } Tag tag = policy.getTagByName(tagName.ToLower()); if (tag == null || "filter".Equals(tag.Action)) { StringBuilder errBuff = new StringBuilder(); if (tagName == null || tagName.Trim().Equals("")) { errBuff.Append("An unprocessable "); } else { errBuff.Append("The <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName.ToLower()) + "</b> "); } errBuff.Append("tag has been filtered for security reasons. The contents of the tag will "); errBuff.Append("remain in place."); errorMessages.Add(errBuff.ToString()); for (int i = 0; i < node.ChildNodes.Count; i++) { tmp = node.ChildNodes[i]; recursiveValidateTag(tmp); if (tmp.ParentNode == null) { i--; } } promoteChildren(node); return; } else if ("validate".Equals(tag.Action)) { if ("style".Equals(tagName.ToLower()) && policy.getTagByName("style") != null) { CssScanner styleScanner = new CssScanner(policy); try { CleanResults cr = styleScanner.scanStyleSheet(node.FirstChild.InnerHtml, maxinputsize); foreach (string msg in cr.getErrorMessages()) { errorMessages.Add(msg.ToString()); } /* * If IE gets an empty style tag, i.e. <style/> * it will break all CSS on the page. I wish I * was kidding. So, if after validation no CSS * properties are left, we would normally be left * with an empty style tag and break all CSS. To * prevent that, we have this check. */ if (cr.getCleanHTML() == null || cr.getCleanHTML().Equals("")) { //node.getFirstChild().setNodeValue("/* */"); node.FirstChild.InnerHtml = "/* */"; } else { //node.getFirstChild().setNodeValue(cr.getCleanHTML()); node.FirstChild.InnerHtml = cr.getCleanHTML(); } } // catch (DomException e) // { // addError(ErrorMessageUtil.ERROR_CSS_TAG_MALFORMED, new Object[] { HTMLEntityEncoder.htmlEntityEncode(node.getFirstChild().getNodeValue()) }); // parentNode.removeChild(node); // } catch (ScanException e) { Console.WriteLine("Scan Exception: " + e.Message); //addError(ErrorMessageUtil.ERROR_CSS_TAG_MALFORMED, new Object[] { HTMLEntityEncoder.htmlEntityEncode(node.getFirstChild().getNodeValue()) }); parentNode.RemoveChild(node); } } HtmlAttribute attribute = null; for (int currentAttributeIndex = 0; currentAttributeIndex < node.Attributes.Count; currentAttributeIndex++) { attribute = node.Attributes[currentAttributeIndex]; string name = attribute.Name; string _value = attribute.Value; Attribute attr = tag.getAttributeByName(name); if (attr == null) { attr = policy.getGlobalAttributeByName(name); } bool isAttributeValid = false; if ("style".Equals(name.ToLower()) && attr != null) { CssScanner styleScanner = new CssScanner(policy); try { CleanResults cr = styleScanner.scanInlineStyle(_value, tagName, maxinputsize); //attribute.setNodeValue(cr.getCleanHTML()); attribute.Value = cr.getCleanHTML(); ArrayList cssScanErrorMessages = cr.getErrorMessages(); foreach (string msg in cr.getErrorMessages()) { errorMessages.Add(msg.ToString()); } } /* * catch (DOMException e) * { * * addError(ErrorMessageUtil.ERROR_CSS_ATTRIBUTE_MALFORMED, new Object[] { tagName, HTMLEntityEncoder.htmlEntityEncode(node.getNodeValue()) }); * * ele.removeAttribute(name); * currentAttributeIndex--; * * } */ catch (ScanException ex) { Console.WriteLine(ex.Message); //addError(ErrorMessageUtil.ERROR_CSS_ATTRIBUTE_MALFORMED, new Object[] { tagName, HTMLEntityEncoder.htmlEntityEncode(node.getNodeValue()) }); //ele.removeAttribute(name); currentAttributeIndex--; } } else { if (attr != null) { //try to find out how robust this is - do I need to do this in a loop? _value = HtmlEntity.DeEntitize(_value); foreach (string allowedValue in attr.AllowedValues) { if (isAttributeValid) { break; } if (allowedValue != null && allowedValue.ToLower().Equals(_value.ToLower())) { isAttributeValid = true; } } foreach (string ptn in attr.AllowedRegExp) { if (isAttributeValid) { break; } string pattern = "^" + ptn + "$"; Match m = Regex.Match(_value, pattern); if (m.Success) { isAttributeValid = true; } } if (!isAttributeValid) { string onInvalidAction = attr.OnInvalid; StringBuilder errBuff = new StringBuilder(); errBuff.Append("The <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag contained an attribute that we couldn't process. "); errBuff.Append("The <b>" + HTMLEntityEncoder.htmlEntityEncode(name) + "</b> attribute had a value of <u>" + HTMLEntityEncoder.htmlEntityEncode(_value) + "</u>. "); errBuff.Append("This value could not be accepted for security reasons. We have chosen to "); //Console.WriteLine(policy); if ("removeTag".Equals(onInvalidAction)) { parentNode.RemoveChild(node); errBuff.Append("remove the <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag and its contents in order to process this input. "); } else if ("filterTag".Equals(onInvalidAction)) { for (int i = 0; i < node.ChildNodes.Count; i++) { tmp = node.ChildNodes[i]; recursiveValidateTag(tmp); if (tmp.ParentNode == null) { i--; } } promoteChildren(node); errBuff.Append("filter the <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag and leave its contents in place so that we could process this input."); } else { node.Attributes.Remove(attr.Name); currentAttributeIndex--; errBuff.Append("remove the <b>" + HTMLEntityEncoder.htmlEntityEncode(name) + "</b> attribute from the tag and leave everything else in place so that we could process this input."); } errorMessages.Add(errBuff.ToString()); if ("removeTag".Equals(onInvalidAction) || "filterTag".Equals(onInvalidAction)) { return; // can't process any more if we remove/filter the tag } } } else { StringBuilder errBuff = new StringBuilder(); errBuff.Append("The <b>" + HTMLEntityEncoder.htmlEntityEncode(name)); errBuff.Append("</b> attribute of the <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag has been removed for security reasons. "); errBuff.Append("This removal should not affect the display of the HTML submitted."); errorMessages.Add(errBuff.ToString()); node.Attributes.Remove(name); currentAttributeIndex--; } // end if attribute is or is not found in policy file } // end if style.equals("name") } // end while loop through attributes for (int i = 0; i < node.ChildNodes.Count; i++) { tmp = node.ChildNodes[i]; recursiveValidateTag(tmp); if (tmp.ParentNode == null) { i--; } } } else if ("truncate".Equals(tag.Action)) { Console.WriteLine("truncate"); HtmlAttributeCollection nnmap = node.Attributes; while (nnmap.Count > 0) { StringBuilder errBuff = new StringBuilder(); errBuff.Append("The <b>" + HTMLEntityEncoder.htmlEntityEncode(nnmap[0].Name)); errBuff.Append("</b> attribute of the <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag has been removed for security reasons. "); errBuff.Append("This removal should not affect the display of the HTML submitted."); node.Attributes.Remove(nnmap[0].Name); errorMessages.Add(errBuff.ToString()); } HtmlNodeCollection cList = node.ChildNodes; int i = 0; int j = 0; int length = cList.Count; while (i < length) { HtmlNode nodeToRemove = cList[j]; if (nodeToRemove.NodeType != HtmlNodeType.Text && nodeToRemove.NodeType != HtmlNodeType.Comment) { node.RemoveChild(nodeToRemove); } else { j++; } i++; } } else { errorMessages.Add("The <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag has been removed for security reasons."); parentNode.RemoveChild(node); } }