我正在尝试修改Vaadin发送到浏览器的引导程序Javascript。以下是有关此问题的Vaadin论坛链接: https://vaadin.com/forum#!/thread/4252604
Vaadin使用Jsoup所以我使用Jsoup API在Vaadin有效负载中找到正确的位置来修改Javascript。当我像这样使用Jsoup API时:
element.html(newHTML)
newHTML中的任何内容都会被转义。因此,例如,如果newHTML是:
alert("hi");
然后调用Jsoup API将导致:
alert("hi");
我以为我可以通过这样做来禁用这个Jsoup逃脱:
element.ownerDocument().outputSettings().escapeMode(...)
但ownerDocument()为null所以我不认为这是一个选项。 Jsoup是否有办法绕过这个限制,以便我可以获得具有双引号(“)和甚至打开/关闭标记括号(<,>)的Javascript以获得输出?
答案 0 :(得分:0)
显然,
element.childNode(0).attr("data", html);
如果元素是“script”元素而 html 是Javascript源,那么就可以了。
答案 1 :(得分:0)
我的解决方案是继承TextNode并覆盖执行转义的方法。
package org.jsoup.nodes;
public class UnescapedTextNode extends TextNode
{
public UnescapedTextNode( final String text, final String baseUri )
{
super( text, baseUri );
}
@Override
void outerHtmlHead(
final StringBuilder accum,
final int depth,
final Document.OutputSettings out )
{
//String html = Entities.escape( getWholeText(), out ); // Don't escape!
String html = getWholeText();
if ( out.prettyPrint() &&
parent() instanceof Element &&
!Element.preserveWhitespace( parent() ) )
{
html = normaliseWhitespace( html );
}
if ( out.prettyPrint() &&
( ( siblingIndex() == 0 &&
parentNode instanceof Element &&
( (Element)parentNode ).tag().formatAsBlock() &&
!isBlank() ) ||
( out.outline() &&
siblingNodes().size() > 0 &&
!isBlank() ) ) )
{
indent( accum, depth, out );
}
accum.append( html );
}
}
这几乎是TextNode.outerHtmlHead()
的逐字副本(最初由Jonathan Hedley撰写)。我刚刚评论了逃逸的部分。这就是我使用它的方式:
// ... assuming head is of type Element and refers to the <head> of the document.
final String message = "Hello World!";
final String messageScript = "alert( \"" + message + "\" );";
final Element messageScriptEl = head.appendElement( "script" ).
attr( "type", "text/javascript" );
final TextNode messageScriptTextNode = new UnescapedTextNode(
messageScript,
messageScriptEl.baseUri() );
messageScriptEl.appendChild( messageScriptTextNode );
// ... etc
此外,调用Document.toString()
或Document.outerHtml()
会生成输出,其中包含未创建的脚本标记内的文本。即:
<script type="text/javascript">alert( "Hello World!" );</script>
而不是:
<script type="text/javascript">alert( "Hello World!" );</script>
以前发生过。
有两个&#39;陷阱&#39;我找到了:
UnescapedTextNode类需要由加载原始jsoup库的同一个类加载器加载。这是因为上面我已经覆盖了一个包私有方法,这是在JLS中规定的。 (感谢Jeff Sinclair提出的the article that pointed this out to me。相关的一点是
当且仅当满足以下任一条件时,才能访问类或接口D的字段或方法R:
- ...
- R是包私有,由与D。
相同的运行时包中的类声明
位于访问控制(5.4.4)下的 JVM规范中。