logo

searx

Unnamed repository; edit this file 'description' to name the repository.
commit: 3a57a1a0d096f9b15eab14c65c9c2bab432097d5
parent: 57149661e4f90e5ad3a9a4c36bb5f31a1c7ec6aa
Author: Adam Tauber <asciimoo@gmail.com>
Date:   Fri, 20 Jan 2017 23:56:50 +0100

Merge pull request #832 from dalf/input_check

Input check

Diffstat:

searx/exceptions.py | 32++++++++++++++++++++++++++++++++
searx/search.py | 66+++++++++++++++++++++++++++++++++++++++++++-----------------------
searx/templates/__common__/about.html | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
searx/templates/__common__/opensearch.xml | 28++++++++++++++++++++++++++++
searx/templates/__common__/opensearch_response_rss.xml | 29+++++++++++++++++++++++++++++
searx/templates/courgette/about.html | 63+--------------------------------------------------------------
searx/templates/courgette/opensearch.xml | 28----------------------------
searx/templates/courgette/opensearch_response_rss.xml | 23-----------------------
searx/templates/legacy/about.html | 63+--------------------------------------------------------------
searx/templates/legacy/opensearch.xml | 28----------------------------
searx/templates/legacy/opensearch_response_rss.xml | 23-----------------------
searx/templates/oscar/about.html | 63+--------------------------------------------------------------
searx/templates/oscar/opensearch.xml | 28----------------------------
searx/templates/oscar/opensearch_response_rss.xml | 23-----------------------
searx/templates/pix-art/about.html | 63+--------------------------------------------------------------
searx/utils.py | 2++
searx/webapp.py | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
tests/unit/test_webapp.py | 2++
18 files changed, 259 insertions(+), 442 deletions(-)

diff --git a/searx/exceptions.py b/searx/exceptions.py @@ -0,0 +1,32 @@ +''' +searx is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +searx is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with searx. If not, see < http://www.gnu.org/licenses/ >. + +(C) 2017- by Alexandre Flament, <alex@al-f.net> +''' + + +class SearxException(Exception): + pass + + +class SearxParameterException(SearxException): + + def __init__(self, name, value): + if value == '' or value is None: + message = 'Empty ' + name + ' parameter' + else: + message = 'Invalid value "' + value + '" for parameter ' + name + super(SearxParameterException, self).__init__(message) + self.parameter_name = name + self.parameter_value = value diff --git a/searx/search.py b/searx/search.py @@ -31,11 +31,16 @@ from searx.query import RawTextQuery, SearchQuery from searx.results import ResultContainer from searx import logger from searx.plugins import plugins +from searx.languages import language_codes +from searx.exceptions import SearxParameterException logger = logger.getChild('search') number_of_searches = 0 +language_code_set = set(l[0].lower() for l in language_codes) +language_code_set.add('all') + def send_http_request(engine, request_params, start_time, timeout_limit): # for page_load_time stats @@ -182,33 +187,13 @@ def default_request_params(): def get_search_query_from_webapp(preferences, form): - query = None - query_engines = [] - query_categories = [] - query_pageno = 1 - query_lang = 'all' - query_time_range = None + # no text for the query ? + if not form.get('q'): + raise SearxParameterException('q', '') # set blocked engines disabled_engines = preferences.engines.get_disabled() - # set specific language if set - query_lang = preferences.get_value('language') - - # safesearch - query_safesearch = preferences.get_value('safesearch') - - # TODO better exceptions - if not form.get('q'): - raise Exception('noquery') - - # set pagenumber - pageno_param = form.get('pageno', '1') - if not pageno_param.isdigit() or int(pageno_param) < 1: - pageno_param = 1 - - query_pageno = int(pageno_param) - # parse query, if tags are set, which change # the serch engine or search-language raw_text_query = RawTextQuery(form['q'], disabled_engines) @@ -217,6 +202,13 @@ def get_search_query_from_webapp(preferences, form): # set query query = raw_text_query.getSearchQuery() + # get and check page number + pageno_param = form.get('pageno', '1') + if not pageno_param.isdigit() or int(pageno_param) < 1: + raise SearxParameterException('pageno', pageno_param) + query_pageno = int(pageno_param) + + # get language # set specific language if set on request, query or preferences # TODO support search with multible languages if len(raw_text_query.languages): @@ -226,10 +218,38 @@ def get_search_query_from_webapp(preferences, form): else: query_lang = preferences.get_value('language') + # check language + if query_lang not in language_code_set: + raise SearxParameterException('language', query_lang) + + # get safesearch + if 'safesearch' in form: + query_safesearch = form.get('safesearch') + # first check safesearch + if not query_safesearch.isdigit(): + raise SearxParameterException('safesearch', query_safesearch) + query_safesearch = int(query_safesearch) + else: + query_safesearch = preferences.get_value('safesearch') + + # safesearch : second check + if query_safesearch < 0 or query_safesearch > 2: + raise SearxParameterException('safesearch', query_safesearch) + + # get time_range query_time_range = form.get('time_range') + # check time_range + if not(query_time_range is None)\ + and not (query_time_range in ['', 'day', 'week', 'month', 'year']): + raise SearxParameterException('time_range', query_time_range) + + # query_engines query_engines = raw_text_query.engines + # query_categories + query_categories = [] + # if engines are calculated from query, # set categories by using that informations if query_engines and raw_text_query.specific: diff --git a/searx/templates/__common__/about.html b/searx/templates/__common__/about.html @@ -0,0 +1,62 @@ +<div{% if rtl %} dir="ltr"{% endif %}> + <h1>About <a href="{{ url_for('index') }}">searx</a></h1> + + <p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, aggregating the results of other <a href="{{ url_for('preferences') }}">search engines</a> while not storing information about its users. + </p> + <h2>Why use searx?</h2> + <ul> + <li>searx may not offer you as personalised results as Google, but it doesn't generate a profile about you</li> + <li>searx doesn't care about what you search for, never shares anything with a third party, and it can't be used to compromise you</li> + <li>searx is free software, the code is 100% open and you can help to make it better. See more on <a href="https://github.com/asciimoo/searx">github</a></li> + </ul> + <p>If you do care about privacy, want to be a conscious user, or otherwise believe + in digital freedom, make searx your default search engine or run it on your own server</p> + +<h2>Technical details - How does it work?</h2> + +<p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, +inspired by the <a href="https://beniz.github.io/seeks/">seeks project</a>.<br /> +It provides basic privacy by mixing your queries with searches on other platforms without storing search data. Queries are made using a POST request on every browser (except chrome*). Therefore they show up in neither our logs, nor your url history. In case of Chrome* users there is an exception, searx uses the search bar to perform GET requests.<br /> +Searx can be added to your browser's search bar; moreover, it can be set as the default search engine. +</p> + +<h2>How can I make it my own?</h2> + +<p>Searx appreciates your concern regarding logs, so take the <a href="https://github.com/asciimoo/searx">code</a> and run it yourself! <br />Add your Searx to this <a href="https://github.com/asciimoo/searx/wiki/Searx-instances">list</a> to help other people reclaim their privacy and make the Internet freer! +<br />The more decentralized the Internet is, the more freedom we have!</p> + + +<h2>More about searx</h2> + +<ul> + <li><a href="https://github.com/asciimoo/searx">github</a></li> + <li><a href="https://www.ohloh.net/p/searx/">ohloh</a></li> + <li><a href="https://twitter.com/Searx_engine">twitter</a></li> + <li>IRC: #searx @ freenode (<a href="https://kiwiirc.com/client/irc.freenode.com/searx">webclient</a>)</li> + <li><a href="https://www.transifex.com/projects/p/searx/">transifex</a></li> +</ul> + + +<hr /> + +<h2 id="faq">FAQ</h2> + +<h3>How to add to firefox?</h3> +<p><a href="#" onclick="window.external.AddSearchProvider(window.location.protocol + '//' + window.location.host + '{{ url_for('opensearch') }}');">Install</a> searx as a search engine on any version of Firefox! (javascript required)</p> + +<h2 id="dev_faq">Developer FAQ</h2> + +<h3>New engines?</h3> +<ul> + <li>Edit your <a href="https://raw.github.com/asciimoo/searx/master/searx/settings.yml">settings.yml</a></li> + <li>Create your custom engine module, check the <a href="https://github.com/asciimoo/searx/blob/master/examples/basic_engine.py">example engine</a></li> +</ul> +<p>Don't forget to restart searx after config edit!</p> + +<h3>Installation/WSGI support?</h3> +<p>See the <a href="https://github.com/asciimoo/searx/wiki/Installation">installation and setup</a> wiki page</p> + +<h3>How to debug engines?</h3> +<p><a href="{{ url_for('stats') }}">Stats page</a> contains some useful data about the engines used.</p> + +</div> diff --git a/searx/templates/__common__/opensearch.xml b/searx/templates/__common__/opensearch.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>{{ instance_name }}</ShortName> + <Description>a privacy-respecting, hackable metasearch engine</Description> + <InputEncoding>UTF-8</InputEncoding> + <Image>{{ urljoin(host, url_for('static', filename='img/favicon.png')) }}</Image> + <LongName>searx metasearch</LongName> + {% if opensearch_method == 'get' %} + <Url type="text/html" method="get" template="{{ host }}search?q={searchTerms}"/> + {% if autocomplete %} + <Url type="application/x-suggestions+json" method="get" template="{{ host }}autocompleter"> + <Param name="format" value="x-suggestions" /> + <Param name="q" value="{searchTerms}" /> + </Url> + {% endif %} + {% else %} + <Url type="text/html" method="post" template="{{ host }}"> + <Param name="q" value="{searchTerms}" /> + </Url> + {% if autocomplete %} + <!-- TODO, POST REQUEST doesn't work --> + <Url type="application/x-suggestions+json" method="get" template="{{ host }}autocompleter"> + <Param name="format" value="x-suggestions" /> + <Param name="q" value="{searchTerms}" /> + </Url> + {% endif %} + {% endif %} +</OpenSearchDescription> diff --git a/searx/templates/__common__/opensearch_response_rss.xml b/searx/templates/__common__/opensearch_response_rss.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<rss version="2.0" + xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" + xmlns:atom="http://www.w3.org/2005/Atom"> + <channel> + <title>Searx search: {{ q|e }}</title> + <link>{{ base_url }}?q={{ q|e }}</link> + <description>Search results for "{{ q|e }}" - searx</description> + <opensearch:totalResults>{{ number_of_results }}</opensearch:totalResults> + <opensearch:startIndex>1</opensearch:startIndex> + <opensearch:itemsPerPage>{{ number_of_results }}</opensearch:itemsPerPage> + <atom:link rel="search" type="application/opensearchdescription+xml" href="{{ base_url }}opensearch.xml"/> + <opensearch:Query role="request" searchTerms="{{ q|e }}" startPage="1" /> + {% if error_message %} + <item> + <title>Error</title> + <description>{{ error_message|e }}</description> + </item> + {% endif %} + {% for r in results %} + <item> + <title>{{ r.title }}</title> + <link>{{ r.url }}</link> + <description>{{ r.content }}</description> + {% if r.pubdate %}<pubDate>{{ r.pubdate }}</pubDate>{% endif %} + </item> + {% endfor %} + </channel> +</rss> diff --git a/searx/templates/courgette/about.html b/searx/templates/courgette/about.html @@ -1,66 +1,5 @@ {% extends 'courgette/base.html' %} {% block content %} {% include 'courgette/github_ribbon.html' %} -<div class="row"{% if rtl %} dir="ltr"{% endif %}> - <h1>About <a href="{{ url_for('index') }}">searx</a></h1> - - <p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, aggregating the results of other <a href="{{ url_for('preferences') }}">search engines</a> while not storing information about its users. - </p> - <h2>Why use searx?</h2> - <ul> - <li>searx may not offer you as personalised results as Google, but it doesn't generate a profile about you</li> - <li>searx doesn't care about what you search for, never shares anything with a third party, and it can't be used to compromise you</li> - <li>searx is free software, the code is 100% open and you can help to make it better. See more on <a href="https://github.com/asciimoo/searx">github</a></li> - </ul> - <p>If you do care about privacy, want to be a conscious user, or otherwise believe - in digital freedom, make searx your default search engine or run it on your own server</p> - -<h2>Technical details - How does it work?</h2> - -<p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, -inspired by the <a href="https://beniz.github.io/seeks/">seeks project</a>.<br /> -It provides basic privacy by mixing your queries with searches on other platforms without storing search data. Queries are made using a POST request on every browser (except chrome*). Therefore they show up in neither our logs, nor your url history. In case of Chrome* users there is an exception, searx uses the search bar to perform GET requests.<br /> -Searx can be added to your browser's search bar; moreover, it can be set as the default search engine. -</p> - -<h2>How can I make it my own?</h2> - -<p>Searx appreciates your concern regarding logs, so take the <a href="https://github.com/asciimoo/searx">code</a> and run it yourself! <br />Add your Searx to this <a href="https://github.com/asciimoo/searx/wiki/Searx-instances">list</a> to help other people reclaim their privacy and make the Internet freer! -<br />The more decentralized the Internet, is the more freedom we have!</p> - - -<h2>More about searx</h2> - -<ul> - <li><a href="https://github.com/asciimoo/searx">github</a></li> - <li><a href="https://www.ohloh.net/p/searx/">ohloh</a></li> - <li><a href="https://twitter.com/Searx_engine">twitter</a></li> - <li>IRC: #searx @ freenode (<a href="https://kiwiirc.com/client/irc.freenode.com/searx">webclient</a>)</li> - <li><a href="https://www.transifex.com/projects/p/searx/">transifex</a></li> -</ul> - - -<hr /> - -<h2 id="faq">FAQ</h2> - -<h3>How to add to firefox?</h3> -<p><a href="#" onclick="window.external.AddSearchProvider(window.location.protocol + '//' + window.location.host + '{{ url_for('opensearch') }}');">Install</a> searx as a search engine on any version of Firefox! (javascript required)</p> - -<h2 id="dev_faq">Developer FAQ</h2> - -<h3>New engines?</h3> -<ul> - <li>Edit your <a href="https://raw.github.com/asciimoo/searx/master/searx/settings.yml">settings.yml</a></li> - <li>Create your custom engine module, check the <a href="https://github.com/asciimoo/searx/blob/master/examples/basic_engine.py">example engine</a></li> -</ul> -<p>Don't forget to restart searx after config edit!</p> - -<h3>Installation/WSGI support?</h3> -<p>See the <a href="https://github.com/asciimoo/searx/wiki/Installation">installation and setup</a> wiki page</p> - -<h3>How to debug engines?</h3> -<p><a href="{{ url_for('stats') }}">Stats page</a> contains some useful data about the engines used.</p> - -</div> +{% include '__common__/about.html' %} {% endblock %} diff --git a/searx/templates/courgette/opensearch.xml b/searx/templates/courgette/opensearch.xml @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> - <ShortName>{{ instance_name }}</ShortName> - <Description>a privacy-respecting, hackable metasearch engine</Description> - <InputEncoding>UTF-8</InputEncoding> - <Image>{{ urljoin(host, url_for('static', filename='img/favicon.png')) }}</Image> - <LongName>searx metasearch</LongName> - {% if opensearch_method == 'get' %} - <Url type="text/html" method="get" template="{{ host }}search?q={searchTerms}"/> - {% if autocomplete %} - <Url type="application/x-suggestions+json" method="get" template="{{ host }}autocompleter"> - <Param name="format" value="x-suggestions" /> - <Param name="q" value="{searchTerms}" /> - </Url> - {% endif %} - {% else %} - <Url type="text/html" method="post" template="{{ host }}"> - <Param name="q" value="{searchTerms}" /> - </Url> - {% if autocomplete %} - <!-- TODO, POST REQUEST doesn't work --> - <Url type="application/x-suggestions+json" method="get" template="{{ host }}autocompleter"> - <Param name="format" value="x-suggestions" /> - <Param name="q" value="{searchTerms}" /> - </Url> - {% endif %} - {% endif %} -</OpenSearchDescription> diff --git a/searx/templates/courgette/opensearch_response_rss.xml b/searx/templates/courgette/opensearch_response_rss.xml @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<rss version="2.0" - xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" - xmlns:atom="http://www.w3.org/2005/Atom"> - <channel> - <title>Searx search: {{ q|e }}</title> - <link>{{ base_url }}?q={{ q|e }}</link> - <description>Search results for "{{ q|e }}" - searx</description> - <opensearch:totalResults>{{ number_of_results }}</opensearch:totalResults> - <opensearch:startIndex>1</opensearch:startIndex> - <opensearch:itemsPerPage>{{ number_of_results }}</opensearch:itemsPerPage> - <atom:link rel="search" type="application/opensearchdescription+xml" href="{{ base_url }}opensearch.xml"/> - <opensearch:Query role="request" searchTerms="{{ q|e }}" startPage="1" /> - {% for r in results %} - <item> - <title>{{ r.title }}</title> - <link>{{ r.url }}</link> - <description>{{ r.content }}</description> - {% if r.pubdate %}<pubDate>{{ r.pubdate }}</pubDate>{% endif %} - </item> - {% endfor %} - </channel> -</rss> diff --git a/searx/templates/legacy/about.html b/searx/templates/legacy/about.html @@ -1,66 +1,5 @@ {% extends 'legacy/base.html' %} {% block content %} {% include 'legacy/github_ribbon.html' %} -<div class="row"{% if rtl %} dir="ltr"{% endif %}> - <h1>About <a href="{{ url_for('index') }}">searx</a></h1> - - <p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, aggregating the results of other <a href="{{ url_for('preferences') }}">search engines</a> while not storing information about its users. - </p> - <h2>Why use searx?</h2> - <ul> - <li>searx may not offer you as personalised results as Google, but it doesn't generate a profile about you</li> - <li>searx doesn't care about what you search for, never shares anything with a third party, and it can't be used to compromise you</li> - <li>searx is free software, the code is 100% open and you can help to make it better. See more on <a href="https://github.com/asciimoo/searx">github</a></li> - </ul> - <p>If you do care about privacy, want to be a conscious user, or otherwise believe - in digital freedom, make searx your default search engine or run it on your own server</p> - -<h2>Technical details - How does it work?</h2> - -<p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, -inspired by the <a href="https://beniz.github.io/seeks/">seeks project</a>.<br /> -It provides basic privacy by mixing your queries with searches on other platforms without storing search data. Queries are made using a POST request on every browser (except chrome*). Therefore they show up in neither our logs, nor your url history. In case of Chrome* users there is an exception, if searx used from the search bar it performs GET requests.<br /> -Searx can be added to your browser's search bar; moreover, it can be set as the default search engine. -</p> - -<h2>How can I make it my own?</h2> - -<p>Searx appreciates your concern regarding logs, so take the <a href="https://github.com/asciimoo/searx">code</a> and run it yourself! <br />Add your Searx to this <a href="https://github.com/asciimoo/searx/wiki/Searx-instances">list</a> to help other people reclaim their privacy and make the Internet freer! -<br />The more decentralized Internet is the more freedom we have!</p> - - -<h2>More about searx</h2> - -<ul> - <li><a href="https://github.com/asciimoo/searx">github</a></li> - <li><a href="https://www.ohloh.net/p/searx/">ohloh</a></li> - <li><a href="https://twitter.com/Searx_engine">twitter</a></li> - <li>IRC: #searx @ freenode (<a href="https://kiwiirc.com/client/irc.freenode.com/searx">webclient</a>)</li> - <li><a href="https://www.transifex.com/projects/p/searx/">transifex</a></li> -</ul> - - -<hr /> - -<h2 id="faq">FAQ</h2> - -<h3>How to add to firefox?</h3> -<p><a href="#" onclick="window.external.AddSearchProvider(window.location.protocol + '//' + window.location.host + '{{ url_for('opensearch') }}');">Install</a> searx as a search engine on any version of Firefox! (javascript required)</p> - -<h2 id="dev_faq">Developer FAQ</h2> - -<h3>New engines?</h3> -<ul> - <li>Edit your <a href="https://raw.github.com/asciimoo/searx/master/searx/settings.yml">settings.yml</a></li> - <li>Create your custom engine module, check the <a href="https://github.com/asciimoo/searx/blob/master/examples/basic_engine.py">example engine</a></li> -</ul> -<p>Don't forget to restart searx after config edit!</p> - -<h3>Installation/WSGI support?</h3> -<p>See the <a href="https://github.com/asciimoo/searx/wiki/Installation">installation and setup</a> wiki page</p> - -<h3>How to debug engines?</h3> -<p><a href="{{ url_for('stats') }}">Stats page</a> contains some useful data about the engines used.</p> - -</div> +{% include '__common__/about.html' %} {% endblock %} diff --git a/searx/templates/legacy/opensearch.xml b/searx/templates/legacy/opensearch.xml @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> - <ShortName>{{ instance_name }}</ShortName> - <Description>a privacy-respecting, hackable metasearch engine</Description> - <InputEncoding>UTF-8</InputEncoding> - <Image>{{ urljoin(host, url_for('static', filename='img/favicon.png')) }}</Image> - <LongName>searx metasearch</LongName> - {% if opensearch_method == 'get' %} - <Url type="text/html" method="get" template="{{ host }}search?q={searchTerms}"/> - {% if autocomplete %} - <Url type="application/x-suggestions+json" method="get" template="{{ host }}autocompleter"> - <Param name="format" value="x-suggestions" /> - <Param name="q" value="{searchTerms}" /> - </Url> - {% endif %} - {% else %} - <Url type="text/html" method="post" template="{{ host }}"> - <Param name="q" value="{searchTerms}" /> - </Url> - {% if autocomplete %} - <!-- TODO, POST REQUEST doesn't work --> - <Url type="application/x-suggestions+json" method="get" template="{{ host }}autocompleter"> - <Param name="format" value="x-suggestions" /> - <Param name="q" value="{searchTerms}" /> - </Url> - {% endif %} - {% endif %} -</OpenSearchDescription> diff --git a/searx/templates/legacy/opensearch_response_rss.xml b/searx/templates/legacy/opensearch_response_rss.xml @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<rss version="2.0" - xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" - xmlns:atom="http://www.w3.org/2005/Atom"> - <channel> - <title>Searx search: {{ q|e }}</title> - <link>{{ base_url }}?q={{ q|e }}</link> - <description>Search results for "{{ q|e }}" - searx</description> - <opensearch:totalResults>{{ number_of_results }}</opensearch:totalResults> - <opensearch:startIndex>1</opensearch:startIndex> - <opensearch:itemsPerPage>{{ number_of_results }}</opensearch:itemsPerPage> - <atom:link rel="search" type="application/opensearchdescription+xml" href="{{ base_url }}opensearch.xml"/> - <opensearch:Query role="request" searchTerms="{{ q|e }}" startPage="1" /> - {% for r in results %} - <item> - <title>{{ r.title }}</title> - <link>{{ r.url }}</link> - <description>{{ r.content }}</description> - {% if r.pubdate %}<pubDate>{{ r.pubdate }}</pubDate>{% endif %} - </item> - {% endfor %} - </channel> -</rss> diff --git a/searx/templates/oscar/about.html b/searx/templates/oscar/about.html @@ -1,66 +1,5 @@ {% extends "oscar/base.html" %} {% block title %}{{ _('about') }} - {% endblock %} {% block content %} -<div{% if rtl %} dir="ltr"{% endif %}> - <h1>About <a href="{{ url_for('index') }}">searx</a></h1> - - <p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, aggregating the results of other <a href="{{ url_for('preferences') }}">search engines</a> while not storing information about its users. - </p> - <h2>Why use searx?</h2> - <ul> - <li>searx may not offer you as personalised results as Google, but it doesn't generate a profile about you</li> - <li>searx doesn't care about what you search for, never shares anything with a third party, and it can't be used to compromise you</li> - <li>searx is free software, the code is 100% open and you can help to make it better. See more on <a href="https://github.com/asciimoo/searx">github</a></li> - </ul> - <p>If you do care about privacy, want to be a conscious user, or otherwise believe - in digital freedom, make searx your default search engine or run it on your own server</p> - -<h2>Technical details - How does it work?</h2> - -<p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, -inspired by the <a href="https://beniz.github.io/seeks/">seeks project</a>.<br /> -It provides basic privacy by mixing your queries with searches on other platforms without storing search data. Queries are made using a POST request on every browser (except chrome*). Therefore they show up in neither our logs, nor your url history. In case of Chrome* users there is an exception, searx uses the search bar to perform GET requests.<br /> -Searx can be added to your browser's search bar; moreover, it can be set as the default search engine. -</p> - -<h2>How can I make it my own?</h2> - -<p>Searx appreciates your concern regarding logs, so take the <a href="https://github.com/asciimoo/searx">code</a> and run it yourself! <br />Add your Searx to this <a href="https://github.com/asciimoo/searx/wiki/Searx-instances">list</a> to help other people reclaim their privacy and make the Internet freer! -<br />The more decentralized the Internet is, the more freedom we have!</p> - - -<h2>More about searx</h2> - -<ul> - <li><a href="https://github.com/asciimoo/searx">github</a></li> - <li><a href="https://www.ohloh.net/p/searx/">ohloh</a></li> - <li><a href="https://twitter.com/Searx_engine">twitter</a></li> - <li>IRC: #searx @ freenode (<a href="https://kiwiirc.com/client/irc.freenode.com/searx">webclient</a>)</li> - <li><a href="https://www.transifex.com/projects/p/searx/">transifex</a></li> -</ul> - - -<hr /> - -<h2 id="faq">FAQ</h2> - -<h3>How to add to firefox?</h3> -<p><a href="#" onclick="window.external.AddSearchProvider(window.location.protocol + '//' + window.location.host + '{{ url_for('opensearch') }}');">Install</a> searx as a search engine on any version of Firefox! (javascript required)</p> - -<h2 id="dev_faq">Developer FAQ</h2> - -<h3>New engines?</h3> -<ul> - <li>Edit your <a href="https://raw.github.com/asciimoo/searx/master/searx/settings.yml">settings.yml</a></li> - <li>Create your custom engine module, check the <a href="https://github.com/asciimoo/searx/blob/master/examples/basic_engine.py">example engine</a></li> -</ul> -<p>Don't forget to restart searx after config edit!</p> - -<h3>Installation/WSGI support?</h3> -<p>See the <a href="https://github.com/asciimoo/searx/wiki/Installation">installation and setup</a> wiki page</p> - -<h3>How to debug engines?</h3> -<p><a href="{{ url_for('stats') }}">Stats page</a> contains some useful data about the engines used.</p> - -</div> +{% include '__common__/about.html' %} {% endblock %} diff --git a/searx/templates/oscar/opensearch.xml b/searx/templates/oscar/opensearch.xml @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> - <ShortName>{{ instance_name }}</ShortName> - <Description>a privacy-respecting, hackable metasearch engine</Description> - <InputEncoding>UTF-8</InputEncoding> - <Image>{{ urljoin(host, url_for('static', filename='img/favicon.png')) }}</Image> - <LongName>searx metasearch</LongName> - {% if opensearch_method == 'get' %} - <Url type="text/html" method="get" template="{{ host }}search?q={searchTerms}"/> - {% if autocomplete %} - <Url type="application/x-suggestions+json" method="get" template="{{ host }}autocompleter"> - <Param name="format" value="x-suggestions" /> - <Param name="q" value="{searchTerms}" /> - </Url> - {% endif %} - {% else %} - <Url type="text/html" method="post" template="{{ host }}"> - <Param name="q" value="{searchTerms}" /> - </Url> - {% if autocomplete %} - <!-- TODO, POST REQUEST doesn't work --> - <Url type="application/x-suggestions+json" method="get" template="{{ host }}autocompleter"> - <Param name="format" value="x-suggestions" /> - <Param name="q" value="{searchTerms}" /> - </Url> - {% endif %} - {% endif %} -</OpenSearchDescription> diff --git a/searx/templates/oscar/opensearch_response_rss.xml b/searx/templates/oscar/opensearch_response_rss.xml @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<rss version="2.0" - xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" - xmlns:atom="http://www.w3.org/2005/Atom"> - <channel> - <title>Searx search: {{ q|e }}</title> - <link>{{ base_url }}?q={{ q|e }}</link> - <description>Search results for "{{ q|e }}" - searx</description> - <opensearch:totalResults>{{ number_of_results }}</opensearch:totalResults> - <opensearch:startIndex>1</opensearch:startIndex> - <opensearch:itemsPerPage>{{ number_of_results }}</opensearch:itemsPerPage> - <atom:link rel="search" type="application/opensearchdescription+xml" href="{{ base_url }}opensearch.xml"/> - <opensearch:Query role="request" searchTerms="{{ q|e }}" startPage="1" /> - {% for r in results %} - <item> - <title>{{ r.title }}</title> - <link>{{ r.url }}</link> - <description>{{ r.content }}</description> - {% if r.pubdate %}<pubDate>{{ r.pubdate }}</pubDate>{% endif %} - </item> - {% endfor %} - </channel> -</rss> diff --git a/searx/templates/pix-art/about.html b/searx/templates/pix-art/about.html @@ -1,65 +1,4 @@ {% extends 'pix-art/base.html' %} {% block content %} -<div class="row"{% if rtl %} dir="ltr"{% endif %}> - <h1>About <a href="{{ url_for('index') }}">searx</a></h1> - - <p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, aggregating the results of other <a href="{{ url_for('preferences') }}">search engines</a> while not storing information about its users. - </p> - <h2>Why use searx?</h2> - <ul> - <li>searx may not offer you as personalised results as Google, but it doesn't generate a profile about you</li> - <li>searx doesn't care about what you search for, never shares anything with a third party, and it can't be used to compromise you</li> - <li>searx is free software, the code is 100% open and you can help to make it better. See more on <a href="https://github.com/asciimoo/searx">github</a></li> - </ul> - <p>If you do care about privacy, want to be a conscious user, or otherwise believe - in digital freedom, make searx your default search engine or run it on your own server</p> - -<h2>Technical details - How does it work?</h2> - -<p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, -inspired by the <a href="https://beniz.github.io/seeks/">seeks project</a>.<br /> -It provides basic privacy by mixing your queries with searches on other platforms without storing search data. Queries are made using a POST request on every browser (except chrome*). Therefore they show up in neither our logs, nor your url history. In case of Chrome* users there is an exception, if searx used from the search bar it performs GET requests.<br /> -Searx can be added to your browser's search bar; moreover, it can be set as the default search engine. -</p> - -<h2>How can I make it my own?</h2> - -<p>Searx appreciates your concern regarding logs, so take the <a href="https://github.com/asciimoo/searx">code</a> and run it yourself! <br />Add your Searx to this <a href="https://github.com/asciimoo/searx/wiki/Searx-instances">list</a> to help other people reclaim their privacy and make the Internet freer! -<br />The more decentralized Internet is the more freedom we have!</p> - - -<h2>More about searx</h2> - -<ul> - <li><a href="https://github.com/asciimoo/searx">github</a></li> - <li><a href="https://www.ohloh.net/p/searx/">ohloh</a></li> - <li><a href="https://twitter.com/Searx_engine">twitter</a></li> - <li>IRC: #searx @ freenode (<a href="https://kiwiirc.com/client/irc.freenode.com/searx">webclient</a>)</li> - <li><a href="https://www.transifex.com/projects/p/searx/">transifex</a></li> -</ul> - - -<hr /> - -<h2 id="faq">FAQ</h2> - -<h3>How to add to firefox?</h3> -<p><a href="#" onclick="window.external.AddSearchProvider(window.location.protocol + '//' + window.location.host + '{{ url_for('opensearch') }}');">Install</a> searx as a search engine on any version of Firefox! (javascript required)</p> - -<h2 id="dev_faq">Developer FAQ</h2> - -<h3>New engines?</h3> -<ul> - <li>Edit your <a href="https://raw.github.com/asciimoo/searx/master/searx/settings.yml">settings.yml</a></li> - <li>Create your custom engine module, check the <a href="https://github.com/asciimoo/searx/blob/master/examples/basic_engine.py">example engine</a></li> -</ul> -<p>Don't forget to restart searx after config edit!</p> - -<h3>Installation/WSGI support?</h3> -<p>See the <a href="https://github.com/asciimoo/searx/wiki/Installation">installation and setup</a> wiki page</p> - -<h3>How to debug engines?</h3> -<p><a href="{{ url_for('stats') }}">Stats page</a> contains some useful data about the engines used.</p> - -</div> +{% include '__common__/about.html' %} {% endblock %} diff --git a/searx/utils.py b/searx/utils.py @@ -175,6 +175,8 @@ def get_themes(root): templates_path = os.path.join(root, 'templates') themes = os.listdir(os.path.join(static_path, 'themes')) + if '__common__' in themes: + themes.remove('__common__') return static_path, templates_path, themes diff --git a/searx/webapp.py b/searx/webapp.py @@ -52,6 +52,7 @@ from flask import ( from flask_babel import Babel, gettext, format_date, format_decimal from flask.json import jsonify from searx import settings, searx_dir, searx_debug +from searx.exceptions import SearxException, SearxParameterException from searx.engines import ( categories, engines, engine_shortcuts, get_engines_stats, initialize_engines ) @@ -226,7 +227,7 @@ def get_current_theme_name(override=None): 2. cookies 3. settings""" - if override and override in themes: + if override and (override in themes or override == '__common__'): return override theme_name = request.args.get('theme', request.preferences.get_value('theme')) if theme_name not in themes: @@ -400,6 +401,33 @@ def pre_request(): request.user_plugins.append(plugin) +def index_error(output_format, error_message): + if output_format == 'json': + return Response(json.dumps({'error': error_message}), + mimetype='application/json') + elif output_format == 'csv': + response = Response('', mimetype='application/csv') + cont_disp = 'attachment;Filename=searx.csv' + response.headers.add('Content-Disposition', cont_disp) + return response + elif output_format == 'rss': + response_rss = render( + 'opensearch_response_rss.xml', + results=[], + q=request.form['q'] if 'q' in request.form else '', + number_of_results=0, + base_url=get_base_url(), + error_message=error_message + ) + return Response(response_rss, mimetype='text/xml') + else: + # html + request.errors.append(gettext('search error')) + return render( + 'index.html', + ) + + @app.route('/search', methods=['GET', 'POST']) @app.route('/', methods=['GET', 'POST']) def index(): @@ -408,10 +436,19 @@ def index(): Supported outputs: html, json, csv, rss. """ + # output_format + output_format = request.form.get('format', 'html') + if output_format not in ['html', 'csv', 'json', 'rss']: + output_format = 'html' + + # check if there is query if request.form.get('q') is None: - return render( - 'index.html', - ) + if output_format == 'html': + return render( + 'index.html', + ) + else: + return index_error(output_format, 'No query'), 400 # search search_query = None @@ -421,20 +458,24 @@ def index(): # search = Search(search_query) # without plugins search = SearchWithPlugins(search_query, request) result_container = search.search() - except: - request.errors.append(gettext('search error')) + except Exception as e: + # log exception logger.exception('search error') - return render( - 'index.html', - ) + # is it an invalid input parameter or something else ? + if (issubclass(e.__class__, SearxParameterException)): + return index_error(output_format, e.message), 400 + else: + return index_error(output_format, gettext('search error')), 500 + + # results results = result_container.get_ordered_results() + number_of_results = result_container.results_number() + if number_of_results < result_container.results_length(): + number_of_results = 0 # UI advanced_search = request.form.get('advanced_search', None) - output_format = request.form.get('format', 'html') - if output_format not in ['html', 'csv', 'json', 'rss']: - output_format = 'html' # output for result in results: @@ -470,10 +511,6 @@ def index(): else: result['publishedDate'] = format_date(result['publishedDate']) - number_of_results = result_container.results_number() - if number_of_results < result_container.results_length(): - number_of_results = 0 - if output_format == 'json': return Response(json.dumps({'query': search_query.query, 'number_of_results': number_of_results, @@ -501,7 +538,8 @@ def index(): results=results, q=request.form['q'], number_of_results=number_of_results, - base_url=get_base_url() + base_url=get_base_url(), + override_theme='__common__', ) return Response(response_rss, mimetype='text/xml') @@ -722,7 +760,8 @@ def opensearch(): ret = render('opensearch.xml', opensearch_method=method, host=get_base_url(), - urljoin=urljoin) + urljoin=urljoin, + override_theme='__common__') resp = Response(response=ret, status=200, diff --git a/tests/unit/test_webapp.py b/tests/unit/test_webapp.py @@ -46,6 +46,8 @@ class ViewsTestCase(SearxTestCase): Search.search = search_mock def get_current_theme_name_mock(override=None): + if override: + return override return 'legacy' webapp.get_current_theme_name = get_current_theme_name_mock