Appending HTML to XUL (Firefox extension)
我有这个从服务器获取 html 部分的 javascript。我能够在警报消息中返回 html,它是正确的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ajax: function(url){ var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Components.interfaces.nsIXMLHttpRequest); request.onreadystatechange = function() { if (request.readyState == 4) { // only if"OK" if (request.status == 200) { var popup = document.getElementById("ajax"); // a <menupopup> element var txt = request.responseText; alert(txt); popup.appendChild(txt); } else { alert("There was a problem retrieving the XML data:\ " + request.statusText); } } }; request.open("GET", url, true); request.send(null); } |
服务器返回的xul/html:
1 2 3 4 5 6 7 8 | <menuitem> <html:h2><html:a href="http://google.com">Google</html:a></html:h2> <html:p><html:table><html:tr><html:td>xxxx</html:td></html:tr></html:table></html:p> </menuitem> <menuitem> <html:h2><html:a href="http://yahoo.com">Yahoo</html:a></html:h2> <html:p><html:table><html:tr><html:td>yyyy</html:td></html:tr></html:table></html:p> </menuitem> |
我的xul页面:
...更多代码
1 2 3 4 | <menu class="menu" label="test"> <menupopup id="ajax" width="450" height="700" onpopupshowing="myextension.ajax('http://www.myserver.com/phpscript.php'> </menupopup> </menu> |
现在,如果我将 html 直接附加到 id ajax 的菜单弹出窗口,它会按预期工作。当我使用 appendChild 附加它时,它没有。我知道我不能使用 appendChild 但在 XUL 中似乎没有与 innerHTML 等效的东西。我无法控制从服务器返回的 xul/html,因此我无法使用 DOM 方法添加内容并绕过 html。
我尝试使用 HTMLParser https://developer.mozilla.org/en/Code_snippets/HTML_to_DOM 将其转换为 DOM 对象,但这似乎不起作用,我相信因为它削减了
任何想法如何将 HTML 附加到菜单弹出,以便我可以将它们显示为菜单项。
好的,我尝试了 iframe 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ajax: function(url){ var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Components.interfaces.nsIXMLHttpRequest); request.onreadystatechange = function() { if (request.readyState == 4) { // only if"OK" if (request.status == 200) { var frame = document.getElementById("frame"); frame.setAttribute("src","data:text/html," + encodeURIComponent(request.responseText)); } else { alert("There was a problem retrieving the XML data:\ " + request.statusText); } } }; request.open("GET", url, true); request.send(null); } |
与
1 | <iframe id="frame" type="content" src="" /> |
这似乎不起作用。但是,如果我对 encodeURIComponent(request.responseText) 发出警报,它就会正确编码。甚至如果我像这样直接将它添加到 iframe 中:
1 | <iframe type="content" src="data:text/html,%3Chtml%3E%0A%3Cbody%3E%0A%3Cp%3EHello%20everyone%3C%2Fp%3E%0A%09%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A%0A"/> |
它不起作用,因为要显示 html,它需要在标签内,但 html 包含许多不同的项目,每个项目都应该在自己的标签中。简单地添加到 html 是行不通的。
首先是正确答案,这不是您真正要寻找的,但重要的是要省略:
不要将远程检索到的 HTML 或 javascript 代码附加/注入/任何内容到 XUL 或 chrome 代码范围!
这样的事情总是存在安全漏洞。 JS 是可执行的,HTML 也可能包含可执行位(例如 javascript: 协议)。任何注入的代码都将以完整的浏览器权限运行,这将转换为操作系统用户权限(在 Windows XP 上转换为管理员权限)。
您需要对 html 进行转义,或者对其进行解析并只保留安全位。
你不能信任远程代码,即使它来自你自己的服务器:
- 中间人攻击 (http)
- 受损的服务器
- 粗略的服务器管理员(不是你,希望 ;))
顺便说一句:由于上述原因,将远程检索到的代码或 HTML 添加/注入/任何远程检索到的代码或 HTML 将导致 addons.mozilla.org 上受影响的插件版本被拒绝。
现在是技术上正确的答案,但不要与远程检索和清理的 HTML 一起使用:
你的代码确实是一个安全漏洞,你不应该那样做。然而,有一种相对简单的方法可以安全地执行此操作(重要:这是假设您的 XUL 没有在浏览器的内容区域中运行)。您将 iframe 放入 menupopup:
1 2 3 4 5 6 7 | <menu class="menu" label="test"> <menupopup id="ajax" onpopupshowing="myextension.ajax('http://www.myserver.com/phpscript.php'> <menuitem> <iframe id="frame" type="content" width="450" height="700"></iframex> </menuitem> </menupopup> </menu> |
然后您可以使用 data: URL 将数据加载到该框架中。这里的重要部分是 type="content" 这里,这会在您的代码 (chrome) 和您加载的代码 (content) 之间创建一个安全边界。这就是为什么您的 XUL 文档不在浏览器的内容区域中很重要的原因 - 那么您已经在安全边界的"内容"一侧,您无法建立另一个。
实际上将数据放入框架是这样的:
1 2 3 | var frame = document.getElementById("frame"); // <iframe> element var txt = request.responseText; frame.setAttribute("src","data:text/html;charset=utf-8," + encodeURIComponent(txt)); |
有关详细信息,请参阅 https://developer.mozilla.org/En/Displaying_web_content_in_an_extension_without_security_issues(本文专门针对 RSS 阅读器编写)。