2011-06-02 113 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中顯示。當我直接添加它像這樣