diff --git a/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java b/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java index e4023d4d14372e32b282bd6d38a7ead5e3242485..f3b01bdd9ee81cd7fa3bd074ab7c3fa77165f657 100644 --- a/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java +++ b/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java @@ -16,6 +16,7 @@ import java.util.Set; import net.i2p.I2PAppContext; import net.i2p.util.Log; import org.cybergarage.util.Debug; +import org.cybergarage.xml.Attribute; import org.cybergarage.xml.Node; import org.cybergarage.xml.ParserException; @@ -43,18 +44,34 @@ public class NewsXMLParser { XMLParser.TEXT_NAME })); + // http://www.w3.org/TR/html-markup/global-attributes.html#common.attrs.event-handler + private static final Set attributeBlacklist = new HashSet(Arrays.asList(new String[] { + "onabort", "onblur", "oncanplay", "oncanplaythrough", "onchange", "onclick", + "oncontextmenu", "ondblclick", "ondrag", "ondragend", "ondragenter", "ondragleave", + "ondragover", "ondragstart", "ondrop", "ondurationchange", "onemptied", + "onended", "onerror", "onfocus", "oninput", "onivalid", "onkeydown", "onkeypress", + "onkeyup", "onload", "onloadeddata", "onloadedmetadata", "onloadstart", + "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup", + "onmousewheel", "onpause", "onplay", "onplaying", "onprogress", "onratechange", + "onreadystatechange", "onreset", "onscroll", "onseeked", "onseeking", "onselect", + "onshow", "onstalled", "onsubmit", "onsuspend", + "ontimeupdate", "onvolumechange", "onwaiting" + })); + /** * The action taken when encountering a non-whitelisted - * XHTML element in the feed content. + * XHTML element or blacklisted attribute in the feed content. */ public enum XHTMLMode { - /** abort the parsing on any non-whitelisted element */ + /** abort the parsing on any non-whitelisted element or blacklisted attribute */ ABORT, - /** remove only the non-whitelisted element */ + /** remove only the non-whitelisted element, or element containing a blacklisted attribute */ REMOVE_ELEMENT, - /** skip the feed entry containing the non-whitelisted element */ + /** remove only the non-whitelisted element, remove only the blacklisted attribute */ + REMOVE_ATTRIBUTE, + /** skip the feed entry containing the non-whitelisted element or blacklisted attribute */ SKIP_ENTRY, - /** disable whitelist checks */ + /** disable all whitelist and blacklist checks */ ALLOW_ALL } @@ -245,6 +262,7 @@ public class NewsXMLParser { _log.warn("Skipping entry", ipe); e = null; break; + case REMOVE_ATTRIBUTE: case REMOVE_ELEMENT: if (_log.shouldLog(Log.WARN)) _log.warn("Removing element", ipe); @@ -295,8 +313,8 @@ public class NewsXMLParser { case ABORT: case SKIP_ENTRY: throw new I2PParserException("Invalid XHTML element \"" + name + '"'); + case REMOVE_ATTRIBUTE: case REMOVE_ELEMENT: - // fixme this screws up the iteration if (_log.shouldLog(Log.WARN)) _log.warn("Removing element: " + node); node.getParentNode().removeNode(node); @@ -307,6 +325,33 @@ public class NewsXMLParser { break; } } + for (int i = 0; i < node.getNAttributes(); i++) { + Attribute attr = node.getAttribute(i); + String aname = attr.getName(); + if (attributeBlacklist.contains(aname.toLowerCase(Locale.US))) { + switch (_mode) { + case ABORT: + case SKIP_ENTRY: + throw new I2PParserException("Invalid XHTML element \"" + name + "\" due to attribute " + aname); + case REMOVE_ELEMENT: + if (_log.shouldLog(Log.WARN)) + _log.warn("Removing element: " + node + " due to attribute " + aname); + node.getParentNode().removeNode(node); + return true; + case REMOVE_ATTRIBUTE: + if (_log.shouldLog(Log.WARN)) + _log.warn("Removing attribute: " + aname + " from " + node); + // sadly, no removeAttribute(int) + if (node.removeAttribute(attr)) + i--; + break; + case ALLOW_ALL: + if (_log.shouldLog(Log.WARN)) + _log.warn("Allowing blacklisted attribute by configuration: " + node); + break; + } + } + } int count = node.getNNodes(); for (int i = 0; i < node.getNNodes(); i++) { boolean removed = validate(node.getNode(i)); @@ -334,10 +379,12 @@ public class NewsXMLParser { I2PAppContext ctx = new I2PAppContext(); Debug.initialize(ctx); NewsXMLParser parser = new NewsXMLParser(ctx); - parser.setXHTMLMode(XHTMLMode.ABORT); - //parser.setXHTMLMode(XHTMLMode.REMOVE_ELEMENT); - //parser.setXHTMLMode(XHTMLMode.SKIP_ENTRY); - //parser.setXHTMLMode(XHTMLMode.ALLOW_ALL); + if (args.length > 1) { + XHTMLMode mode = XHTMLMode.valueOf(args[1]); + parser.setXHTMLMode(mode); + } else { + parser.setXHTMLMode(XHTMLMode.ABORT); + } parser.parse(new File(args[0])); NewsMetadata ud = parser.getMetadata(); List<NewsEntry> entries = parser.getEntries();