|  | @@ -0,0 +1,88 @@
 | 
	
		
			
				|  |  | +# SPDX-License-Identifier: AGPL-3.0-or-later
 | 
	
		
			
				|  |  | +# lint: pylint
 | 
	
		
			
				|  |  | +"""A plugin to check if the ip address of the request is a TOR exit node if the
 | 
	
		
			
				|  |  | +user searches for ``tor-check``.  It fetches the tor exit node list from
 | 
	
		
			
				|  |  | +https://check.torproject.org/exit-addresses and parses all the IPs into a list,
 | 
	
		
			
				|  |  | +then checks if the user's IP address is in it.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Enable in ``settings.yml``:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +.. code:: yaml
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  enabled_plugins:
 | 
	
		
			
				|  |  | +    ..
 | 
	
		
			
				|  |  | +    - 'Tor check plugin'
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +"""
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import re
 | 
	
		
			
				|  |  | +from flask_babel import gettext
 | 
	
		
			
				|  |  | +from httpx import HTTPError
 | 
	
		
			
				|  |  | +from searx.network import get
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +default_on = False
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +name = gettext("Tor check plugin")
 | 
	
		
			
				|  |  | +'''Translated name of the plugin'''
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +description = gettext(
 | 
	
		
			
				|  |  | +    "This plugin checks if the address of the request is a TOR exit node, and"
 | 
	
		
			
				|  |  | +    " informs the user if it is, like check.torproject.org but from searxng."
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +'''Translated description of the plugin.'''
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +preference_section = 'query'
 | 
	
		
			
				|  |  | +'''The preference section where the plugin is shown.'''
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +query_keywords = ['tor-check']
 | 
	
		
			
				|  |  | +'''Query keywords shown in the preferences.'''
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +query_examples = ''
 | 
	
		
			
				|  |  | +'''Query examples shown in the preferences.'''
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +# Regex for exit node addresses in the list.
 | 
	
		
			
				|  |  | +reg = re.compile(r"(?<=ExitAddress )\S+")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +def post_search(request, search):
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if search.search_query.pageno > 1:
 | 
	
		
			
				|  |  | +        return True
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if search.search_query.query.lower() == "tor-check":
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # Request the list of tor exit nodes.
 | 
	
		
			
				|  |  | +        try:
 | 
	
		
			
				|  |  | +            resp = get("https://check.torproject.org/exit-addresses")
 | 
	
		
			
				|  |  | +            node_list = re.findall(reg, resp.text)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        except HTTPError:
 | 
	
		
			
				|  |  | +            # No answer, return error
 | 
	
		
			
				|  |  | +            search.result_container.answers["tor"] = {
 | 
	
		
			
				|  |  | +                "answer": gettext(
 | 
	
		
			
				|  |  | +                    "The TOR exit node list (https://check.torproject.org/exit-addresses) is unreachable."
 | 
	
		
			
				|  |  | +                )
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            return True
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        x_forwarded_for = request.headers.getlist("X-Forwarded-For")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if x_forwarded_for:
 | 
	
		
			
				|  |  | +            ip_address = x_forwarded_for[0]
 | 
	
		
			
				|  |  | +        else:
 | 
	
		
			
				|  |  | +            ip_address = request.remote_addr
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if ip_address in node_list:
 | 
	
		
			
				|  |  | +            search.result_container.answers["tor"] = {
 | 
	
		
			
				|  |  | +                "answer": gettext(
 | 
	
		
			
				|  |  | +                    "You are using TOR. Your IP address seems to be: {ip_address}.".format(ip_address=ip_address)
 | 
	
		
			
				|  |  | +                )
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        else:
 | 
	
		
			
				|  |  | +            search.result_container.answers["tor"] = {
 | 
	
		
			
				|  |  | +                "answer": gettext(
 | 
	
		
			
				|  |  | +                    "You are not using TOR. Your IP address seems to be: {ip_address}.".format(ip_address=ip_address)
 | 
	
		
			
				|  |  | +                )
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return True
 |