[FIX] website: escaping saved html content
Escape text nodes changed via the web editor before sending the content
it to the server controller.
It is done since the content is unescaped one time when being displayed,
and it is not done for inline style and script tags (which may be
injected by dropping a snippet) since that would break them.
replacing the solution in cdb900044
.
This commit is contained in:
parent
96be5b404a
commit
8c77c711ee
|
@ -7,7 +7,6 @@ from openerp import SUPERUSER_ID, api
|
|||
from openerp.addons.website.models import website
|
||||
from openerp.http import request
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools import html_escape
|
||||
|
||||
class view(osv.osv):
|
||||
_inherit = "ir.ui.view"
|
||||
|
@ -120,14 +119,6 @@ class view(osv.osv):
|
|||
# ensure there's only one match
|
||||
[root] = arch.xpath(section_xpath)
|
||||
|
||||
# html text need to be escaped for xml storage
|
||||
def escape_node(node):
|
||||
node.text = node.text and html_escape(node.text)
|
||||
node.tail = node.tail and html_escape(node.tail)
|
||||
escape_node(replacement)
|
||||
for descendant in replacement.iterdescendants():
|
||||
escape_node(descendant)
|
||||
|
||||
root.text = replacement.text
|
||||
root.tail = replacement.tail
|
||||
# replace all children
|
||||
|
|
|
@ -423,7 +423,14 @@
|
|||
* Saves an RTE content, which always corresponds to a view section (?).
|
||||
*/
|
||||
saveElement: function ($el) {
|
||||
var markup = $el.prop('outerHTML');
|
||||
// escape text nodes for xml saving
|
||||
var escaped_el = $el.clone();
|
||||
escaped_el.find('*').addBack().not('script,style').contents().each(function(){
|
||||
if(this.nodeType == 3) {
|
||||
this.nodeValue = _.escape(this.nodeValue);
|
||||
}
|
||||
});
|
||||
var markup = escaped_el.prop('outerHTML');
|
||||
return openerp.jsonRpc('/web/dataset/call', 'call', {
|
||||
model: 'ir.ui.view',
|
||||
method: 'save',
|
||||
|
|
|
@ -175,14 +175,34 @@ class TestViewSaving(common.TransactionCase):
|
|||
)
|
||||
|
||||
def test_save_escaped_text(self):
|
||||
""" Test saving html special chars in text nodes """
|
||||
view_id = self.registry('ir.ui.view').create(self.cr, self.uid, {
|
||||
'arch':'<t>hello world</t>',
|
||||
'arch':'<t><p><h1>hello world</h1></p></t>',
|
||||
'type':'qweb'
|
||||
})
|
||||
view = self.registry('ir.ui.view').browse(self.cr, self.uid, view_id)
|
||||
replacement = 'hello world & <angle brackets>!'
|
||||
view.save(replacement, xpath='/t')
|
||||
self.assertEqual(view.render(), replacement, 'html special characters wrongly escaped')
|
||||
# script and style text nodes should not escaped client side
|
||||
replacement = '<script>1 && "hello & world"</script>'
|
||||
view.save(replacement, xpath='/t/p/h1')
|
||||
self.assertIn(
|
||||
replacement.replace('&', '&'),
|
||||
view.arch,
|
||||
'inline script should be escaped server side'
|
||||
)
|
||||
self.assertIn(
|
||||
replacement,
|
||||
view.render(),
|
||||
'inline script should not be escaped when rendering'
|
||||
)
|
||||
# common text nodes should be be escaped client side
|
||||
replacement = 'world &amp; &lt;b&gt;cie'
|
||||
view.save(replacement, xpath='/t/p')
|
||||
self.assertIn(replacement, view.arch, 'common text node should not be escaped server side')
|
||||
self.assertIn(
|
||||
replacement,
|
||||
view.render().replace('&', '&'),
|
||||
'text node characters wrongly unescaped when rendering'
|
||||
)
|
||||
|
||||
def test_save_only_embedded(self):
|
||||
Company = self.registry('res.company')
|
||||
|
|
Loading…
Reference in New Issue