From 74e6f5d72442a19a896aaf6ee3d7af7d480e18ec Mon Sep 17 00:00:00 2001
From: Sion Kazama <13185633+KazamaSion@users.noreply.github.com>
Date: Tue, 19 May 2020 20:47:35 +0800
Subject: [PATCH 1/5] Revise outdated URLs

---
 docs/admin/settings.rst | 2 +-
 searx/settings.yml      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/admin/settings.rst b/docs/admin/settings.rst
index 0bfdcc6cb..2c42a21e9 100644
--- a/docs/admin/settings.rst
+++ b/docs/admin/settings.rst
@@ -98,7 +98,7 @@ Global Settings
   specific instance of searx, a locale can be defined using an ISO language
   code, like ``fr``, ``en``, ``de``.
 
-.. _requests proxies: http://docs.python-requests.org/en/latest/user/advanced/#proxies
+.. _requests proxies: http://requests.readthedocs.io/en/latest/user/advanced/#proxies
 .. _PR SOCKS support: https://github.com/kennethreitz/requests/pull/478
 
 ``outgoing_proxies`` :
diff --git a/searx/settings.yml b/searx/settings.yml
index 77cc4e087..2497a764b 100644
--- a/searx/settings.yml
+++ b/searx/settings.yml
@@ -41,7 +41,7 @@ outgoing: # communication with search engines
     pool_maxsize : 10 # Number of simultaneous requests by host
 # uncomment below section if you want to use a proxy
 # see http://docs.python-requests.org/en/latest/user/advanced/#proxies
-# SOCKS proxies are also supported: see http://docs.python-requests.org/en/master/user/advanced/#socks
+# SOCKS proxies are also supported: see http://requests.readthedocs.io/en/master/user/advanced/#socks
 #    proxies :
 #        http : http://127.0.0.1:8080
 #        https: http://127.0.0.1:8080

From e84cdb66ae9842c304fde631517f8ebc9c7aaaaa Mon Sep 17 00:00:00 2001
From: resynth1943 <resynth1943@tutanota.com>
Date: Wed, 27 May 2020 13:49:00 +0100
Subject: [PATCH 2/5] Add autofocus to all search inputs

---
 searx/templates/courgette/search.html  | 2 +-
 searx/templates/legacy/search.html     | 2 +-
 searx/templates/oscar/search.html      | 2 +-
 searx/templates/oscar/search_full.html | 2 +-
 searx/templates/pix-art/search.html    | 2 +-
 searx/templates/simple/search.html     | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/searx/templates/courgette/search.html b/searx/templates/courgette/search.html
index bd4efd42f..fe70fde05 100644
--- a/searx/templates/courgette/search.html
+++ b/searx/templates/courgette/search.html
@@ -1,6 +1,6 @@
 <form method="{{ method or 'POST' }}" action="{{ url_for('index') }}" id="search_form">
     <div id="search_wrapper">
-        <input type="text" placeholder="{{ _('Search for...') }}" id="q" class="q" name="q" tabindex="1" autocomplete="off" {% if q %}value="{{ q }}"{% endif %}/>
+        <input type="text" autofocus placeholder="{{ _('Search for...') }}" id="q" class="q" name="q" tabindex="1" autocomplete="off" {% if q %}value="{{ q }}"{% endif %}/>
         <input type="submit" value="search" id="search_submit" />
     </div>
     {% include 'courgette/categories.html' %}
diff --git a/searx/templates/legacy/search.html b/searx/templates/legacy/search.html
index 4d37f9ba1..fcd08d6d2 100644
--- a/searx/templates/legacy/search.html
+++ b/searx/templates/legacy/search.html
@@ -1,6 +1,6 @@
 <form method="{{ method or 'POST' }}" action="{{ url_for('index') }}" id="search_form">
     <div id="search_wrapper">
-        <input type="text" placeholder="{{ _('Search for...') }}" id="q" class="q" name="q" tabindex="1" autocomplete="off" size="100" {% if q %}value="{{ q }}"{% endif %}/>
+        <input type="text" autofocus placeholder="{{ _('Search for...') }}" id="q" class="q" name="q" tabindex="1" autocomplete="off" size="100" {% if q %}value="{{ q }}"{% endif %}/>
         <input type="submit" value="search" id="search_submit" />
     </div>
     {% set display_tooltip = true %}
diff --git a/searx/templates/oscar/search.html b/searx/templates/oscar/search.html
index 9978801ca..666a4df38 100644
--- a/searx/templates/oscar/search.html
+++ b/searx/templates/oscar/search.html
@@ -3,7 +3,7 @@
   <div class="row">
     <div class="col-xs-12 col-md-8">
       <div class="input-group search-margin">
-        <input type="search" name="q" class="form-control" id="q" placeholder="{{ _('Search for...') }}" aria-label="{{ _('Search for...') }}" autocomplete="off" value="{{ q }}" accesskey="s">
+        <input type="search" autofocus name="q" class="form-control" id="q" placeholder="{{ _('Search for...') }}" aria-label="{{ _('Search for...') }}" autocomplete="off" value="{{ q }}" accesskey="s">
         <span class="input-group-btn">
             <button type="submit" class="btn btn-default" aria-label="{{ _('Start search') }}"><span class="hide_if_nojs">{{ icon('search') }}</span><span class="hidden active_if_nojs">{{ _('Start search') }}</span></button>
             <button type="reset" class="btn btn-default" aria-label="{{ _('Clear search') }}"><span class="hide_if_nojs">{{ icon('remove') }}</span><span class="hidden active_if_nojs">{{ _('Clear') }}</span></button>
diff --git a/searx/templates/oscar/search_full.html b/searx/templates/oscar/search_full.html
index ea821dc45..1f1c50e50 100644
--- a/searx/templates/oscar/search_full.html
+++ b/searx/templates/oscar/search_full.html
@@ -6,7 +6,7 @@
     {% else %}
     <div class="input-group col-md-8 col-md-offset-2">
     {% endif %}
-        <input type="search" name="q" class="form-control input-lg autofocus" id="q" placeholder="{{ _('Search for...') }}" aria-label="{{ _('Search for...') }}" autocomplete="off" value="{{ q }}" accesskey="s">
+        <input type="search" autofocus name="q" class="form-control input-lg autofocus" id="q" placeholder="{{ _('Search for...') }}" aria-label="{{ _('Search for...') }}" autocomplete="off" value="{{ q }}" accesskey="s">
         <span class="input-group-btn">
             <button type="submit" class="btn btn-default input-lg" aria-label="{{ _('Start search') }}"><span class="hide_if_nojs">{{ icon('search') }}</span><span class="hidden active_if_nojs">{{ _('Start search') }}</span></button>
             <button type="reset" class="btn btn-default input-lg" aria-label="{{ _('Clear search') }}"><span class="hide_if_nojs">{{ icon('remove') }}</span><span class="hidden active_if_nojs">{{ _('Clear') }}</span></button>
diff --git a/searx/templates/pix-art/search.html b/searx/templates/pix-art/search.html
index 4d129ec68..bb40559db 100644
--- a/searx/templates/pix-art/search.html
+++ b/searx/templates/pix-art/search.html
@@ -1,6 +1,6 @@
 <form method="{{ method or 'POST' }}" action="{{ url_for('index') }}" id="search_form">
     <div id="search_wrapper">
-        <input type="text" placeholder="{{ _('Search for...') }}" id="q" class="q" name="q" tabindex="1" size="100" {% if q %}value="{{ q }}"{% endif %}/>
+        <input type="text" autofocus placeholder="{{ _('Search for...') }}" id="q" class="q" name="q" tabindex="1" size="100" {% if q %}value="{{ q }}"{% endif %}/>
         <input type="submit" value="" id="search_submit" />
         {% for category in categories %}
         <input type="hidden" name="category_{{ category }}" value="1"/>
diff --git a/searx/templates/simple/search.html b/searx/templates/simple/search.html
index e9023b420..61d52dbc7 100644
--- a/searx/templates/simple/search.html
+++ b/searx/templates/simple/search.html
@@ -1,7 +1,7 @@
 <form id="search" method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
   <div id="search_wrapper">
     <div class="search_box">
-      <input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" tabindex="1" autocomplete="off" spellcheck="false" dir="auto" {% if q %}value="{{ q }}"{% endif %} >
+      <input id="q" autofocus name="q" type="text" placeholder="{{ _('Search for...') }}" tabindex="1" autocomplete="off" spellcheck="false" dir="auto" {% if q %}value="{{ q }}"{% endif %} >
       <button id="clear_search" type="button" tabindex="-1"><span class="hide_if_nojs">{{ icon('close') }}</span><span class="show_if_nojs">{{ _('Clear search') }}</span></button>
       <button id="send_search" type="submit" tabindex="-1"><span class="hide_if_nojs">{{ icon('search') }}</span><span class="show_if_nojs">{{ _('Start search') }}</span></button>
     </div>

From e3282748d0433d455336487f7e36b789fe6ade30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= <sitbackandwait@gmail.com>
Date: Sun, 29 Mar 2020 13:14:06 +0200
Subject: [PATCH 3/5] add display_error_messages option to engine settings

A new option is added to engines to hide error messages from users. It
is called `display_error_messages` and by default it is set to `True`.
If it is set to `False` error messages do not show up on the UI.

Keep in mind that engines are still suspended if needed regardless of
this setting.

Closes #1828
---
 docs/admin/engines.rst       | 4 ++++
 docs/admin/settings.rst      | 3 +++
 docs/dev/engine_overview.rst | 1 +
 searx/engines/__init__.py    | 1 +
 searx/results.py             | 3 ++-
 5 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/docs/admin/engines.rst b/docs/admin/engines.rst
index 4b78c8c2b..4d1872dfc 100644
--- a/docs/admin/engines.rst
+++ b/docs/admin/engines.rst
@@ -26,6 +26,8 @@ Safe search   **SS**
 Weigth        **W**
 ------------- ----------- ---------------------------------
 Disabled      **D**
+------------- ----------- ---------------------------------
+Show errors   **DE**
 ============= =========== =================================
 
 Configuration defaults (at built time):
@@ -51,6 +53,7 @@ Configuration defaults (at built time):
         - O
 	- W
 	- D
+	- DE
 
       {% for name, mod in engines.items() %}
 
@@ -67,5 +70,6 @@ Configuration defaults (at built time):
         - {{(mod.offline and "y") or ""}}
         - {{mod.weight or 1 }}
         - {{(mod.disabled and "y") or ""}}
+        - {{(mod.display_error_messages and "y") or ""}}
 
      {% endfor %}
diff --git a/docs/admin/settings.rst b/docs/admin/settings.rst
index 2c42a21e9..2bfbae35c 100644
--- a/docs/admin/settings.rst
+++ b/docs/admin/settings.rst
@@ -175,6 +175,9 @@ Engine settings
 ``weigth`` : default ``1``
   Weighting of the results of this engine.
 
+``display_error_messages`` : default ``True``
+  When an engine returns an error, the message is displayed on the user interface.
+
 .. note::
 
    A few more options are possible, but they are pretty specific to some
diff --git a/docs/dev/engine_overview.rst b/docs/dev/engine_overview.rst
index 449c837a9..c3c81fff8 100644
--- a/docs/dev/engine_overview.rst
+++ b/docs/dev/engine_overview.rst
@@ -57,6 +57,7 @@ engine                  string      name of searx-engine
                                     (filename without ``.py``)
 shortcut                string      shortcut of search-engine
 timeout                 string      specific timeout for search-engine
+display_error_messages  boolean     display error messages on the web UI
 ======================= =========== ===========================================
 
 
diff --git a/searx/engines/__init__.py b/searx/engines/__init__.py
index 9ccef8b54..48c02e2e7 100644
--- a/searx/engines/__init__.py
+++ b/searx/engines/__init__.py
@@ -55,6 +55,7 @@ engine_default_args = {'paging': False,
                        'continuous_errors': 0,
                        'time_range_support': False,
                        'offline': False,
+                       'display_error_messages': True,
                        'tokens': []}
 
 
diff --git a/searx/results.py b/searx/results.py
index 02ab9efb1..62a01a5bd 100644
--- a/searx/results.py
+++ b/searx/results.py
@@ -346,7 +346,8 @@ class ResultContainer(object):
         return resultnum_sum / len(self._number_of_results)
 
     def add_unresponsive_engine(self, engine_name, error_type, error_message=None):
-        self.unresponsive_engines.add((engine_name, error_type, error_message))
+        if engines[engine_name].display_error_messages:
+            self.unresponsive_engines.add((engine_name, error_type, error_message))
 
     def add_timing(self, engine_name, engine_time, page_load_time):
         self.timings.append({

From d7d89369cb3f9d33855749f13c410fb444a81104 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= <sitbackandwait@gmail.com>
Date: Sun, 31 May 2020 22:36:09 +0200
Subject: [PATCH 4/5] add disable all and allow all engines button to Oscar
 preferences

---
 searx/static/themes/oscar/js/searx.js               | 10 ++++++++++
 searx/static/themes/oscar/js/searx.min.js           |  4 ++--
 searx/static/themes/oscar/js/searx_src/toggleall.js | 10 ++++++++++
 searx/templates/oscar/preferences.html              |  8 ++++++++
 4 files changed, 30 insertions(+), 2 deletions(-)
 create mode 100644 searx/static/themes/oscar/js/searx_src/toggleall.js

diff --git a/searx/static/themes/oscar/js/searx.js b/searx/static/themes/oscar/js/searx.js
index 9138576f5..c6feda50c 100644
--- a/searx/static/themes/oscar/js/searx.js
+++ b/searx/static/themes/oscar/js/searx.js
@@ -357,3 +357,13 @@ $(document).ready(function(){
         $( this ).off( event );
     });
 });
+;$(document).ready(function(){
+    $("#allow-all-engines").click(function() {
+        $(".onoffswitch-checkbox").each(function() { this.checked = false;});
+    });
+
+    $("#disable-all-engines").click(function() {
+        $(".onoffswitch-checkbox").each(function() { this.checked = true;});
+    });
+});
+
diff --git a/searx/static/themes/oscar/js/searx.min.js b/searx/static/themes/oscar/js/searx.min.js
index 4c01dca94..9c3e13b59 100644
--- a/searx/static/themes/oscar/js/searx.min.js
+++ b/searx/static/themes/oscar/js/searx.min.js
@@ -1,2 +1,2 @@
-/*! oscar/searx.min.js | 23-03-2020 | https://github.com/asciimoo/searx */
-requirejs.config({baseUrl:"./static/themes/oscar/js",paths:{app:"../app"}}),window.searx=function(a){"use strict";var b=a.currentScript||function(){var b=a.getElementsByTagName("script");return b[b.length-1]}();return{autocompleter:"true"===b.getAttribute("data-autocompleter"),method:b.getAttribute("data-method")}}(document),searx.autocompleter&&(searx.searchResults=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace("value"),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:"./autocompleter?q=%QUERY"}),searx.searchResults.initialize()),$(document).ready(function(){searx.autocompleter&&($("#q").typeahead(null,{name:"search-results",displayKey:function(a){return a},source:searx.searchResults.ttAdapter()}),$("#q").bind("typeahead:selected",function(a,b){$("#search_form").submit()}))}),$(document).ready(function(){$("#q.autofocus").focus(),$(".select-all-on-click").click(function(){$(this).select()}),$(".btn-collapse").click(function(){var a=$(this).data("btn-text-collapsed"),b=$(this).data("btn-text-not-collapsed");""!==a&&""!==b&&($(this).hasClass("collapsed")?new_html=$(this).html().replace(a,b):new_html=$(this).html().replace(b,a),$(this).html(new_html))}),$(".btn-toggle .btn").click(function(){var a="btn-"+$(this).data("btn-class"),b=$(this).data("btn-label-default"),c=$(this).data("btn-label-toggled");""!==c&&($(this).hasClass("btn-default")?new_html=$(this).html().replace(b,c):new_html=$(this).html().replace(c,b),$(this).html(new_html)),$(this).toggleClass(a),$(this).toggleClass("btn-default")}),$(".media-loader").click(function(){var a=$(this).data("target"),b=$(a+" > iframe"),c=b.attr("src");void 0!==c&&c!==!1||b.attr("src",b.data("src"))}),$(".btn-sm").dblclick(function(){var a="btn-"+$(this).data("btn-class");$(this).hasClass("btn-default")?($(".btn-sm > input").attr("checked","checked"),$(".btn-sm > input").prop("checked",!0),$(".btn-sm").addClass(a),$(".btn-sm").addClass("active"),$(".btn-sm").removeClass("btn-default")):($(".btn-sm > input").attr("checked",""),$(".btn-sm > input").removeAttr("checked"),$(".btn-sm > input").checked=!1,$(".btn-sm").removeClass(a),$(".btn-sm").removeClass("active"),$(".btn-sm").addClass("btn-default"))})}),$(document).ready(function(){$(".searx_overpass_request").on("click",function(a){var b="https://overpass-api.de/api/interpreter?data=",c=b+"[out:json][timeout:25];(",d=");out meta;",e=$(this).data("osm-id"),f=$(this).data("osm-type"),g=$(this).data("result-table"),h="#"+$(this).data("result-table-loadicon"),i=["addr:city","addr:country","addr:housenumber","addr:postcode","addr:street"];if(e&&f&&g){g="#"+g;var j=null;switch(f){case"node":j=c+"node("+e+");"+d;break;case"way":j=c+"way("+e+");"+d;break;case"relation":j=c+"relation("+e+");"+d}if(j){$.ajax(j).done(function(a){if(a&&a.elements&&a.elements[0]){var b=a.elements[0],c=$(g).html();for(var d in b.tags)if(null===b.tags.name||i.indexOf(d)==-1){switch(c+="<tr><td>"+d+"</td><td>",d){case"phone":case"fax":c+='<a href="tel:'+b.tags[d].replace(/ /g,"")+'">'+b.tags[d]+"</a>";break;case"email":c+='<a href="mailto:'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"website":case"url":c+='<a href="'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikidata":c+='<a href="https://www.wikidata.org/wiki/'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikipedia":if(b.tags[d].indexOf(":")!=-1){c+='<a href="https://'+b.tags[d].substring(0,b.tags[d].indexOf(":"))+".wikipedia.org/wiki/"+b.tags[d].substring(b.tags[d].indexOf(":")+1)+'">'+b.tags[d]+"</a>";break}default:c+=b.tags[d]}c+="</td></tr>"}$(g).html(c),$(g).removeClass("hidden"),$(h).addClass("hidden")}}).fail(function(){$(h).html($(h).html()+'<p class="text-muted">could not load data!</p>')})}}$(this).off(a)}),$(".searx_init_map").on("click",function(a){var b=$(this).data("leaflet-target"),c=$(this).data("map-lon"),d=$(this).data("map-lat"),e=$(this).data("map-zoom"),f=$(this).data("map-boundingbox"),g=$(this).data("map-geojson");require(["leaflet-0.7.3.min"],function(a){f&&(southWest=L.latLng(f[0],f[2]),northEast=L.latLng(f[1],f[3]),map_bounds=L.latLngBounds(southWest,northEast)),L.Icon.Default.imagePath="./static/themes/oscar/img/map";var h=L.map(b),i="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",j='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',k=new L.TileLayer(i,{minZoom:1,maxZoom:19,attribution:j}),l="https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png",m='Wikimedia maps beta | Maps data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';new L.TileLayer(l,{minZoom:1,maxZoom:19,attribution:m});map_bounds?setTimeout(function(){h.fitBounds(map_bounds,{maxZoom:17})},0):c&&d&&(e?h.setView(new L.LatLng(d,c),e):h.setView(new L.LatLng(d,c),8)),h.addLayer(k);var n={"OSM Mapnik":k};L.control.layers(n).addTo(h),g&&L.geoJson(g).addTo(h)}),$(this).off(a)})});
\ No newline at end of file
+/*! oscar/searx.min.js | 31-05-2020 |   */
+requirejs.config({baseUrl:"./static/themes/oscar/js",paths:{app:"../app"}}),window.searx=function(a){"use strict";var b=a.currentScript||function(){var b=a.getElementsByTagName("script");return b[b.length-1]}();return{autocompleter:"true"===b.getAttribute("data-autocompleter"),method:b.getAttribute("data-method")}}(document),searx.autocompleter&&(searx.searchResults=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace("value"),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:"./autocompleter?q=%QUERY"}),searx.searchResults.initialize()),$(document).ready(function(){searx.autocompleter&&($("#q").typeahead(null,{name:"search-results",displayKey:function(a){return a},source:searx.searchResults.ttAdapter()}),$("#q").bind("typeahead:selected",function(a,b){$("#search_form").submit()}))}),$(document).ready(function(){$("#q.autofocus").focus(),$(".select-all-on-click").click(function(){$(this).select()}),$(".btn-collapse").click(function(){var a=$(this).data("btn-text-collapsed"),b=$(this).data("btn-text-not-collapsed");""!==a&&""!==b&&($(this).hasClass("collapsed")?new_html=$(this).html().replace(a,b):new_html=$(this).html().replace(b,a),$(this).html(new_html))}),$(".btn-toggle .btn").click(function(){var a="btn-"+$(this).data("btn-class"),b=$(this).data("btn-label-default"),c=$(this).data("btn-label-toggled");""!==c&&($(this).hasClass("btn-default")?new_html=$(this).html().replace(b,c):new_html=$(this).html().replace(c,b),$(this).html(new_html)),$(this).toggleClass(a),$(this).toggleClass("btn-default")}),$(".media-loader").click(function(){var a=$(this).data("target"),b=$(a+" > iframe"),c=b.attr("src");void 0!==c&&c!==!1||b.attr("src",b.data("src"))}),$(".btn-sm").dblclick(function(){var a="btn-"+$(this).data("btn-class");$(this).hasClass("btn-default")?($(".btn-sm > input").attr("checked","checked"),$(".btn-sm > input").prop("checked",!0),$(".btn-sm").addClass(a),$(".btn-sm").addClass("active"),$(".btn-sm").removeClass("btn-default")):($(".btn-sm > input").attr("checked",""),$(".btn-sm > input").removeAttr("checked"),$(".btn-sm > input").checked=!1,$(".btn-sm").removeClass(a),$(".btn-sm").removeClass("active"),$(".btn-sm").addClass("btn-default"))})}),$(document).ready(function(){$(".searx_overpass_request").on("click",function(a){var b="https://overpass-api.de/api/interpreter?data=",c=b+"[out:json][timeout:25];(",d=");out meta;",e=$(this).data("osm-id"),f=$(this).data("osm-type"),g=$(this).data("result-table"),h="#"+$(this).data("result-table-loadicon"),i=["addr:city","addr:country","addr:housenumber","addr:postcode","addr:street"];if(e&&f&&g){g="#"+g;var j=null;switch(f){case"node":j=c+"node("+e+");"+d;break;case"way":j=c+"way("+e+");"+d;break;case"relation":j=c+"relation("+e+");"+d}if(j){$.ajax(j).done(function(a){if(a&&a.elements&&a.elements[0]){var b=a.elements[0],c=$(g).html();for(var d in b.tags)if(null===b.tags.name||i.indexOf(d)==-1){switch(c+="<tr><td>"+d+"</td><td>",d){case"phone":case"fax":c+='<a href="tel:'+b.tags[d].replace(/ /g,"")+'">'+b.tags[d]+"</a>";break;case"email":c+='<a href="mailto:'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"website":case"url":c+='<a href="'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikidata":c+='<a href="https://www.wikidata.org/wiki/'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikipedia":if(b.tags[d].indexOf(":")!=-1){c+='<a href="https://'+b.tags[d].substring(0,b.tags[d].indexOf(":"))+".wikipedia.org/wiki/"+b.tags[d].substring(b.tags[d].indexOf(":")+1)+'">'+b.tags[d]+"</a>";break}default:c+=b.tags[d]}c+="</td></tr>"}$(g).html(c),$(g).removeClass("hidden"),$(h).addClass("hidden")}}).fail(function(){$(h).html($(h).html()+'<p class="text-muted">could not load data!</p>')})}}$(this).off(a)}),$(".searx_init_map").on("click",function(a){var b=$(this).data("leaflet-target"),c=$(this).data("map-lon"),d=$(this).data("map-lat"),e=$(this).data("map-zoom"),f=$(this).data("map-boundingbox"),g=$(this).data("map-geojson");require(["leaflet-0.7.3.min"],function(a){f&&(southWest=L.latLng(f[0],f[2]),northEast=L.latLng(f[1],f[3]),map_bounds=L.latLngBounds(southWest,northEast)),L.Icon.Default.imagePath="./static/themes/oscar/img/map";var h=L.map(b),i="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",j='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',k=new L.TileLayer(i,{minZoom:1,maxZoom:19,attribution:j}),l="https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png",m='Wikimedia maps beta | Maps data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';new L.TileLayer(l,{minZoom:1,maxZoom:19,attribution:m});map_bounds?setTimeout(function(){h.fitBounds(map_bounds,{maxZoom:17})},0):c&&d&&(e?h.setView(new L.LatLng(d,c),e):h.setView(new L.LatLng(d,c),8)),h.addLayer(k);var n={"OSM Mapnik":k};L.control.layers(n).addTo(h),g&&L.geoJson(g).addTo(h)}),$(this).off(a)})}),$(document).ready(function(){$("#allow-all-engines").click(function(){$(".onoffswitch-checkbox").each(function(){this.checked=!1})}),$("#disable-all-engines").click(function(){$(".onoffswitch-checkbox").each(function(){this.checked=!0})})});
\ No newline at end of file
diff --git a/searx/static/themes/oscar/js/searx_src/toggleall.js b/searx/static/themes/oscar/js/searx_src/toggleall.js
new file mode 100644
index 000000000..b6c484e3e
--- /dev/null
+++ b/searx/static/themes/oscar/js/searx_src/toggleall.js
@@ -0,0 +1,10 @@
+$(document).ready(function(){
+    $("#allow-all-engines").click(function() {
+        $(".onoffswitch-checkbox").each(function() { this.checked = false;});
+    });
+
+    $("#disable-all-engines").click(function() {
+        $(".onoffswitch-checkbox").each(function() { this.checked = true;});
+    });
+});
+
diff --git a/searx/templates/oscar/preferences.html b/searx/templates/oscar/preferences.html
index b03929df3..38d9c7b04 100644
--- a/searx/templates/oscar/preferences.html
+++ b/searx/templates/oscar/preferences.html
@@ -155,6 +155,14 @@
 
                 <!-- Tab panes -->
                 <div class="tab-content">
+
+                    <div class="hide_if_nojs">
+                        <p class="text-{% if rtl %}left{% else %}right{% endif %}">
+                            <button type="button" class="btn btn-default btn-success" id="allow-all-engines">{{ _("Allow all") }}</button>
+                            <button type="button" class="btn btn-default btn-danger" id="disable-all-engines">{{ _("Disable all") }}</button>
+                        </p>
+                    </div>
+
                     {% for categ in all_categories %}
                     <noscript><label>{{ _(categ) }}</label>
                     </noscript>

From a3e15a3df6f5502c58f82f18e09d80a2fdf7a957 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= <sitbackandwait@gmail.com>
Date: Sun, 31 May 2020 20:02:58 +0200
Subject: [PATCH 5/5] Fix Farsi language in Oscar && adjust tables with RTL

---
 searx/templates/oscar/preferences.html        |  28 +++++++++---------
 .../fa_IR/LC_MESSAGES/messages.mo             | Bin 14413 -> 14403 bytes
 .../fa_IR/LC_MESSAGES/messages.po             |   2 +-
 searx/webapp.py                               |   2 +-
 4 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/searx/templates/oscar/preferences.html b/searx/templates/oscar/preferences.html
index b03929df3..2211da2aa 100644
--- a/searx/templates/oscar/preferences.html
+++ b/searx/templates/oscar/preferences.html
@@ -174,14 +174,14 @@
                                     <th>{{ _("Avg. time") }}</th>
                                     <th>{{ _("Max time") }}</th>
                                     {% else %}
-                                    <th>{{ _("Max time") }}</th>
-                                    <th>{{ _("Avg. time") }}</th>
-                                    <th>{{ _("Time range") }}</th>
-                                    <th>{{ _("SafeSearch") }}</th>
-                                    <th>{{ _("Selected language") }}</th>
-                                    <th>{{ _("Shortcut") }}</th>
-                                    <th>{{ _("Engine name") }}</th>
-                                    <th>{{ _("Allow") }}</th>
+                                    <th class="text-right">{{ _("Max time") }}</th>
+                                    <th class="text-right">{{ _("Avg. time") }}</th>
+                                    <th class="text-right">{{ _("Time range") }}</th>
+                                    <th class="text-right">{{ _("SafeSearch") }}</th>
+                                    <th class="text-right">{{ _("Selected language") }}</th>
+                                    <th class="text-right">{{ _("Shortcut") }}</th>
+                                    <th class="text-right">{{ _("Engine name") }}</th>
+                                    <th class="text-right">{{ _("Allow") }}</th>
                                     {% endif %}
                                 </tr>
                         {% for search_engine in engines_by_category[categ] %}
@@ -256,10 +256,10 @@
                 </p>
                 <table class="table table-striped">
                     <tr>
-                        <th class="text-muted">{{ _('Name') }}</th>
-                        <th class="text-muted">{{ _('Keywords') }}</th>
-                        <th class="text-muted">{{ _('Description') }}</th>
-                        <th class="text-muted">{{ _('Examples') }}</th>
+                        <th class="text-muted{% if rtl %} text-right{% endif %}">{{ _('Name') }}</th>
+                        <th class="text-muted{% if rtl %} text-right{% endif %}">{{ _('Keywords') }}</th>
+                        <th class="text-muted{% if rtl %} text-right{% endif %}">{{ _('Description') }}</th>
+                        <th class="text-muted{% if rtl %} text-right{% endif %}">{{ _('Examples') }}</th>
                     </tr>
 
                     {% for answerer in answerers %}
@@ -285,8 +285,8 @@
                 {% if cookies %}
                 <table class="table table-striped">
                     <tr>
-                        <th class="text-muted" style="padding-right:40px;">{{ _('Cookie name') }}</th>
-                        <th class="text-muted">{{ _('Value') }}</th>
+                        <th class="text-muted{% if rtl %} text-right{% endif %}" style="padding-right:40px;">{{ _('Cookie name') }}</th>
+                        <th class="text-muted{% if rtl %} text-right{% endif %}">{{ _('Value') }}</th>
                     </tr>
 
                     {% for cookie in cookies %}
diff --git a/searx/translations/fa_IR/LC_MESSAGES/messages.mo b/searx/translations/fa_IR/LC_MESSAGES/messages.mo
index a2f50338647770a6065e78208cbb207308c65487..56c04178f62da4130dc23c491bc00f1f749d9ddf 100644
GIT binary patch
delta 1331
zcmXZbPe@cz6vy$?!ofzJaU8|5CL6P?98=5uL(~+Nwx~8qWJN_ONf9cU1QtzDL}5@Z
zT4kFgqm`kUkR<enBut7HK`tsJiy)*$NF-w4U+-?_bI+Z3&pr3t_r}{^v^_fSOO~72
z_oZfGjKs`BSb{Z}K+T`UV(h{QK1M&j#Q;uVH~zrIc%{HB9q*y?^<geP!$SOs$~#wJ
zNvmTJT4uHt8!!#;pf-4bO3;sa_!9H+6RyNL)N?Dyx)#e(8y&+;>_ipRh5z%RHtu)x
zuL_eaW@3_wAf_(&Hi)1WR%0{PV-pUe3W>2ug>7)|LM1-z;?t-OTz2s-XAkBuKZq)5
zEXhDE{NS8IAMtPeg|n!Z|19zrq;TwM;!M>1JSt&im6xX!xlP-ID&P>-<4G5fU>Wfk
zYJGB+K|h1+)n*rP6m_z?VzVeVU>0_uPIwh-u^aX7OkygA<7PWBiqvXNn74q|BiC*B
zOT2ZXs5}{K*pvOOfB{{#D%9N_M7<O3E`EYq@E$Ai8|n(8rQQjvP*=4L_5Tsn-QPy#
z>%|Nlaq$~e$G&2S{p~LUwLG1^=%iuXf<>r>&8QQ1;0+wc5!}h~_0swI>BNn=8;3A}
zDeKG@VK!D{8PaTPMip=q1MF|T40OUlq&xN+)zTRZ;ykK=V1?O!+=~h9L!ERQ{Wy<G
z>|gI4Aci60qo{YG9r<AFBI+yZ!K5ahGl=07Dxr@)s-?N8xB``UJF2h)sDzEEjoVO#
zp2H>Bg<*V%S@_ib{|<E}Ur?R-Q%V1oAYA1o%ttMZqaNJs+~?+7QFng{bMUT<2T%o#
zqY9rut)FoQ=)dA3RQ?2B$34}|a-H^>2`voPcn`)0uBDyIUU<BtrSZ&()|U2x)L3og
EA8nhG#Q*>R

delta 1341
zcmXZbTS!z<6vpvYq^6eRWlSd<FJqaFm3HxxP)wm_4@M9LK@o{zk%dApiFOE-DC|Pu
zO9efZ1c{nYf@M*X(1j$d8S5cP=z^#aL{HNH>ztSQ?Y+<Jwbx$joENQcTL(MhooX}t
zo@bVUp?tG6tiUR)N3CDNF!o|LKEou8VG7RRUHpwXc(cH41wKN>8^J7mjfMCP6*nPd
zj@2>937PG|Moh;0r~`&j0Y))^?=TmC;Cf6Tn*LXcTd*2+Pz$DF7b>A%{2vc>@Tj-`
zzR)pS$HFWNK1^Th9uPup+>On644ZHql}MOPO0357Fe>mVZ{C5bz;$na$Fm<ZSsz0s
zH03Z*3BP*IV?6UkT)?;@x8#3N8+=@Q4p*aEkyz{o458vwA>FjSs05nvAfET;6IjZ8
z3bo&f+hF#XK`vgzNz}~_gw57qBc`K+y5TLX#Rpi1v$!0CB^-)HNUnAc14}49(rz2r
z=<b_D#mU-a<|nL`FrcayLG|t=)?ueNe~H@g1<P>()q<kU?hPZTRyClWpGNim9xC1-
zuEYs%{t?xJIZWexTSh(NSy+X-X%Hh=hT7PMy0L>da2%iFA+E2N&d*Of)?oua#}xE!
zrA?TNmAC_`y0xJaxQ!{CZ-WeU!!e{f_5oE=+vdKMiKqkucm$8*E*wGK^e-l1;&wN%
zA0y1en1*Li??NZ?;n-EwSJaP=7Tz$($9Yu1RO+ab7NF)kQ5o+?CDw!rcoubVJNmF2
zgV>81IE?A|%6mSIYRNBDWtLV@e+39uxB-h%8_Q9D+~;}1Tfczn{WZ+QK5za6mCz?t
z;xnlIs=LhgEJMYw#~wUd$y3^CKUvVmK$W|peE3Roi$5be66=n2O+SndMF;X@m!o~3
LdxjVDYP0_VKuMU7

diff --git a/searx/translations/fa_IR/LC_MESSAGES/messages.po b/searx/translations/fa_IR/LC_MESSAGES/messages.po
index 6689dafe7..28cfd1ed6 100644
--- a/searx/translations/fa_IR/LC_MESSAGES/messages.po
+++ b/searx/translations/fa_IR/LC_MESSAGES/messages.po
@@ -109,7 +109,7 @@ msgstr "توابع آماری"
 
 #: searx/answerers/statistics/answerer.py:54
 msgid "Compute {functions} of the arguments"
-msgstr "پردازش {عملکرد های} نشانوند ها<br>"
+msgstr "پردازش {functions} نشانوند ها<br>"
 
 #: searx/engines/__init__.py:194
 msgid "Engine time (sec)"
diff --git a/searx/webapp.py b/searx/webapp.py
index 8c3531069..f3f5f21b8 100755
--- a/searx/webapp.py
+++ b/searx/webapp.py
@@ -144,7 +144,7 @@ if not searx_debug \
 
 babel = Babel(app)
 
-rtl_locales = ['ar', 'arc', 'bcc', 'bqi', 'ckb', 'dv', 'fa', 'glk', 'he',
+rtl_locales = ['ar', 'arc', 'bcc', 'bqi', 'ckb', 'dv', 'fa', 'fa_IR', 'glk', 'he',
                'ku', 'mzn', 'pnb', 'ps', 'sd', 'ug', 'ur', 'yi']
 
 # used when translating category names