changeset 961:840c1a8bd8af

Mitigate QueryParserError when searching.
author Brian Neal <bgneal@gmail.com>
date Mon, 03 Aug 2015 17:26:32 -0500
parents fc4a1c4e488a
children 10e7570a3aab
files custom_search/views.py sg101/templates/search/search.html
diffstat 2 files changed, 51 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/custom_search/views.py	Mon Jul 13 18:24:41 2015 -0500
+++ b/custom_search/views.py	Mon Aug 03 17:26:32 2015 -0500
@@ -1,13 +1,19 @@
 """Custom views for searching."""
+import logging
 
+from django.shortcuts import render_to_response
 from haystack.views import SearchView
+from xapian import QueryParserError
 
+logger = logging.getLogger(__name__)
 
 class UserSearchView(SearchView):
     """This class passes the user making the search as an __init__ argument to
     the search form as the keyword argument 'user'.
 
     """
+    query_parser_error = False
+
     def build_form(self, form_kwargs=None):
         """Pass the request.user object to the form's constructor."""
         if not form_kwargs:
@@ -15,3 +21,35 @@
         if 'user' not in form_kwargs:
             form_kwargs['user'] = self.request.user
         return super(UserSearchView, self).build_form(form_kwargs)
+
+    # This nonsense is because Xapian can raise QueryParserError when evaluating
+    # the query. This was triggered by some sh*t-bag looking for SQL injection
+    # vulnerabilities.
+    # If QueryParserError is raised, just drive on and set a flag in the context
+    # (via extra_context()) so that an error is rendered on the template instead
+    # of a 500 error.
+
+    def create_response(self):
+        try:
+            return super(UserSearchView, self).create_response()
+        except QueryParserError:
+            self.query_parser_error = True
+
+        logger.warning("QueryParserError triggered from user search input")
+
+        context = {
+            'query': self.query,
+            'form': self.form,
+            'page': None,
+            'paginator': None,
+            'suggestion': None,
+        }
+
+        context.update(self.extra_context())
+        return render_to_response(self.template, context,
+                                  context_instance=self.context_class(self.request))
+
+    def extra_context(self):
+        return {
+            'query_parser_error': self.query_parser_error,
+        }
--- a/sg101/templates/search/search.html	Mon Jul 13 18:24:41 2015 -0500
+++ b/sg101/templates/search/search.html	Mon Aug 03 17:26:32 2015 -0500
@@ -27,6 +27,18 @@
 {% endblock %}
 {% block content %}
 <h2>Search <img src="{{ STATIC_URL }}icons/magnifier.png" alt="Search" /></h2>
+{% if query_parser_error %}
+<div class="error">
+   <p>
+   Your search query could not be processed. This is most likely because you've
+   included terms like AND, OR, or NOT. These terms are not necessary.
+   </p>
+   <p>
+   If you continue to have problems with this error, please
+   <a href="{% url 'contact-form' %}?subject=Search%20Help">contact us</a>.
+   </p>
+</div>
+{% endif %}
 <form id="search-form" method="get" action=".">
 <fieldset>
 <legend>Find content with:</legend>
@@ -44,7 +56,7 @@
 </fieldset>
 </form>
 
-{% if form.is_valid %}
+{% if form.is_valid and not query_parser_error %}
 <h3>Search results; page {{ page.number }} of {{ page.paginator.num_pages }}</h3>
 
    {% if page.paginator.count %}