forked from zaclys/searxng
		
	Merge pull request #99 from return42/webapp-misc
[enh] add settings option to enable/disable search formats
This commit is contained in:
		
						commit
						83ccf7b04d
					
				
					 6 changed files with 77 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -18,6 +18,7 @@ search:
 | 
			
		|||
    default_lang : "" # Default search language - leave blank to detect from browser information or use codes from 'languages.py'
 | 
			
		||||
    ban_time_on_fail : 5 # ban time in seconds after engine errors
 | 
			
		||||
    max_ban_time_on_fail : 120 # max ban time in seconds after engine errors
 | 
			
		||||
    formats: [html, csv, json, rss]  # remove format to deny access, use lower case.
 | 
			
		||||
 | 
			
		||||
server:
 | 
			
		||||
    port : 8888
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,9 +80,10 @@
 | 
			
		|||
                            <input id="search_url" type="url" class="form-control select-all-on-click cursor-text" name="search_url" value="{{ search_url() }}" readonly>{{- "" -}}
 | 
			
		||||
                        </div>{{- "" -}}
 | 
			
		||||
                    </form>
 | 
			
		||||
                    {% if search_formats %}
 | 
			
		||||
                    <label>{{ _('Download results') }}</label>
 | 
			
		||||
                    <div class="clearfix"></div>
 | 
			
		||||
                    {% for output_type in ('csv', 'json', 'rss') %}
 | 
			
		||||
                    {% for output_type in search_formats %}
 | 
			
		||||
                    <form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="form-inline pull-{% if rtl %}right{% else %}left{% endif %} result_download">
 | 
			
		||||
                        {{- search_form_attrs(pageno) -}}
 | 
			
		||||
                        <input type="hidden" name="format" value="{{ output_type }}">{{- "" -}}
 | 
			
		||||
| 
						 | 
				
			
			@ -90,8 +91,11 @@
 | 
			
		|||
                    </form>
 | 
			
		||||
                    {% endfor %}
 | 
			
		||||
                    <div class="clearfix"></div>
 | 
			
		||||
                    {% if 'rss' in search_formats %}
 | 
			
		||||
                    <br /><label><a href="{{ search_url() }}&format=rss">{{ _('RSS subscription') }}</a></label>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                    <div class="clearfix"></div>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div><!-- /#sidebar_results -->
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,8 +85,9 @@
 | 
			
		|||
            <div class="selectable_url"><pre>{{ url_for('search', _external=True) }}?q={{ q|urlencode }}&language={{ current_language }}&time_range={{ time_range }}&safesearch={{ safesearch }}{% if pageno > 1 %}&pageno={{ pageno }}{% endif %}{% if selected_categories %}&categories={{ selected_categories|join(",") | replace(' ','+') }}{% endif %}{% if timeout_limit %}&timeout_limit={{ timeout_limit|urlencode }}{% endif %}</pre></div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div id="apis">
 | 
			
		||||
          {% if search_formats %}
 | 
			
		||||
          <h4 class="title">{{ _('Download results') }}</h4>
 | 
			
		||||
          {% for output_type in ('csv', 'json', 'rss') %}
 | 
			
		||||
          {% for output_type in search_formats %}
 | 
			
		||||
	  <div class="left">
 | 
			
		||||
            <form method="{{ method or 'POST' }}" action="{{ url_for('search') }}">
 | 
			
		||||
              <input type="hidden" name="q" value="{{ q|e }}">
 | 
			
		||||
| 
						 | 
				
			
			@ -103,6 +104,7 @@
 | 
			
		|||
            </form>
 | 
			
		||||
	  </div>
 | 
			
		||||
          {% endfor %}
 | 
			
		||||
          {% endif %}
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ from os.path import splitext, join
 | 
			
		|||
from random import choice
 | 
			
		||||
from html.parser import HTMLParser
 | 
			
		||||
from urllib.parse import urljoin, urlparse
 | 
			
		||||
from collections.abc import Mapping
 | 
			
		||||
 | 
			
		||||
from lxml import html
 | 
			
		||||
from lxml.etree import ElementBase, XPath, XPathError, XPathSyntaxError, _ElementStringResult, _ElementUnicodeResult
 | 
			
		||||
| 
						 | 
				
			
			@ -500,6 +501,58 @@ def get_engine_from_settings(name):
 | 
			
		|||
    return {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
NOT_EXISTS = object()
 | 
			
		||||
"""Singleton used by :py:obj:`get_value` if a key does not exists."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_value(dictionary, *keys, default=NOT_EXISTS):
 | 
			
		||||
    """Return the value from a *deep* mapping type (e.g. the ``settings`` object
 | 
			
		||||
    from yaml).  If the path to the *key* does not exists a :py:obj:`NOT_EXISTS`
 | 
			
		||||
    is returned (non ``KeyError`` exception is raised).
 | 
			
		||||
 | 
			
		||||
    .. code: python
 | 
			
		||||
 | 
			
		||||
       >>> from searx import settings
 | 
			
		||||
       >>> from searx.utils import get_value, NOT_EXISTS
 | 
			
		||||
       >>> get_value(settings, 'checker', 'additional_tests', 'rosebud', 'result_container')
 | 
			
		||||
       ['not_empty', ['one_title_contains', 'citizen kane']]
 | 
			
		||||
 | 
			
		||||
       >>> get_value(settings, 'search', 'xxx') is NOT_EXISTS
 | 
			
		||||
       True
 | 
			
		||||
       >>> get_value(settings, 'search', 'formats')
 | 
			
		||||
       ['html', 'csv', 'json', 'rss']
 | 
			
		||||
 | 
			
		||||
    The list returned from the ``search.format`` key is not a mapping type, you
 | 
			
		||||
    can't traverse along non-mapping types.  If you try it, you will get a
 | 
			
		||||
    :py:ref:`NOT_EXISTS`:
 | 
			
		||||
 | 
			
		||||
    .. code: python
 | 
			
		||||
 | 
			
		||||
       >>> get_value(settings, 'search', 'format', 'csv') is NOT_EXISTS
 | 
			
		||||
       True
 | 
			
		||||
       >>> get_value(settings, 'search', 'formats')[1]
 | 
			
		||||
       'csv'
 | 
			
		||||
 | 
			
		||||
    For convenience you can replace :py:ref:`NOT_EXISTS` by a default value of
 | 
			
		||||
    your choice:
 | 
			
		||||
 | 
			
		||||
    .. code: python
 | 
			
		||||
 | 
			
		||||
       if 'csv' in get_value(settings, 'search', 'formats', default=[]):
 | 
			
		||||
           print("csv format is denied")
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    obj = dictionary
 | 
			
		||||
    for k in keys:
 | 
			
		||||
        if not isinstance(obj, Mapping):
 | 
			
		||||
            raise TypeError("expected mapping type, got %s" % type(obj))
 | 
			
		||||
        obj = obj.get(k, default)
 | 
			
		||||
        if obj is default:
 | 
			
		||||
            return obj
 | 
			
		||||
    return obj
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_xpath(xpath_spec):
 | 
			
		||||
    """Return cached compiled XPath
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,8 @@ from pygments.formatters import HtmlFormatter  # pylint: disable=no-name-in-modu
 | 
			
		|||
from werkzeug.middleware.proxy_fix import ProxyFix
 | 
			
		||||
from werkzeug.serving import WSGIRequestHandler
 | 
			
		||||
 | 
			
		||||
import flask
 | 
			
		||||
 | 
			
		||||
from flask import (
 | 
			
		||||
    Flask,
 | 
			
		||||
    request,
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +88,7 @@ from searx.utils import (
 | 
			
		|||
    gen_useragent,
 | 
			
		||||
    dict_subset,
 | 
			
		||||
    match_language,
 | 
			
		||||
    get_value,
 | 
			
		||||
)
 | 
			
		||||
from searx.version import VERSION_STRING
 | 
			
		||||
from searx.query import RawTextQuery
 | 
			
		||||
| 
						 | 
				
			
			@ -161,6 +164,8 @@ for indice, theme in enumerate(themes):
 | 
			
		|||
    for (dirpath, dirnames, filenames) in os.walk(theme_img_path):
 | 
			
		||||
        global_favicons[indice].extend(filenames)
 | 
			
		||||
 | 
			
		||||
OUTPUT_FORMATS = ['html', 'csv', 'json', 'rss']
 | 
			
		||||
 | 
			
		||||
STATS_SORT_PARAMETERS = {
 | 
			
		||||
    'name': (False, 'name', ''),
 | 
			
		||||
    'score': (True, 'score', 0),
 | 
			
		||||
| 
						 | 
				
			
			@ -511,6 +516,11 @@ def render(template_name, override_theme=None, **kwargs):
 | 
			
		|||
 | 
			
		||||
    kwargs['preferences'] = request.preferences
 | 
			
		||||
 | 
			
		||||
    kwargs['search_formats'] = [
 | 
			
		||||
        x for x in get_value(
 | 
			
		||||
            settings, 'search', 'formats', default=OUTPUT_FORMATS)
 | 
			
		||||
        if x != 'html']
 | 
			
		||||
 | 
			
		||||
    kwargs['brand'] = brand
 | 
			
		||||
 | 
			
		||||
    kwargs['translations'] = json.dumps(get_translations(), separators=(',', ':'))
 | 
			
		||||
| 
						 | 
				
			
			@ -683,9 +693,12 @@ def search():
 | 
			
		|||
 | 
			
		||||
    # output_format
 | 
			
		||||
    output_format = request.form.get('format', 'html')
 | 
			
		||||
    if output_format not in ['html', 'csv', 'json', 'rss']:
 | 
			
		||||
    if output_format not in OUTPUT_FORMATS:
 | 
			
		||||
        output_format = 'html'
 | 
			
		||||
 | 
			
		||||
    if output_format not in get_value(settings, 'search', 'formats', default=OUTPUT_FORMATS):
 | 
			
		||||
        flask.abort(403)
 | 
			
		||||
 | 
			
		||||
    # check if there is query (not None and not an empty string)
 | 
			
		||||
    if not request.form.get('q'):
 | 
			
		||||
        if output_format == 'html':
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ search:
 | 
			
		|||
    safe_search : 0 # Filter results. 0: None, 1: Moderate, 2: Strict
 | 
			
		||||
    autocomplete : "" # Existing autocomplete backends: "dbpedia", "duckduckgo", "google", "startpage", "swisscows", "qwant", "wikipedia" - leave blank to turn it off by default
 | 
			
		||||
    default_lang : "" # Default search language - leave blank to detect from browser information or use codes from 'languages.py'
 | 
			
		||||
    formats: [html, csv, json, rss]
 | 
			
		||||
 | 
			
		||||
server:
 | 
			
		||||
    port : 8888
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue