sql: escape ILike/ElementILike value (#55528)
\, _ and % must be escaped.
This commit is contained in:
parent
8314648278
commit
549e513bf6
|
@ -516,3 +516,45 @@ def test_data_source_custom_view_digest(pub):
|
|||
cards = CardDef.get_data_source_items('carddef:foo:view', get_by_text='Hello Foo Bar')
|
||||
assert len(cards) == 1
|
||||
assert cards[0]['text'] == 'Hello Foo Bar'
|
||||
|
||||
|
||||
def test_data_source_query_escape(pub):
|
||||
CardDef.wipe()
|
||||
carddef = CardDef()
|
||||
carddef.name = 'foo'
|
||||
carddef.fields = [
|
||||
StringField(id='1', label='Test', type='string', varname='foo'),
|
||||
]
|
||||
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
|
||||
carddef.store()
|
||||
carddef.data_class().wipe()
|
||||
|
||||
carddata = carddef.data_class()()
|
||||
carddata.data = {'1': 'Astreinte\\Lundi %'}
|
||||
carddata.just_created()
|
||||
carddata.store()
|
||||
|
||||
carddata2 = carddef.data_class()()
|
||||
carddata2.data = {'1': 'Astreinte\\Mardi _'}
|
||||
carddata2.just_created()
|
||||
carddata2.store()
|
||||
|
||||
cards = CardDef.get_data_source_items('carddef:foo', query='astreinte')
|
||||
assert len(cards) == 2
|
||||
assert cards[0]['text'] == 'Astreinte\\Lundi %'
|
||||
|
||||
cards = CardDef.get_data_source_items('carddef:foo', query='astreinte\\')
|
||||
assert len(cards) == 2
|
||||
assert cards[0]['text'] == 'Astreinte\\Lundi %'
|
||||
|
||||
cards = CardDef.get_data_source_items('carddef:foo', query='astreinte\\l')
|
||||
assert len(cards) == 1
|
||||
assert cards[0]['text'] == 'Astreinte\\Lundi %'
|
||||
|
||||
cards = CardDef.get_data_source_items('carddef:foo', query='%')
|
||||
assert len(cards) == 1
|
||||
assert cards[0]['text'] == 'Astreinte\\Lundi %'
|
||||
|
||||
cards = CardDef.get_data_source_items('carddef:foo', query='_')
|
||||
assert len(cards) == 1
|
||||
assert cards[0]['text'] == 'Astreinte\\Mardi _'
|
||||
|
|
11
wcs/sql.py
11
wcs/sql.py
|
@ -87,6 +87,13 @@ SQL_TYPE_MAPPING = {
|
|||
}
|
||||
|
||||
|
||||
def like_escape(value):
|
||||
value = value.replace('\\', '\\\\')
|
||||
value = value.replace('_', '\\_')
|
||||
value = value.replace('%', '\\%')
|
||||
return value
|
||||
|
||||
|
||||
def pickle_loads(value):
|
||||
if hasattr(value, 'tobytes'):
|
||||
value = value.tobytes()
|
||||
|
@ -261,7 +268,7 @@ class Intersects(Criteria):
|
|||
class ILike(Criteria):
|
||||
def __init__(self, attribute, value, **kwargs):
|
||||
super().__init__(attribute, value, **kwargs)
|
||||
self.value = '%' + self.value + '%'
|
||||
self.value = '%' + like_escape(self.value) + '%'
|
||||
|
||||
def as_sql(self):
|
||||
return '%s ILIKE %%(c%s)s' % (self.attribute, id(self.value))
|
||||
|
@ -291,7 +298,7 @@ class ElementEqual(Criteria):
|
|||
class ElementILike(ElementEqual):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.value = '%' + self.value + '%'
|
||||
self.value = '%' + like_escape(self.value) + '%'
|
||||
|
||||
def as_sql(self):
|
||||
return "%s->>'%s' ILIKE %%(c%s)s" % (self.attribute, self.key, id(self.value))
|
||||
|
|
Loading…
Reference in New Issue