diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py index 2895379dcf4..9a3a84a9adb 100644 --- a/addons/website/models/ir_ui_view.py +++ b/addons/website/models/ir_ui_view.py @@ -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 diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 4a3e8ee4f19..43df01d3514 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -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', diff --git a/addons/website/tests/test_views.py b/addons/website/tests/test_views.py index c8e7efb9044..b63ac75997d 100644 --- a/addons/website/tests/test_views.py +++ b/addons/website/tests/test_views.py @@ -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':'hello world', + 'arch':'

hello world

', '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 = '' + 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')