Добавление HTML в XUL (расширение Firefox) - PullRequest
2 голосов
/ 02 июня 2011

У меня есть этот JavaScript, который получает HTML-часть с сервера.Я могу вернуть html в сообщении с предупреждением, и это правильный код.

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 напрямую к menupopup с идентификатором ajax, он будет работать, как и ожидалось.Когда я прикрепляю его с помощью 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 не работает.

Ответы [ 2 ]

3 голосов
/ 05 июня 2011

Сначала правильный ответ, который на самом деле не то, что вы ищете, но важно пропустить:

Не добавляйте / вставляйте / что-либо удаленно извлекающее HTML или код JavaScript в XULили хромированные области кода!

Такие вещи всегда являются уязвимостью безопасности.JS является исполняемым, и HTML также может содержать исполняемые биты (например, javascript: protocol).Любой внедренный код будет работать с полными привилегиями браузера, что означает привилегии пользователя ОС (что в Windows XP означает привилегии администратора).

Вам нужно либо экранировать html, либо проанализировать его и оставить только безопасные биты в.

Вы не можете доверять удаленному коду, даже если он исходит от ваших собственных серверов:

  • Атаки посредником (http)
  • Скомпрометированный сервер
  • Грубый администратор сервера (не вы, надеюсь;))

Кстати: добавление / внедрение / удаленного извлечения кода или HTML-кода в пространство Chrome приведет к отклонению уязвимых версий вашего дополнения.на 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. Затем добавлять элементы по одному (каждый пункт меню и поддерево).
1 голос
/ 06 июня 2011

Ваш код действительно является уязвимостью безопасности, вы никогда не должны делать это так. Однако есть относительно простой способ сделать это безопасно (важно: это предполагает, что ваш 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) и загруженным кодом (content). Вот почему важно, чтобы ваш 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).

...