2011-06-02 166 views
2

我有这个JavaScript从服务器获取html部分。我能够在警告消息中返回html,并且它是正确的代码。将HTML附加到XUL(Firefox扩展)

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:\n" + 
          request.statusText); 
       } 
      } 
     }; 
     request.open("GET", url, true); 
     request.send(null); 
} 

的XUL/HTML从服务器返回:

 <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页面:

...更多的代码

<menu class="menu" label="test"> 
    <menupopup id="ajax" width="450" height="700" onpopupshowing="myextension.ajax('http://www.myserver.com/phpscript.php'> 
    </menupopup> 
</menu> 

现在,如果我附上了html direc对id ajax的menupopup可以按照预期工作。当我使用appendChild附加它时,它不会。我知道我不能使用appendChild,但在XUL中似乎没有与innerHTML等效的内容。我无法控制从服务器返回的xul/html,所以我不能使用DOM方法添加内容并绕过html。

我尝试使用HTMLParser https://developer.mozilla.org/en/Code_snippets/HTML_to_DOM将它转换为DOM对象,但似乎并不奏效,我相信因为它削减了<menuitem>标记。

任何想法如何将HTML附加到menupopup,以便我可以将它们显示为菜单项。

好吧,我试过了iframe的办法:

 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:\n" + request.statusText); 
        } 
       } 
      }; 
      request.open("GET", url, true); 
      request.send(null); 
    } 

<iframe id="frame" type="content" src="" /> 

这似乎并没有工作。但是,如果我执行encodeURIComponent(request.responseText)的警报,它的编码是正确的。进而更如果我直接把它添加到这样的iframe:

<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是行不通的。

+0

如果你控制服务器,AJAX调用返回一些JSON和你想要显示的数据,然后使用DOM方法或XBL在客户端构建XUL/HTML结构可能会更好。 – MatrixFrog 2011-06-02 17:25:07

+0

我不能那样做。实际上,我收到的描述中包含一些HTML的RSS源。我已经解析了RSS feed,以便将HMTL部分从它中解放出来。但是很难解析这个html,以及我不知道将会发生什么。所以我更喜欢使用html。 – Stofke 2011-06-02 22:45:33

+0

对不起,我没有注意到你已经说过你无法控制服务器。 – MatrixFrog 2011-06-02 23:22:45

回答

3

首先正确的答案,这是不是真的,你要寻找什么,但重要的省略:

不要追加/注入/不管远程检索到的HTML或JavaScript代码到XUL或Chrome代码作用域!

像这样的东西总是一个安全漏洞。 JS是可执行的,并且HTML也可以包含可执行位(例如,javascript:协议)。任何注入的代码都将以完全浏览器特权运行,这将转化为操作系统用户权限(在Windows XP上转换为管理员权限)。

您需要转义html,或解析它,只留下安全位。

你不能信任的远程代码,即使它从你自己的服务器来源:

  • 中间人攻击(HTTP)
  • 危及的服务器
  • 粗糙服务器管理员(不是你,希望; ))

BTW:添加/注射/不管远程检索代码或HTML到镀铬的空间将导致拒绝你的附加组件的受影响版本的addons.mozilla.org上进行了重新如上所述。

现在技术上正确的答案,但不与远程检索和消毒HTML使用:

  1. 您需要确保正确的HTML命名空间将被用于(xmlns:html="http://www.w3.org/1999/xhtml"
  2. 你不能真正appendElement()文本,但只有真正的DOM元素。因此,您必须先将任何文本解析为DOM。使用有效的XML最容易(DOMParser);可以通过隐藏的iframe标记汤料。
  3. 您应该adoptNode来自不同DOM的任何元素
  4. 然后逐个追加元素(每个菜单项和子树)。
+0

问题是rss提要包含一个html部分,很难用JavaScript解析成单个元素(这是一个PITA)。所以我正在寻找一种更简单的方法来追加它。 – Stofke 2011-06-06 16:54:07

1

你的代码确实是一个安全漏洞,你不应该这样做。有一种相对简单的方法可以安全地执行它(重要的是:这是假设你的XUL没有在浏览器的内容区运行)。您将iframe放入您的menupopup中:

<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"></iframe> 
     </menuitem> 
    </menupopup> 
</menu> 

然后,您可以使用data:URL将数据加载到该框架中。这里的重要部分是type =“content”,这会在您的代码(chrome)和您加载的代码(内容)之间创建一个安全边界。这就是为什么你的XUL文档不在浏览器的内容区域是很重要的 - 那么你已经在安全边界的“内容”一侧,你不能建立另一个。

数据实际投入的框架是这样的:

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阅读器记写的)。

+0

我试图用一个非常简单的htmlpage:

大家

\t 但它不会在iframe中显示。当我直接添加它像这样