From 95b0f24a09f26451ea15b6297e3558f9025569b1 Mon Sep 17 00:00:00 2001 From: "sayrer%gmail.com" Date: Sat, 12 Aug 2006 04:46:43 +0000 Subject: [PATCH] Bug 340554. Provide sanitizing fragment sinks for use with feeds. r=mrbkap. sr=jst git-svn-id: svn://10.0.0.236/trunk@207207 18797224-902f-48f8-a5cc-f745e15eee43 --- .../components/feeds/src/FeedWriter.js | 44 +-- mozilla/content/base/public/nsContentCID.h | 8 + mozilla/content/base/src/nsContentSink.h | 161 ++++++++ mozilla/content/base/src/nsContentUtils.cpp | 5 + mozilla/content/base/src/nsGkAtomList.h | 6 + .../src/nsHTMLFragmentContentSink.cpp | 365 +++++++++++++++++- .../xml/document/src/nsXMLContentSink.h | 2 +- .../document/src/nsXMLFragmentContentSink.cpp | 322 +++++++++++++++ mozilla/layout/build/nsLayoutModule.cpp | 12 + mozilla/layout/generic/nsHTMLParts.h | 6 + .../public/nsIFragmentContentSink.h | 11 + .../feeds/public/nsIFeedTextConstruct.idl | 9 +- .../public/nsIScriptableUnescapeHTML.idl | 14 +- .../components/feeds/src/FeedProcessor.js | 21 + .../toolkit/components/feeds/src/Makefile.in | 1 + .../feeds/src/nsScriptableUnescapeHTML.cpp | 127 +++++- 16 files changed, 1082 insertions(+), 32 deletions(-) diff --git a/mozilla/browser/components/feeds/src/FeedWriter.js b/mozilla/browser/components/feeds/src/FeedWriter.js index 50ed660262e..5959eb067ac 100755 --- a/mozilla/browser/components/feeds/src/FeedWriter.js +++ b/mozilla/browser/components/feeds/src/FeedWriter.js @@ -56,6 +56,7 @@ function LOG(str) { dump("*** Feeds: " + str + "\n"); } +const XML_NS = "http://www.w3.org/XML/1998/namespace" const HTML_NS = "http://www.w3.org/1999/xhtml"; const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed"; const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties"; @@ -196,9 +197,6 @@ FeedWriter.prototype = { * The container of entries in the feed */ _writeFeedContent: function FW__writeFeedContent(container) { - // XXXben - do something with this. parameterize? - const MAX_CHARS = 600; - // Build the actual feed content var feedContent = this._document.getElementById("feedContent"); var feed = container.QueryInterface(Ci.nsIFeed); @@ -209,7 +207,7 @@ FeedWriter.prototype = { var entryContainer = this._document.createElementNS(HTML_NS, "div"); entryContainer.className = "entry"; - + // If the entry has a title, make it a like if (entry.title) { var a = this._document.createElementNS(HTML_NS, "a"); @@ -224,31 +222,31 @@ FeedWriter.prototype = { entryContainer.appendChild(title); } - - var body = this._document.createElementNS(HTML_NS, "p"); var summary = entry.summary || entry.content; - if (summary) - summary = summary.plainText(); - if (summary && summary.length > MAX_CHARS) - summary = summary.substring(0, MAX_CHARS) + "..."; + var docFragment = null; + if (summary) { - // XXXben - Change to use innerHTML - body.appendChild(this._document.createTextNode(summary)); - body.className = "feedEntryContent"; + if (summary.base) + body.setAttributeNS(XML_NS, "base", summary.base.spec); + else + LOG("no base?"); + docFragment = summary.createDocumentFragment(body); + body.appendChild(docFragment); + + // If the entry doesn't have a title, append a # permalink + // See http://scripting.com/rss.xml for an example + if (!entry.title && entry.link) { + var a = this._document.createElementNS(HTML_NS, "a"); + a.appendChild(this._document.createTextNode("#")); + this._safeSetURIAttribute(a, "href", entry.link.spec); + body.appendChild(this._document.createTextNode(" ")); + body.appendChild(a); + } - // If the entry doesn't have a title, append a # permalink - // See http://scripting.com/rss.xml for an example - if (!entry.title && entry.link) { - var a = this._document.createElementNS(HTML_NS, "a"); - a.appendChild(this._document.createTextNode("#")); - this._safeSetURIAttribute(a, "href", entry.link.spec); - body.appendChild(this._document.createTextNode(" ")); - body.appendChild(a); } - + body.className = "feedEntryContent"; entryContainer.appendChild(body); - feedContent.appendChild(entryContainer); } }, diff --git a/mozilla/content/base/public/nsContentCID.h b/mozilla/content/base/public/nsContentCID.h index 12bc9e916a4..4e1729dc4a2 100644 --- a/mozilla/content/base/public/nsContentCID.h +++ b/mozilla/content/base/public/nsContentCID.h @@ -223,6 +223,10 @@ #define NS_HTMLFRAGMENTSINK2_CID \ { 0x13111d00, 0xce81, 0x11d6, { 0x80, 0x82, 0xec, 0xf3, 0x66, 0x5a, 0xf6, 0x7c } } +// {A47E9526-6E48-4574-9D6C-3164E271F74E} +#define NS_HTMLPARANOIDFRAGMENTSINK_CID \ +{ 0xa47e9526, 0x6e48, 0x4574, { 0x9d, 0x6c, 0x31, 0x64, 0xe2, 0x71, 0xf7, 0x4e } } + // {4B664E54-72A2-4bbf-A5C2-66D4DC3066A0} #define NS_XMLFRAGMENTSINK_CID \ { 0x4b664e54, 0x72a2, 0x4bbf, { 0xa5, 0xc2, 0x66, 0xd4, 0xdc, 0x30, 0x66, 0xa0 } } @@ -231,6 +235,10 @@ #define NS_XMLFRAGMENTSINK2_CID \ { 0x4dc30689, 0x929d, 0x425e, { 0xa7, 0x9, 0x8, 0x2c, 0x62, 0x94, 0xe5, 0x42 } } +// {2D78BBF0-E26C-482B-92B3-78A7B2AFC8F7} +#define NS_XHTMLPARANOIDFRAGMENTSINK_CID \ +{ 0x2d78bbf0, 0xe26c, 0x482b, { 0x92, 0xb3, 0x78, 0xa7, 0xb2, 0xaf, 0xc8, 0xf7} } + // {3986B301-097C-11d3-BF87-00105A1B0627} #define NS_XULPOPUPLISTENER_CID \ { 0x3986b301, 0x97c, 0x11d3, { 0xbf, 0x87, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } } diff --git a/mozilla/content/base/src/nsContentSink.h b/mozilla/content/base/src/nsContentSink.h index 4252fee1b31..beb74adce15 100644 --- a/mozilla/content/base/src/nsContentSink.h +++ b/mozilla/content/base/src/nsContentSink.h @@ -52,6 +52,9 @@ #include "nsCOMArray.h" #include "nsString.h" #include "nsAutoPtr.h" +#include "nsHTMLAtoms.h" +#include "nsTHashtable.h" +#include "nsHashKeys.h" class nsIDocument; class nsIURI; @@ -125,4 +128,162 @@ protected: PRBool mNeedToBlockParser; }; +// these two lists are used by the sanitizing fragment serializers +static nsIAtom** const kDefaultAllowedTags [] = { + &nsHTMLAtoms::a, + &nsHTMLAtoms::abbr, + &nsHTMLAtoms::acronym, + &nsHTMLAtoms::address, + &nsHTMLAtoms::area, + &nsHTMLAtoms::b, + &nsHTMLAtoms::big, + &nsHTMLAtoms::blockquote, + &nsHTMLAtoms::br, + &nsHTMLAtoms::button, + &nsHTMLAtoms::caption, + &nsHTMLAtoms::center, + &nsHTMLAtoms::cite, + &nsHTMLAtoms::code, + &nsHTMLAtoms::col, + &nsHTMLAtoms::colgroup, + &nsHTMLAtoms::dd, + &nsHTMLAtoms::del, + &nsHTMLAtoms::dfn, + &nsHTMLAtoms::dir, + &nsHTMLAtoms::div, + &nsHTMLAtoms::dl, + &nsHTMLAtoms::dt, + &nsHTMLAtoms::em, + &nsHTMLAtoms::fieldset, + &nsHTMLAtoms::font, + &nsHTMLAtoms::form, + &nsHTMLAtoms::h1, + &nsHTMLAtoms::h2, + &nsHTMLAtoms::h3, + &nsHTMLAtoms::h4, + &nsHTMLAtoms::h5, + &nsHTMLAtoms::h6, + &nsHTMLAtoms::hr, + &nsHTMLAtoms::i, + &nsHTMLAtoms::img, + &nsHTMLAtoms::input, + &nsHTMLAtoms::ins, + &nsHTMLAtoms::kbd, + &nsHTMLAtoms::label, + &nsHTMLAtoms::legend, + &nsHTMLAtoms::li, + &nsHTMLAtoms::map, + &nsHTMLAtoms::menu, + &nsHTMLAtoms::ol, + &nsHTMLAtoms::optgroup, + &nsHTMLAtoms::option, + &nsHTMLAtoms::p, + &nsHTMLAtoms::pre, + &nsHTMLAtoms::q, + &nsHTMLAtoms::s, + &nsHTMLAtoms::samp, + &nsHTMLAtoms::select, + &nsHTMLAtoms::small, + &nsHTMLAtoms::span, + &nsHTMLAtoms::strike, + &nsHTMLAtoms::strong, + &nsHTMLAtoms::sub, + &nsHTMLAtoms::sup, + &nsHTMLAtoms::table, + &nsHTMLAtoms::tbody, + &nsHTMLAtoms::td, + &nsHTMLAtoms::textarea, + &nsHTMLAtoms::tfoot, + &nsHTMLAtoms::th, + &nsHTMLAtoms::thead, + &nsHTMLAtoms::tr, + &nsHTMLAtoms::tt, + &nsHTMLAtoms::u, + &nsHTMLAtoms::ul +}; + +static nsIAtom** const kDefaultAllowedAttributes [] = { + &nsHTMLAtoms::accept, + &nsHTMLAtoms::acceptcharset, + &nsHTMLAtoms::accesskey, + &nsHTMLAtoms::action, + &nsHTMLAtoms::align, + &nsHTMLAtoms::alt, + &nsHTMLAtoms::axis, + &nsHTMLAtoms::border, + &nsHTMLAtoms::cellpadding, + &nsHTMLAtoms::cellspacing, + &nsHTMLAtoms::_char, + &nsHTMLAtoms::charoff, + &nsHTMLAtoms::charset, + &nsHTMLAtoms::checked, + &nsHTMLAtoms::cite, + &nsHTMLAtoms::_class, + &nsHTMLAtoms::clear, + &nsHTMLAtoms::cols, + &nsHTMLAtoms::colspan, + &nsHTMLAtoms::color, + &nsHTMLAtoms::compact, + &nsHTMLAtoms::coords, + &nsHTMLAtoms::datetime, + &nsHTMLAtoms::dir, + &nsHTMLAtoms::disabled, + &nsHTMLAtoms::enctype, + &nsHTMLAtoms::_for, + &nsHTMLAtoms::frame, + &nsHTMLAtoms::headers, + &nsHTMLAtoms::height, + &nsHTMLAtoms::href, + &nsHTMLAtoms::hreflang, + &nsHTMLAtoms::hspace, + &nsHTMLAtoms::id, + &nsHTMLAtoms::ismap, + &nsHTMLAtoms::label, + &nsHTMLAtoms::lang, + &nsHTMLAtoms::longdesc, + &nsHTMLAtoms::maxlength, + &nsHTMLAtoms::media, + &nsHTMLAtoms::method, + &nsHTMLAtoms::multiple, + &nsHTMLAtoms::name, + &nsHTMLAtoms::nohref, + &nsHTMLAtoms::noshade, + &nsHTMLAtoms::nowrap, + &nsHTMLAtoms::prompt, + &nsHTMLAtoms::readonly, + &nsHTMLAtoms::rel, + &nsHTMLAtoms::rev, + &nsHTMLAtoms::rows, + &nsHTMLAtoms::rowspan, + &nsHTMLAtoms::rules, + &nsHTMLAtoms::scope, + &nsHTMLAtoms::selected, + &nsHTMLAtoms::shape, + &nsHTMLAtoms::size, + &nsHTMLAtoms::span, + &nsHTMLAtoms::src, + &nsHTMLAtoms::start, + &nsHTMLAtoms::summary, + &nsHTMLAtoms::tabindex, + &nsHTMLAtoms::target, + &nsHTMLAtoms::title, + &nsHTMLAtoms::type, + &nsHTMLAtoms::usemap, + &nsHTMLAtoms::valign, + &nsHTMLAtoms::value, + &nsHTMLAtoms::vspace, + &nsHTMLAtoms::width +}; + +// URIs action, href, src, longdesc, usemap, cite +static +PRBool IsAttrURI(nsIAtom *aName) +{ + return (aName == nsHTMLAtoms::action || + aName == nsHTMLAtoms::href || + aName == nsHTMLAtoms::src || + aName == nsHTMLAtoms::longdesc || + aName == nsHTMLAtoms::usemap || + aName == nsHTMLAtoms::cite); +} #endif // _nsContentSink_h_ diff --git a/mozilla/content/base/src/nsContentUtils.cpp b/mozilla/content/base/src/nsContentUtils.cpp index 6d1a5e6ef42..e909eff6549 100644 --- a/mozilla/content/base/src/nsContentUtils.cpp +++ b/mozilla/content/base/src/nsContentUtils.cpp @@ -135,6 +135,8 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #include "nsIEventListenerManager.h" #include "nsAttrName.h" #include "nsIDOMUserDataHandler.h" +#include "nsIFragmentContentSink.h" + #ifdef IBMBIDI #include "nsIBidiKeyboard.h" #endif @@ -601,6 +603,9 @@ nsContentUtils::Shutdown() { sInitialized = PR_FALSE; + NS_HTMLParanoidFragmentSinkShutdown(); + NS_XHTMLParanoidFragmentSinkShutdown(); + NS_IF_RELEASE(sContentPolicyService); sTriedToGetContentPolicy = PR_FALSE; PRInt32 i; diff --git a/mozilla/content/base/src/nsGkAtomList.h b/mozilla/content/base/src/nsGkAtomList.h index 368c2480dd6..cd0dcca4457 100755 --- a/mozilla/content/base/src/nsGkAtomList.h +++ b/mozilla/content/base/src/nsGkAtomList.h @@ -76,9 +76,11 @@ GK_ATOM(acceltext, "acceltext") GK_ATOM(accept, "accept") GK_ATOM(acceptcharset, "accept-charset") GK_ATOM(accesskey, "accesskey") +GK_ATOM(acronym, "acronym") GK_ATOM(action, "action") GK_ATOM(active, "active") GK_ATOM(actuate, "actuate") +GK_ATOM(address, "address") GK_ATOM(after, "after") GK_ATOM(after_end, "after_end") GK_ATOM(after_start, "after_start") @@ -404,6 +406,7 @@ GK_ATOM(iscontainer, "iscontainer") GK_ATOM(isempty, "isempty") GK_ATOM(isindex, "isindex") GK_ATOM(ismap, "ismap") +GK_ATOM(kbd, "kbd") GK_ATOM(key, "key") GK_ATOM(keycode, "keycode") GK_ATOM(keydown, "keydown") @@ -676,6 +679,7 @@ GK_ATOM(rtl, "rtl") GK_ATOM(rule, "rule") GK_ATOM(rules, "rules") GK_ATOM(s, "s") +GK_ATOM(samp, "samp") GK_ATOM(scheme, "scheme") GK_ATOM(scope, "scope") GK_ATOM(screen, "screen") @@ -751,7 +755,9 @@ GK_ATOM(substate, "substate") GK_ATOM(substring, "substring") GK_ATOM(substringAfter, "substring-after") GK_ATOM(substringBefore, "substring-before") +GK_ATOM(sub, "sub") GK_ATOM(sum, "sum") +GK_ATOM(sup, "sup") GK_ATOM(summary, "summary") GK_ATOM(systemProperty, "system-property") GK_ATOM(tab, "tab") diff --git a/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp b/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp index 22d2b9621db..c660cfe0a4d 100644 --- a/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp @@ -21,6 +21,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Robert Sayre * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -61,6 +62,8 @@ #include "nsContentCreatorFunctions.h" #include "nsNetUtil.h" #include "nsIScriptSecurityManager.h" +#include "nsContentSink.h" +#include "nsTHashtable.h" // // XXX THIS IS TEMPORARY CODE @@ -120,8 +123,8 @@ public: PRInt32 PushContent(nsIContent *aContent); nsIContent* PopContent(); - nsresult AddAttributes(const nsIParserNode& aNode, - nsIContent* aContent); + virtual nsresult AddAttributes(const nsIParserNode& aNode, + nsIContent* aContent); nsresult AddText(const nsAString& aString); nsresult AddTextToContent(nsIContent* aContent, const nsAString& aText); @@ -821,3 +824,361 @@ nsHTMLFragmentContentSink::AddAttributes(const nsIParserNode& aNode, return NS_OK; } + +// nsHTMLParanoidFragmentSink + +// Find the whitelist of allowed elements and attributes in +// nsContentSink.h We share it with nsHTMLParanoidFragmentSink + +class nsHTMLParanoidFragmentSink : public nsHTMLFragmentContentSink +{ +public: + nsHTMLParanoidFragmentSink(); + + static nsresult Init(); + static void Cleanup(); + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + NS_IMETHOD OpenContainer(const nsIParserNode& aNode); + NS_IMETHOD CloseContainer(const nsHTMLTag aTag); + NS_IMETHOD AddLeaf(const nsIParserNode& aNode); + NS_IMETHOD AddComment(const nsIParserNode& aNode); + NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode); + + nsresult AddAttributes(const nsIParserNode& aNode, + nsIContent* aContent); +protected: + nsresult NameFromType(const nsHTMLTag aTag, + nsIAtom **aResult); + + nsresult NameFromNode(const nsIParserNode& aNode, + nsIAtom **aResult); + + PRBool mSkip; // used when we descend into