diff options
author | mikesamuel <mikesamuel@ad8eed46-c659-4a31-e19d-951d88f54425> | 2011-04-04 23:27:09 +0000 |
---|---|---|
committer | mikesamuel <mikesamuel@ad8eed46-c659-4a31-e19d-951d88f54425> | 2011-04-04 23:27:09 +0000 |
commit | 8560af5e2982092cb27cce62aa9cfa5bb45ea387 (patch) | |
tree | 545c85e3e4dc53ea86530ef0508dc66b59cd05f4 /distrib | |
parent | 846d5d0377617bd20ac271a486f07bfe757cc7a2 (diff) | |
download | sanitizer-8560af5e2982092cb27cce62aa9cfa5bb45ea387.tar.gz |
Fixed CDATA rendering
git-svn-id: http://owasp-java-html-sanitizer.googlecode.com/svn/trunk@27 ad8eed46-c659-4a31-e19d-951d88f54425
Diffstat (limited to 'distrib')
-rw-r--r-- | distrib/javadoc/org/owasp/html/HtmlStreamRenderer.html | 2 | ||||
-rw-r--r-- | distrib/javadoc/src-html/org/owasp/html/HtmlStreamRenderer.html | 354 | ||||
-rw-r--r-- | distrib/lib/owasp-java-html-sanitizer-src.jar | bin | 70302 -> 70636 bytes | |||
-rw-r--r-- | distrib/lib/owasp-java-html-sanitizer.jar | bin | 79724 -> 79877 bytes |
4 files changed, 192 insertions, 164 deletions
diff --git a/distrib/javadoc/org/owasp/html/HtmlStreamRenderer.html b/distrib/javadoc/org/owasp/html/HtmlStreamRenderer.html index 6d2639c..8ef44ae 100644 --- a/distrib/javadoc/org/owasp/html/HtmlStreamRenderer.html +++ b/distrib/javadoc/org/owasp/html/HtmlStreamRenderer.html @@ -328,7 +328,7 @@ public final void <A HREF="../../../src-html/org/owasp/html/HtmlStreamRenderer.h <A NAME="text(java.lang.String)"><!-- --></A><H3> text</H3> <PRE> -public final void <A HREF="../../../src-html/org/owasp/html/HtmlStreamRenderer.html#line.215"><B>text</B></A>(java.lang.String text)</PRE> +public final void <A HREF="../../../src-html/org/owasp/html/HtmlStreamRenderer.html#line.221"><B>text</B></A>(java.lang.String text)</PRE> <DL> <DD><DL> <DT><B>Specified by:</B><DD><CODE><A HREF="../../../org/owasp/html/HtmlStreamEventReceiver.html#text(java.lang.String)">text</A></CODE> in interface <CODE><A HREF="../../../org/owasp/html/HtmlStreamEventReceiver.html" title="interface in org.owasp.html">HtmlStreamEventReceiver</A></CODE></DL> diff --git a/distrib/javadoc/src-html/org/owasp/html/HtmlStreamRenderer.html b/distrib/javadoc/src-html/org/owasp/html/HtmlStreamRenderer.html index 40dce0e..380cbfe 100644 --- a/distrib/javadoc/src-html/org/owasp/html/HtmlStreamRenderer.html +++ b/distrib/javadoc/src-html/org/owasp/html/HtmlStreamRenderer.html @@ -201,175 +201,203 @@ <FONT color="green">198</FONT> error("Tag content cannot appear inside CDATA element", elementName);<a name="line.198"></a> <FONT color="green">199</FONT> return;<a name="line.199"></a> <FONT color="green">200</FONT> } else {<a name="line.200"></a> -<FONT color="green">201</FONT> String unescaped = pendingUnescaped.toString();<a name="line.201"></a> +<FONT color="green">201</FONT> StringBuilder cdataContent = pendingUnescaped;<a name="line.201"></a> <FONT color="green">202</FONT> pendingUnescaped = null;<a name="line.202"></a> -<FONT color="green">203</FONT> if (!containsCloseTag(unescaped, lastTagOpened)) {<a name="line.203"></a> -<FONT color="green">204</FONT> output.append(unescaped);<a name="line.204"></a> -<FONT color="green">205</FONT> } else {<a name="line.205"></a> -<FONT color="green">206</FONT> error("Unescaped text content contains close tag", elementName);<a name="line.206"></a> -<FONT color="green">207</FONT> // Still output the close tag.<a name="line.207"></a> -<FONT color="green">208</FONT> }<a name="line.208"></a> -<FONT color="green">209</FONT> }<a name="line.209"></a> -<FONT color="green">210</FONT> if ("plaintext".equals(elementName)) { return; }<a name="line.210"></a> -<FONT color="green">211</FONT> }<a name="line.211"></a> -<FONT color="green">212</FONT> output.append("</").append(elementName).append(">");<a name="line.212"></a> -<FONT color="green">213</FONT> }<a name="line.213"></a> -<FONT color="green">214</FONT> <a name="line.214"></a> -<FONT color="green">215</FONT> public final void text(String text) {<a name="line.215"></a> -<FONT color="green">216</FONT> try {<a name="line.216"></a> -<FONT color="green">217</FONT> writeText(text);<a name="line.217"></a> -<FONT color="green">218</FONT> } catch (IOException ex) {<a name="line.218"></a> -<FONT color="green">219</FONT> ioExHandler.handle(ex);<a name="line.219"></a> -<FONT color="green">220</FONT> }<a name="line.220"></a> -<FONT color="green">221</FONT> }<a name="line.221"></a> -<FONT color="green">222</FONT> <a name="line.222"></a> -<FONT color="green">223</FONT> private final void writeText(String text) throws IOException {<a name="line.223"></a> -<FONT color="green">224</FONT> if (!open) { throw new IllegalStateException(); }<a name="line.224"></a> -<FONT color="green">225</FONT> if (pendingUnescaped != null) {<a name="line.225"></a> -<FONT color="green">226</FONT> pendingUnescaped.append(text.replaceAll("\0", ""));<a name="line.226"></a> -<FONT color="green">227</FONT> } else {<a name="line.227"></a> -<FONT color="green">228</FONT> escapeHtmlOnto(text, output); // Works for RCDATA.<a name="line.228"></a> -<FONT color="green">229</FONT> }<a name="line.229"></a> -<FONT color="green">230</FONT> }<a name="line.230"></a> -<FONT color="green">231</FONT> <a name="line.231"></a> -<FONT color="green">232</FONT> private static boolean containsCloseTag(String unescaped, String tagName) {<a name="line.232"></a> -<FONT color="green">233</FONT> boolean allowEscapingTextSpan = HtmlTextEscapingMode.allowsEscapingTextSpan(<a name="line.233"></a> -<FONT color="green">234</FONT> tagName);<a name="line.234"></a> -<FONT color="green">235</FONT> <a name="line.235"></a> -<FONT color="green">236</FONT> int unescapedLength = unescaped.length();<a name="line.236"></a> -<FONT color="green">237</FONT> int tagNameLength = tagName.length();<a name="line.237"></a> -<FONT color="green">238</FONT> int limit = unescapedLength - tagName.length() - 2;<a name="line.238"></a> -<FONT color="green">239</FONT> for (int i = -1; (i = unescaped.indexOf('<', i + 1)) >= 0;) {<a name="line.239"></a> -<FONT color="green">240</FONT> if (i <= limit && '/' == unescaped.charAt(i + 1)<a name="line.240"></a> -<FONT color="green">241</FONT> && Strings.regionMatchesIgnoreCase(<a name="line.241"></a> -<FONT color="green">242</FONT> unescaped, i + 2, tagName, 0, tagNameLength)) {<a name="line.242"></a> -<FONT color="green">243</FONT> // Content cannot be embedded.<a name="line.243"></a> -<FONT color="green">244</FONT> return true;<a name="line.244"></a> -<FONT color="green">245</FONT> } else if (allowEscapingTextSpan && i + 4 <= unescapedLength<a name="line.245"></a> -<FONT color="green">246</FONT> && '!' == unescaped.charAt(i + 1)<a name="line.246"></a> -<FONT color="green">247</FONT> && '-' == unescaped.charAt(i + 2)<a name="line.247"></a> -<FONT color="green">248</FONT> && '-' == unescaped.charAt(i + 3)) {<a name="line.248"></a> -<FONT color="green">249</FONT> // HTML 5 allows the end of an escaping text span to share dashes with<a name="line.249"></a> -<FONT color="green">250</FONT> // the open : <!--> and <!---> are both fully formed.<a name="line.250"></a> -<FONT color="green">251</FONT> if (i + 4 < unescapedLength && unescaped.charAt(i + 4) == '>') {<a name="line.251"></a> -<FONT color="green">252</FONT> i = i + 5;<a name="line.252"></a> -<FONT color="green">253</FONT> } else if (i + 5 < unescapedLength<a name="line.253"></a> -<FONT color="green">254</FONT> && unescaped.charAt(i + 4) == '-'<a name="line.254"></a> -<FONT color="green">255</FONT> && unescaped.charAt(i + 5) == '>') {<a name="line.255"></a> -<FONT color="green">256</FONT> i = i + 6;<a name="line.256"></a> -<FONT color="green">257</FONT> } else {<a name="line.257"></a> -<FONT color="green">258</FONT> i = unescaped.indexOf("-->", i + 4);<a name="line.258"></a> -<FONT color="green">259</FONT> if (i < 0) {<a name="line.259"></a> -<FONT color="green">260</FONT> // If the escaping text span is not closed, then final close tag<a name="line.260"></a> -<FONT color="green">261</FONT> // would be covered by the unclosed escaping text span.<a name="line.261"></a> -<FONT color="green">262</FONT> return true;<a name="line.262"></a> -<FONT color="green">263</FONT> }<a name="line.263"></a> -<FONT color="green">264</FONT> }<a name="line.264"></a> -<FONT color="green">265</FONT> }<a name="line.265"></a> -<FONT color="green">266</FONT> }<a name="line.266"></a> -<FONT color="green">267</FONT> return false;<a name="line.267"></a> -<FONT color="green">268</FONT> }<a name="line.268"></a> -<FONT color="green">269</FONT> <a name="line.269"></a> -<FONT color="green">270</FONT> <a name="line.270"></a> -<FONT color="green">271</FONT> @VisibleForTesting<a name="line.271"></a> -<FONT color="green">272</FONT> static boolean isValidHtmlName(String name) {<a name="line.272"></a> -<FONT color="green">273</FONT> int n = name.length();<a name="line.273"></a> -<FONT color="green">274</FONT> if (n == 0) { return false; }<a name="line.274"></a> -<FONT color="green">275</FONT> if (n > 128) { return false; }<a name="line.275"></a> -<FONT color="green">276</FONT> boolean isNamespaced = false;<a name="line.276"></a> -<FONT color="green">277</FONT> for (int i = 0; i < n; ++i) {<a name="line.277"></a> -<FONT color="green">278</FONT> char ch = name.charAt(i);<a name="line.278"></a> -<FONT color="green">279</FONT> switch (ch) {<a name="line.279"></a> -<FONT color="green">280</FONT> case ':':<a name="line.280"></a> -<FONT color="green">281</FONT> if (isNamespaced) { return false; }<a name="line.281"></a> -<FONT color="green">282</FONT> isNamespaced = true;<a name="line.282"></a> -<FONT color="green">283</FONT> if (i == 0 || i + 1 == n) { return false; }<a name="line.283"></a> -<FONT color="green">284</FONT> break;<a name="line.284"></a> -<FONT color="green">285</FONT> case '-':<a name="line.285"></a> -<FONT color="green">286</FONT> if (i == 0 || i + 1 == n) { return false; }<a name="line.286"></a> +<FONT color="green">203</FONT> int problemIndex = checkHtmlCdataCloseable(lastTagOpened, cdataContent);<a name="line.203"></a> +<FONT color="green">204</FONT> if (problemIndex == -1) {<a name="line.204"></a> +<FONT color="green">205</FONT> output.append(cdataContent);<a name="line.205"></a> +<FONT color="green">206</FONT> } else {<a name="line.206"></a> +<FONT color="green">207</FONT> error(<a name="line.207"></a> +<FONT color="green">208</FONT> "Invalid CDATA text content",<a name="line.208"></a> +<FONT color="green">209</FONT> cdataContent.subSequence(<a name="line.209"></a> +<FONT color="green">210</FONT> problemIndex,<a name="line.210"></a> +<FONT color="green">211</FONT> Math.min(problemIndex + 10, cdataContent.length()))<a name="line.211"></a> +<FONT color="green">212</FONT> .toString());<a name="line.212"></a> +<FONT color="green">213</FONT> // Still output the close tag.<a name="line.213"></a> +<FONT color="green">214</FONT> }<a name="line.214"></a> +<FONT color="green">215</FONT> }<a name="line.215"></a> +<FONT color="green">216</FONT> if ("plaintext".equals(elementName)) { return; }<a name="line.216"></a> +<FONT color="green">217</FONT> }<a name="line.217"></a> +<FONT color="green">218</FONT> output.append("</").append(elementName).append(">");<a name="line.218"></a> +<FONT color="green">219</FONT> }<a name="line.219"></a> +<FONT color="green">220</FONT> <a name="line.220"></a> +<FONT color="green">221</FONT> public final void text(String text) {<a name="line.221"></a> +<FONT color="green">222</FONT> try {<a name="line.222"></a> +<FONT color="green">223</FONT> writeText(text);<a name="line.223"></a> +<FONT color="green">224</FONT> } catch (IOException ex) {<a name="line.224"></a> +<FONT color="green">225</FONT> ioExHandler.handle(ex);<a name="line.225"></a> +<FONT color="green">226</FONT> }<a name="line.226"></a> +<FONT color="green">227</FONT> }<a name="line.227"></a> +<FONT color="green">228</FONT> <a name="line.228"></a> +<FONT color="green">229</FONT> private final void writeText(String text) throws IOException {<a name="line.229"></a> +<FONT color="green">230</FONT> if (!open) { throw new IllegalStateException(); }<a name="line.230"></a> +<FONT color="green">231</FONT> if (pendingUnescaped != null) {<a name="line.231"></a> +<FONT color="green">232</FONT> pendingUnescaped.append(text.replaceAll("\0", ""));<a name="line.232"></a> +<FONT color="green">233</FONT> } else {<a name="line.233"></a> +<FONT color="green">234</FONT> escapeHtmlOnto(text, output); // Works for RCDATA.<a name="line.234"></a> +<FONT color="green">235</FONT> }<a name="line.235"></a> +<FONT color="green">236</FONT> }<a name="line.236"></a> +<FONT color="green">237</FONT> <a name="line.237"></a> +<FONT color="green">238</FONT> private static int checkHtmlCdataCloseable(<a name="line.238"></a> +<FONT color="green">239</FONT> String localName, StringBuilder sb) {<a name="line.239"></a> +<FONT color="green">240</FONT> int escapingTextSpanStart = -1;<a name="line.240"></a> +<FONT color="green">241</FONT> for (int i = 0, n = sb.length(); i < n; ++i) {<a name="line.241"></a> +<FONT color="green">242</FONT> char ch = sb.charAt(i);<a name="line.242"></a> +<FONT color="green">243</FONT> switch (ch) {<a name="line.243"></a> +<FONT color="green">244</FONT> case '<':<a name="line.244"></a> +<FONT color="green">245</FONT> if (i + 3 < n<a name="line.245"></a> +<FONT color="green">246</FONT> && '!' == sb.charAt(i + 1)<a name="line.246"></a> +<FONT color="green">247</FONT> && '-' == sb.charAt(i + 2)<a name="line.247"></a> +<FONT color="green">248</FONT> && '-' == sb.charAt(i + 3)) {<a name="line.248"></a> +<FONT color="green">249</FONT> if (escapingTextSpanStart == -1) {<a name="line.249"></a> +<FONT color="green">250</FONT> escapingTextSpanStart = i;<a name="line.250"></a> +<FONT color="green">251</FONT> } else {<a name="line.251"></a> +<FONT color="green">252</FONT> return i;<a name="line.252"></a> +<FONT color="green">253</FONT> }<a name="line.253"></a> +<FONT color="green">254</FONT> } else if (i + 1 + localName.length() < n<a name="line.254"></a> +<FONT color="green">255</FONT> && '/' == sb.charAt(i + 1)<a name="line.255"></a> +<FONT color="green">256</FONT> && Strings.regionMatchesIgnoreCase(<a name="line.256"></a> +<FONT color="green">257</FONT> sb, i + 2, localName, 0, localName.length())) {<a name="line.257"></a> +<FONT color="green">258</FONT> // A close tag contained in the content.<a name="line.258"></a> +<FONT color="green">259</FONT> if (escapingTextSpanStart < 0) {<a name="line.259"></a> +<FONT color="green">260</FONT> // We could try some recovery strategies here.<a name="line.260"></a> +<FONT color="green">261</FONT> // E.g. prepending "/<!--\n" to sb if "script".equals(localName)<a name="line.261"></a> +<FONT color="green">262</FONT> return i;<a name="line.262"></a> +<FONT color="green">263</FONT> }<a name="line.263"></a> +<FONT color="green">264</FONT> if (!"script".equals(localName)) {<a name="line.264"></a> +<FONT color="green">265</FONT> // Script tags are commonly included inside script tags.<a name="line.265"></a> +<FONT color="green">266</FONT> // <script><!--document.write('<script>f()</script>');--></script><a name="line.266"></a> +<FONT color="green">267</FONT> // but this does not happen in other CDATA element types.<a name="line.267"></a> +<FONT color="green">268</FONT> // Actually allowing an end tag inside others is problematic.<a name="line.268"></a> +<FONT color="green">269</FONT> // Specifically,<a name="line.269"></a> +<FONT color="green">270</FONT> // <style><!--</style>-->/* foo */</style><a name="line.270"></a> +<FONT color="green">271</FONT> // displays the text "/* foo */" on some browsers.<a name="line.271"></a> +<FONT color="green">272</FONT> return i;<a name="line.272"></a> +<FONT color="green">273</FONT> }<a name="line.273"></a> +<FONT color="green">274</FONT> }<a name="line.274"></a> +<FONT color="green">275</FONT> break;<a name="line.275"></a> +<FONT color="green">276</FONT> case '>':<a name="line.276"></a> +<FONT color="green">277</FONT> // From the HTML5 spec:<a name="line.277"></a> +<FONT color="green">278</FONT> // The text in style, script, title, and textarea elements must not<a name="line.278"></a> +<FONT color="green">279</FONT> // have an escaping text span start that is not followed by an<a name="line.279"></a> +<FONT color="green">280</FONT> // escaping text span end.<a name="line.280"></a> +<FONT color="green">281</FONT> // We look left since the HTML 5 spec allows the escaping text span<a name="line.281"></a> +<FONT color="green">282</FONT> // end to share dashes with the start.<a name="line.282"></a> +<FONT color="green">283</FONT> if (i >= 2 && '-' == sb.charAt(i - 1) && '-' == sb.charAt(i - 2)) {<a name="line.283"></a> +<FONT color="green">284</FONT> if (escapingTextSpanStart < 0) { return i - 2; }<a name="line.284"></a> +<FONT color="green">285</FONT> escapingTextSpanStart = -1;<a name="line.285"></a> +<FONT color="green">286</FONT> }<a name="line.286"></a> <FONT color="green">287</FONT> break;<a name="line.287"></a> -<FONT color="green">288</FONT> default:<a name="line.288"></a> -<FONT color="green">289</FONT> if (ch <= '9') {<a name="line.289"></a> -<FONT color="green">290</FONT> if (i == 0 || ch < '0') { return false; }<a name="line.290"></a> -<FONT color="green">291</FONT> } else if ('A' <= ch && ch <= 'z') {<a name="line.291"></a> -<FONT color="green">292</FONT> if ('Z' < ch && ch < 'a') { return false; }<a name="line.292"></a> -<FONT color="green">293</FONT> } else {<a name="line.293"></a> -<FONT color="green">294</FONT> return false;<a name="line.294"></a> -<FONT color="green">295</FONT> }<a name="line.295"></a> -<FONT color="green">296</FONT> break;<a name="line.296"></a> -<FONT color="green">297</FONT> }<a name="line.297"></a> -<FONT color="green">298</FONT> }<a name="line.298"></a> -<FONT color="green">299</FONT> return true;<a name="line.299"></a> -<FONT color="green">300</FONT> }<a name="line.300"></a> -<FONT color="green">301</FONT> <a name="line.301"></a> -<FONT color="green">302</FONT> @SuppressWarnings("fallthrough")<a name="line.302"></a> -<FONT color="green">303</FONT> static void escapeHtmlOnto(String plainText, Appendable output)<a name="line.303"></a> -<FONT color="green">304</FONT> throws IOException {<a name="line.304"></a> -<FONT color="green">305</FONT> int n = plainText.length();<a name="line.305"></a> -<FONT color="green">306</FONT> int pos = 0;<a name="line.306"></a> -<FONT color="green">307</FONT> for (int i = 0; i < n; ++i) {<a name="line.307"></a> -<FONT color="green">308</FONT> char ch = plainText.charAt(i);<a name="line.308"></a> -<FONT color="green">309</FONT> switch (ch) {<a name="line.309"></a> -<FONT color="green">310</FONT> case '<':<a name="line.310"></a> -<FONT color="green">311</FONT> output.append(plainText, pos, i).append("&lt;");<a name="line.311"></a> -<FONT color="green">312</FONT> pos = i + 1;<a name="line.312"></a> -<FONT color="green">313</FONT> break;<a name="line.313"></a> -<FONT color="green">314</FONT> case '>':<a name="line.314"></a> -<FONT color="green">315</FONT> output.append(plainText, pos, i).append("&gt;");<a name="line.315"></a> -<FONT color="green">316</FONT> pos = i + 1;<a name="line.316"></a> -<FONT color="green">317</FONT> break;<a name="line.317"></a> -<FONT color="green">318</FONT> case '&':<a name="line.318"></a> -<FONT color="green">319</FONT> output.append(plainText, pos, i).append("&amp;");<a name="line.319"></a> -<FONT color="green">320</FONT> pos = i + 1;<a name="line.320"></a> -<FONT color="green">321</FONT> break;<a name="line.321"></a> -<FONT color="green">322</FONT> case '"':<a name="line.322"></a> -<FONT color="green">323</FONT> output.append(plainText, pos, i).append("&#34;");<a name="line.323"></a> -<FONT color="green">324</FONT> pos = i + 1;<a name="line.324"></a> -<FONT color="green">325</FONT> break;<a name="line.325"></a> -<FONT color="green">326</FONT> case '\r': case '\n': break;<a name="line.326"></a> -<FONT color="green">327</FONT> default:<a name="line.327"></a> -<FONT color="green">328</FONT> if (0x20 <= ch && ch < 0xff00) {<a name="line.328"></a> -<FONT color="green">329</FONT> continue;<a name="line.329"></a> -<FONT color="green">330</FONT> }<a name="line.330"></a> -<FONT color="green">331</FONT> // Is a control character or possible full-width version of a<a name="line.331"></a> -<FONT color="green">332</FONT> // special character.<a name="line.332"></a> -<FONT color="green">333</FONT> // FALL-THROUGH<a name="line.333"></a> -<FONT color="green">334</FONT> case '+': // UTF-7<a name="line.334"></a> -<FONT color="green">335</FONT> case '=': // Special in attributes.<a name="line.335"></a> -<FONT color="green">336</FONT> case '@': // Conditional compilation<a name="line.336"></a> -<FONT color="green">337</FONT> case '\'': case '`': // Quoting character<a name="line.337"></a> -<FONT color="green">338</FONT> output.append(plainText, pos, i).append("&#")<a name="line.338"></a> -<FONT color="green">339</FONT> .append(String.valueOf((int) ch)).append(';');<a name="line.339"></a> +<FONT color="green">288</FONT> }<a name="line.288"></a> +<FONT color="green">289</FONT> }<a name="line.289"></a> +<FONT color="green">290</FONT> if (escapingTextSpanStart >= 0) {<a name="line.290"></a> +<FONT color="green">291</FONT> // We could try recovery strategies here.<a name="line.291"></a> +<FONT color="green">292</FONT> // E.g. appending "//-->" to the buffer if "script".equals(localName)<a name="line.292"></a> +<FONT color="green">293</FONT> return escapingTextSpanStart;<a name="line.293"></a> +<FONT color="green">294</FONT> }<a name="line.294"></a> +<FONT color="green">295</FONT> return -1;<a name="line.295"></a> +<FONT color="green">296</FONT> }<a name="line.296"></a> +<FONT color="green">297</FONT> <a name="line.297"></a> +<FONT color="green">298</FONT> <a name="line.298"></a> +<FONT color="green">299</FONT> @VisibleForTesting<a name="line.299"></a> +<FONT color="green">300</FONT> static boolean isValidHtmlName(String name) {<a name="line.300"></a> +<FONT color="green">301</FONT> int n = name.length();<a name="line.301"></a> +<FONT color="green">302</FONT> if (n == 0) { return false; }<a name="line.302"></a> +<FONT color="green">303</FONT> if (n > 128) { return false; }<a name="line.303"></a> +<FONT color="green">304</FONT> boolean isNamespaced = false;<a name="line.304"></a> +<FONT color="green">305</FONT> for (int i = 0; i < n; ++i) {<a name="line.305"></a> +<FONT color="green">306</FONT> char ch = name.charAt(i);<a name="line.306"></a> +<FONT color="green">307</FONT> switch (ch) {<a name="line.307"></a> +<FONT color="green">308</FONT> case ':':<a name="line.308"></a> +<FONT color="green">309</FONT> if (isNamespaced) { return false; }<a name="line.309"></a> +<FONT color="green">310</FONT> isNamespaced = true;<a name="line.310"></a> +<FONT color="green">311</FONT> if (i == 0 || i + 1 == n) { return false; }<a name="line.311"></a> +<FONT color="green">312</FONT> break;<a name="line.312"></a> +<FONT color="green">313</FONT> case '-':<a name="line.313"></a> +<FONT color="green">314</FONT> if (i == 0 || i + 1 == n) { return false; }<a name="line.314"></a> +<FONT color="green">315</FONT> break;<a name="line.315"></a> +<FONT color="green">316</FONT> default:<a name="line.316"></a> +<FONT color="green">317</FONT> if (ch <= '9') {<a name="line.317"></a> +<FONT color="green">318</FONT> if (i == 0 || ch < '0') { return false; }<a name="line.318"></a> +<FONT color="green">319</FONT> } else if ('A' <= ch && ch <= 'z') {<a name="line.319"></a> +<FONT color="green">320</FONT> if ('Z' < ch && ch < 'a') { return false; }<a name="line.320"></a> +<FONT color="green">321</FONT> } else {<a name="line.321"></a> +<FONT color="green">322</FONT> return false;<a name="line.322"></a> +<FONT color="green">323</FONT> }<a name="line.323"></a> +<FONT color="green">324</FONT> break;<a name="line.324"></a> +<FONT color="green">325</FONT> }<a name="line.325"></a> +<FONT color="green">326</FONT> }<a name="line.326"></a> +<FONT color="green">327</FONT> return true;<a name="line.327"></a> +<FONT color="green">328</FONT> }<a name="line.328"></a> +<FONT color="green">329</FONT> <a name="line.329"></a> +<FONT color="green">330</FONT> @SuppressWarnings("fallthrough")<a name="line.330"></a> +<FONT color="green">331</FONT> static void escapeHtmlOnto(String plainText, Appendable output)<a name="line.331"></a> +<FONT color="green">332</FONT> throws IOException {<a name="line.332"></a> +<FONT color="green">333</FONT> int n = plainText.length();<a name="line.333"></a> +<FONT color="green">334</FONT> int pos = 0;<a name="line.334"></a> +<FONT color="green">335</FONT> for (int i = 0; i < n; ++i) {<a name="line.335"></a> +<FONT color="green">336</FONT> char ch = plainText.charAt(i);<a name="line.336"></a> +<FONT color="green">337</FONT> switch (ch) {<a name="line.337"></a> +<FONT color="green">338</FONT> case '<':<a name="line.338"></a> +<FONT color="green">339</FONT> output.append(plainText, pos, i).append("&lt;");<a name="line.339"></a> <FONT color="green">340</FONT> pos = i + 1;<a name="line.340"></a> <FONT color="green">341</FONT> break;<a name="line.341"></a> -<FONT color="green">342</FONT> case 0:<a name="line.342"></a> -<FONT color="green">343</FONT> output.append(plainText, pos, i);<a name="line.343"></a> +<FONT color="green">342</FONT> case '>':<a name="line.342"></a> +<FONT color="green">343</FONT> output.append(plainText, pos, i).append("&gt;");<a name="line.343"></a> <FONT color="green">344</FONT> pos = i + 1;<a name="line.344"></a> <FONT color="green">345</FONT> break;<a name="line.345"></a> -<FONT color="green">346</FONT> }<a name="line.346"></a> -<FONT color="green">347</FONT> }<a name="line.347"></a> -<FONT color="green">348</FONT> output.append(plainText, pos, n);<a name="line.348"></a> -<FONT color="green">349</FONT> }<a name="line.349"></a> -<FONT color="green">350</FONT> <a name="line.350"></a> -<FONT color="green">351</FONT> <a name="line.351"></a> -<FONT color="green">352</FONT> static class CloseableHtmlStreamRenderer extends HtmlStreamRenderer<a name="line.352"></a> -<FONT color="green">353</FONT> implements Closeable {<a name="line.353"></a> -<FONT color="green">354</FONT> private final Closeable closeable;<a name="line.354"></a> -<FONT color="green">355</FONT> <a name="line.355"></a> -<FONT color="green">356</FONT> CloseableHtmlStreamRenderer(<a name="line.356"></a> -<FONT color="green">357</FONT> @WillCloseWhenClosed<a name="line.357"></a> -<FONT color="green">358</FONT> Appendable output, Handler<? super IOException> errorHandler,<a name="line.358"></a> -<FONT color="green">359</FONT> Handler<? super String> badHtmlHandler) {<a name="line.359"></a> -<FONT color="green">360</FONT> super(output, errorHandler, badHtmlHandler);<a name="line.360"></a> -<FONT color="green">361</FONT> this.closeable = (Closeable) output;<a name="line.361"></a> -<FONT color="green">362</FONT> }<a name="line.362"></a> -<FONT color="green">363</FONT> <a name="line.363"></a> -<FONT color="green">364</FONT> public void close() throws IOException {<a name="line.364"></a> -<FONT color="green">365</FONT> if (isDocumentOpen()) { closeDocument(); }<a name="line.365"></a> -<FONT color="green">366</FONT> closeable.close();<a name="line.366"></a> -<FONT color="green">367</FONT> }<a name="line.367"></a> -<FONT color="green">368</FONT> }<a name="line.368"></a> -<FONT color="green">369</FONT> }<a name="line.369"></a> +<FONT color="green">346</FONT> case '&':<a name="line.346"></a> +<FONT color="green">347</FONT> output.append(plainText, pos, i).append("&amp;");<a name="line.347"></a> +<FONT color="green">348</FONT> pos = i + 1;<a name="line.348"></a> +<FONT color="green">349</FONT> break;<a name="line.349"></a> +<FONT color="green">350</FONT> case '"':<a name="line.350"></a> +<FONT color="green">351</FONT> output.append(plainText, pos, i).append("&#34;");<a name="line.351"></a> +<FONT color="green">352</FONT> pos = i + 1;<a name="line.352"></a> +<FONT color="green">353</FONT> break;<a name="line.353"></a> +<FONT color="green">354</FONT> case '\r': case '\n': break;<a name="line.354"></a> +<FONT color="green">355</FONT> default:<a name="line.355"></a> +<FONT color="green">356</FONT> if (0x20 <= ch && ch < 0xff00) {<a name="line.356"></a> +<FONT color="green">357</FONT> continue;<a name="line.357"></a> +<FONT color="green">358</FONT> }<a name="line.358"></a> +<FONT color="green">359</FONT> // Is a control character or possible full-width version of a<a name="line.359"></a> +<FONT color="green">360</FONT> // special character.<a name="line.360"></a> +<FONT color="green">361</FONT> // FALL-THROUGH<a name="line.361"></a> +<FONT color="green">362</FONT> case '+': // UTF-7<a name="line.362"></a> +<FONT color="green">363</FONT> case '=': // Special in attributes.<a name="line.363"></a> +<FONT color="green">364</FONT> case '@': // Conditional compilation<a name="line.364"></a> +<FONT color="green">365</FONT> case '\'': case '`': // Quoting character<a name="line.365"></a> +<FONT color="green">366</FONT> output.append(plainText, pos, i).append("&#")<a name="line.366"></a> +<FONT color="green">367</FONT> .append(String.valueOf((int) ch)).append(';');<a name="line.367"></a> +<FONT color="green">368</FONT> pos = i + 1;<a name="line.368"></a> +<FONT color="green">369</FONT> break;<a name="line.369"></a> +<FONT color="green">370</FONT> case 0:<a name="line.370"></a> +<FONT color="green">371</FONT> output.append(plainText, pos, i);<a name="line.371"></a> +<FONT color="green">372</FONT> pos = i + 1;<a name="line.372"></a> +<FONT color="green">373</FONT> break;<a name="line.373"></a> +<FONT color="green">374</FONT> }<a name="line.374"></a> +<FONT color="green">375</FONT> }<a name="line.375"></a> +<FONT color="green">376</FONT> output.append(plainText, pos, n);<a name="line.376"></a> +<FONT color="green">377</FONT> }<a name="line.377"></a> +<FONT color="green">378</FONT> <a name="line.378"></a> +<FONT color="green">379</FONT> <a name="line.379"></a> +<FONT color="green">380</FONT> static class CloseableHtmlStreamRenderer extends HtmlStreamRenderer<a name="line.380"></a> +<FONT color="green">381</FONT> implements Closeable {<a name="line.381"></a> +<FONT color="green">382</FONT> private final Closeable closeable;<a name="line.382"></a> +<FONT color="green">383</FONT> <a name="line.383"></a> +<FONT color="green">384</FONT> CloseableHtmlStreamRenderer(<a name="line.384"></a> +<FONT color="green">385</FONT> @WillCloseWhenClosed<a name="line.385"></a> +<FONT color="green">386</FONT> Appendable output, Handler<? super IOException> errorHandler,<a name="line.386"></a> +<FONT color="green">387</FONT> Handler<? super String> badHtmlHandler) {<a name="line.387"></a> +<FONT color="green">388</FONT> super(output, errorHandler, badHtmlHandler);<a name="line.388"></a> +<FONT color="green">389</FONT> this.closeable = (Closeable) output;<a name="line.389"></a> +<FONT color="green">390</FONT> }<a name="line.390"></a> +<FONT color="green">391</FONT> <a name="line.391"></a> +<FONT color="green">392</FONT> public void close() throws IOException {<a name="line.392"></a> +<FONT color="green">393</FONT> if (isDocumentOpen()) { closeDocument(); }<a name="line.393"></a> +<FONT color="green">394</FONT> closeable.close();<a name="line.394"></a> +<FONT color="green">395</FONT> }<a name="line.395"></a> +<FONT color="green">396</FONT> }<a name="line.396"></a> +<FONT color="green">397</FONT> }<a name="line.397"></a> diff --git a/distrib/lib/owasp-java-html-sanitizer-src.jar b/distrib/lib/owasp-java-html-sanitizer-src.jar Binary files differindex 240253c..5315319 100644 --- a/distrib/lib/owasp-java-html-sanitizer-src.jar +++ b/distrib/lib/owasp-java-html-sanitizer-src.jar diff --git a/distrib/lib/owasp-java-html-sanitizer.jar b/distrib/lib/owasp-java-html-sanitizer.jar Binary files differindex d9d9ed2..dfcb5e0 100644 --- a/distrib/lib/owasp-java-html-sanitizer.jar +++ b/distrib/lib/owasp-java-html-sanitizer.jar |