Enforce SOCKS proxy setting in search engine plugins

Previously it require each plugin to import helpers.py to setup SOCKS proxy.
Now it is enforced by default for all plugins.
Also added a function for plugins to ignore/restore the socket to
default state.

PR #22554.
This commit is contained in:
Chocobo1 2025-04-19 07:11:50 +08:00 committed by GitHub
parent 2785636d3f
commit 2aee875642
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 33 deletions

View file

@ -1,4 +1,4 @@
#VERSION: 1.52 # VERSION: 1.53
# Author: # Author:
# Christophe DUMEZ (chris@qbittorrent.org) # Christophe DUMEZ (chris@qbittorrent.org)
@ -61,32 +61,32 @@ def _getBrowserUserAgent() -> str:
_headers: dict[str, Any] = {'User-Agent': _getBrowserUserAgent()} _headers: dict[str, Any] = {'User-Agent': _getBrowserUserAgent()}
_original_socket = socket.socket
def injectSOCKSProxySocket() -> None: def enable_socks_proxy(enable: bool) -> None:
socksURL = os.environ.get("qbt_socks_proxy") if enable:
if socksURL is not None: socksURL = os.environ.get("qbt_socks_proxy")
parts = urllib.parse.urlsplit(socksURL) if socksURL is not None:
resolveHostname = (parts.scheme == "socks4a") or (parts.scheme == "socks5h") parts = urllib.parse.urlsplit(socksURL)
if (parts.scheme == "socks4") or (parts.scheme == "socks4a"): resolveHostname = (parts.scheme == "socks4a") or (parts.scheme == "socks5h")
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4, parts.hostname, parts.port, resolveHostname) if (parts.scheme == "socks4") or (parts.scheme == "socks4a"):
socket.socket = socks.socksocket # type: ignore[misc] socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4, parts.hostname, parts.port, resolveHostname)
elif (parts.scheme == "socks5") or (parts.scheme == "socks5h"): socket.socket = socks.socksocket # type: ignore[misc]
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, parts.hostname, parts.port, resolveHostname, parts.username, parts.password) elif (parts.scheme == "socks5") or (parts.scheme == "socks5h"):
socket.socket = socks.socksocket # type: ignore[misc] socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, parts.hostname, parts.port, resolveHostname, parts.username, parts.password)
socket.socket = socks.socksocket # type: ignore[misc]
else:
# the following code provide backward compatibility for older qbt versions
# TODO: scheduled be removed with qbt >= 5.3
legacySocksURL = os.environ.get("sock_proxy")
if legacySocksURL is not None:
legacySocksURL = f"socks5h://{legacySocksURL.strip()}"
parts = urllib.parse.urlsplit(legacySocksURL)
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, parts.hostname, parts.port, True, parts.username, parts.password)
socket.socket = socks.socksocket # type: ignore[misc]
else: else:
# the following code provide backward compatibility for older qbt versions socket.socket = _original_socket # type: ignore[misc]
# TODO: scheduled be removed with qbt >= 5.3
legacySocksURL = os.environ.get("sock_proxy")
if legacySocksURL is not None:
legacySocksURL = f"socks5h://{legacySocksURL.strip()}"
parts = urllib.parse.urlsplit(legacySocksURL)
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, parts.hostname, parts.port, True, parts.username, parts.password)
socket.socket = socks.socksocket # type: ignore[misc]
# monkey patching, run it now
injectSOCKSProxySocket()
# This is only provided for backward compatibility, new code should not use it # This is only provided for backward compatibility, new code should not use it

View file

@ -1,4 +1,4 @@
#VERSION: 1.48 # VERSION: 1.49
# Author: # Author:
# Fabien Devaux <fab AT gnux DOT info> # Fabien Devaux <fab AT gnux DOT info>
@ -46,6 +46,16 @@ from multiprocessing import Pool, cpu_count
from os import path from os import path
from typing import Optional from typing import Optional
# qbt tend to run this script in 'isolate mode' so append the current path manually
current_path = str(pathlib.Path(__file__).parent.resolve())
if current_path not in sys.path:
sys.path.append(current_path)
import helpers
# enable SOCKS proxy for all plugins by default
helpers.enable_socks_proxy(True)
THREADED: bool = True THREADED: bool = True
try: try:
MAX_THREADS: int = cpu_count() MAX_THREADS: int = cpu_count()
@ -182,11 +192,6 @@ def run_search(search_params: tuple[type[Engine], str, Category]) -> bool:
if __name__ == "__main__": if __name__ == "__main__":
def main() -> int: def main() -> int:
# qbt tend to run this script in 'isolate mode' so append the current path manually
current_path = str(pathlib.Path(__file__).parent.resolve())
if current_path not in sys.path:
sys.path.append(current_path)
# https://docs.python.org/3/library/sys.html#sys.exit # https://docs.python.org/3/library/sys.html#sys.exit
class ExitCode(Enum): class ExitCode(Enum):
OK = 0 OK = 0

View file

@ -1,4 +1,4 @@
#VERSION: 1.24 # VERSION: 1.25
# Author: # Author:
# Christophe DUMEZ (chris@qbittorrent.org) # Christophe DUMEZ (chris@qbittorrent.org)
@ -38,7 +38,10 @@ current_path = str(pathlib.Path(__file__).parent.resolve())
if current_path not in sys.path: if current_path not in sys.path:
sys.path.append(current_path) sys.path.append(current_path)
from helpers import download_file import helpers
# enable SOCKS proxy for all plugins by default
helpers.enable_socks_proxy(True)
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv) < 3: if len(sys.argv) < 3:
@ -58,6 +61,6 @@ if __name__ == '__main__':
if hasattr(engine, 'download_torrent'): if hasattr(engine, 'download_torrent'):
engine.download_torrent(download_param) engine.download_torrent(download_param)
else: else:
print(download_file(download_param)) print(helpers.download_file(download_param))
sys.exit(0) sys.exit(0)