[FIX] website,website_sale: HTML escape dynamic snippet
Issue
To do on Community:
- Install website_sale (eCommerce)
- Go into Website app
- Navigate through Product/Products
- Edit 'Customizable Desk (CONFIG)' and add '&' and/or '<' and/or '>'
characters into the name
- Save
- Go to the Website app Dashboard and click on 'Go to Website'
- Click on 'Edit' button
- Drag and drop the 'Dynamic Product' snippet into the website
- Click on the block 'Your Dynamic Snippet wil be ...'
- In the right panel, in the 'Dynamic Product' snippet options,
chose a 'Template' and a 'Product Category'
A traceback is shown
Cause
the '&' character crashes lxml.etree.fromstring
Solution
ensure no '&' is sent to lxmx.etree.fromstring by using
odoo.tools.html_escape (in order to ensure no other problematic
characters are sent to the front) on the field values except when
not applicable (widget rendering with record_to_html should not be
escaped).
It is important to note here that this is applicable
to action servers that are used by the dynamic filter.
opw-2357027
closes odoo/odoo#59805
X-original-commit: f91422115c09be484f2868347566b6392ed0effd
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commit is contained in:
@@ -707,6 +707,8 @@
|
||||
<field name="url">/website/static/src/img/snippets_demo/s_popup.jpg</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
<data>
|
||||
<!-- Filter for Dynamic Snippet -->
|
||||
<record id="dynamic_snippet_country_filter" model="ir.filters">
|
||||
<field name="name">Countries</field>
|
||||
@@ -769,9 +771,6 @@
|
||||
<field name="name">Countries</field>
|
||||
<field name="website_id" ref="website.default_website"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
<data>
|
||||
<record id="group_multi_website" model="res.groups">
|
||||
<field name="name">Multi-website</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
|
||||
@@ -5,6 +5,7 @@ from collections import OrderedDict
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.osv import expression
|
||||
from odoo.tools import html_escape as escape
|
||||
from lxml import etree as ET
|
||||
|
||||
|
||||
@@ -21,6 +22,10 @@ class WebsiteSnippetFilter(models.Model):
|
||||
limit = fields.Integer(help='The limit is the maximum number of records retrieved', required=True)
|
||||
website_id = fields.Many2one('website', string='Website', ondelete='cascade', required=True)
|
||||
|
||||
@api.model
|
||||
def escape_falsy_as_empty(self, s):
|
||||
return escape(s) if s else ''
|
||||
|
||||
@api.constrains('action_server_id', 'filter_id')
|
||||
def _check_data_source_is_provided(self):
|
||||
for record in self:
|
||||
@@ -115,9 +120,9 @@ class WebsiteSnippetFilter(models.Model):
|
||||
field = model._fields.get(field_name)
|
||||
field_widget = field_widget or field.type
|
||||
if field.type == 'binary':
|
||||
data['image_fields'][field_name] = Website.image_url(record, field_name)
|
||||
data['image_fields'][field_name] = self.escape_falsy_as_empty(Website.image_url(record, field_name))
|
||||
elif field_widget == 'image':
|
||||
data['image_fields'][field_name] = record[field_name]
|
||||
data['image_fields'][field_name] = self.escape_falsy_as_empty(record[field_name])
|
||||
elif field_widget == 'monetary':
|
||||
FieldMonetary = self.env['ir.qweb.field.monetary']
|
||||
model_currency = None
|
||||
@@ -137,11 +142,11 @@ class WebsiteSnippetFilter(models.Model):
|
||||
{'display_currency': website_currency}
|
||||
)
|
||||
else:
|
||||
data['fields'][field_name] = record[field_name]
|
||||
data['fields'][field_name] = self.escape_falsy_as_empty(record[field_name])
|
||||
elif ('ir.qweb.field.%s' % field_widget) in self.env:
|
||||
data['fields'][field_name] = self.env[('ir.qweb.field.%s' % field_widget)].record_to_html(record, field_name, {})
|
||||
else:
|
||||
data['fields'][field_name] = record[field_name]
|
||||
data['fields'][field_name] = self.escape_falsy_as_empty(record[field_name])
|
||||
|
||||
data['fields']['call_to_action_url'] = 'website_url' in record and record['website_url']
|
||||
values.append(data)
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
<field name="website_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
<data>
|
||||
<!-- Action Server for Dynamic Filter -->
|
||||
<record id="dynamic_snippet_products_action" model="ir.actions.server">
|
||||
<field name="name">Products Dynamic Snippet</field>
|
||||
@@ -60,6 +62,7 @@ dynamic_filter = model.env.context.get('dynamic_filter')
|
||||
limit = model.env.context.get('limit')
|
||||
search_domain = model.env.context.get('search_domain')
|
||||
get_rendering_data_structure = model.env.context.get('get_rendering_data_structure')
|
||||
escape = dynamic_filter.escape_falsy_as_empty
|
||||
|
||||
domain = [('website_published', '=', True)] + website.website_domain() + (search_domain or [])
|
||||
products = ProductProduct.search(domain, limit=limit)
|
||||
@@ -82,12 +85,12 @@ for product in products:
|
||||
for field_name in dynamic_filter.field_names.split(","):
|
||||
field = ProductProduct._fields.get(field_name)
|
||||
if field and field.type == 'binary':
|
||||
res_product[field_name] = website.image_url(product, field_name)
|
||||
data_type = 'image_fields'
|
||||
data['image_fields'][field_name] = escape(website.image_url(product, field_name))
|
||||
elif field_name == 'list_price':
|
||||
data['fields'][field_name] = res_product[field_name]
|
||||
else:
|
||||
data_type = 'fields'
|
||||
data[data_type][field_name] = res_product[field_name]
|
||||
data['fields']['call_to_action_url'] = product['website_url']
|
||||
data['fields'][field_name] = escape(res_product[field_name])
|
||||
data['fields']['call_to_action_url'] = escape(product['website_url'])
|
||||
res_products.append(data)
|
||||
|
||||
response = res_products
|
||||
@@ -101,8 +104,6 @@ response = res_products
|
||||
<field name="name">Products</field>
|
||||
<field name="website_id" ref="website.default_website"/>
|
||||
</record>
|
||||
</data>
|
||||
<data>
|
||||
<function model="ir.model.fields" name="formbuilder_whitelist">
|
||||
<value>sale.order</value>
|
||||
<value eval="[
|
||||
|
||||
Reference in New Issue
Block a user