recipes: improved support for queries containing quotes

Use shlex.split() to split the query string so that quotes can be used
to delimit strings containing spaces to be matched as a whole. This
worked with the previous code, but it did not support single quotes -
these caused an error in Django's filter code and thus an internal
server error (as did querying for ""). Add some additional checks for
single quotes as it is still possible to get them past shlex.split()
e.g. with something like "'hello'" (with quotes).

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
Paul Eggleton 2019-11-20 11:13:16 +13:00
parent 8c33374d6c
commit 7eea41de30

View File

@ -524,15 +524,27 @@ class RecipeSearchView(ListView):
return qs, filtered return qs, filtered
def get_queryset(self): def get_queryset(self):
import shlex
_check_url_branch(self.kwargs) _check_url_branch(self.kwargs)
query_string = self.request.GET.get('q', '') query_string = self.request.GET.get('q', '')
init_qs = Recipe.objects.filter(layerbranch__branch__name=self.kwargs['branch']) init_qs = Recipe.objects.filter(layerbranch__branch__name=self.kwargs['branch'])
# Support slightly crude search on inherits field try:
query_items = query_string.split() # Note: we drop quotes here, they will be added back later
query_items = shlex.split(query_string)
except ValueError:
messages.add_message(self.request, messages.ERROR, 'Invalid query string')
return Recipe.objects.none()
# Check for single quotes which will cause the filter to blow up (e.g. searching for "'hello'" with all quotes)
for item in query_items:
if '\'' in item:
messages.add_message(self.request, messages.ERROR, 'Invalid query string')
return Recipe.objects.none()
inherits = [] inherits = []
query_terms = [] query_terms = []
for item in query_items: for item in query_items:
# Support slightly crude search on inherits field
if item.startswith('inherits:'): if item.startswith('inherits:'):
inherits.append(item.split(':')[1]) inherits.append(item.split(':')[1])
@ -565,6 +577,8 @@ layer name is expected to follow the \"layer:\" prefix without any spaces.')
'No layer \"%s\" was found.' 'No layer \"%s\" was found.'
% query_layername) % query_layername)
else: else:
if ' ' in item:
item = '"%s"' % item
query_terms.append(item) query_terms.append(item)
if inherits: if inherits:
# FIXME This is a bit ugly, perhaps we should consider having this as a one-many relationship instead # FIXME This is a bit ugly, perhaps we should consider having this as a one-many relationship instead