From bcbe2b3f4614b7272e13f39c6dd9b51967322f33 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Fri, 3 Jan 2020 23:26:55 +0300 Subject: [PATCH] added https support to the settings --- app/connections.py | 34 ++++++++++------ app/settings.py | 13 +++++- app/ui/main_app_window.py | 2 +- app/ui/settings_dialog.glade | 79 +++++++++++++++++++++++++----------- app/ui/settings_dialog.py | 20 ++++++++- 5 files changed, 108 insertions(+), 40 deletions(-) diff --git a/app/connections.py b/app/connections.py index 2c0bf16b..f9fc041b 100644 --- a/app/connections.py +++ b/app/connections.py @@ -11,7 +11,7 @@ from urllib.error import HTTPError, URLError from urllib.parse import urlencode from urllib.request import urlopen, HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener, install_opener -from app.commons import log, run_idle +from app.commons import log from app.settings import SettingsType _BQ_FILES_LIST = ("tv", "radio", # enigma 2 @@ -97,7 +97,7 @@ def upload_data(*, settings, download_type=DownloadType.ALL, remove_unused=False s_type = settings.setting_type data_path = settings.data_local_path host = settings.host - base_url = "http://{}:{}/api/".format(host, settings.http_port) + base_url = "http{}://{}:{}/api/".format("s" if settings.http_use_ssl else "", host, settings.http_port) tn, ht = None, None # telnet, http try: @@ -276,7 +276,6 @@ def telnet(host, port=23, user="", password="", timeout=5): # ***************** HTTP API *******************# class HttpAPI: - __MAX_WORKERS = 4 def __init__(self, settings): @@ -299,8 +298,10 @@ class HttpAPI: future.add_done_callback(lambda f: callback(f.result())) def init(self): - self._base_url = "http://{}:{}/api/".format(self._settings.host, self._settings.http_port) - init_auth(self._settings.http_user, self._settings.http_password, self._base_url) + use_ssl = self._settings.http_use_ssl + url = "http{}://{}:{}".format("s" if use_ssl else "", self._settings.host, self._settings.http_port) + self._base_url = "{}/api/".format(url) + init_auth(self._settings.http_user, self._settings.http_password, url, use_ssl) def close(self): self._executor.shutdown(False) @@ -313,7 +314,7 @@ def get_json(req_type, url): return f.read().decode("utf-8") else: return json.loads(f.read().decode("utf-8")) - except (URLError, HTTPError): + except (URLError, HTTPError, RemoteDisconnected): pass @@ -327,26 +328,35 @@ def test_ftp(host, port, user, password, timeout=5): raise TestException(e) -def test_http(host, port, user, password, timeout=5, skip_message=False): +def test_http(host, port, user, password, timeout=5, use_ssl=False, skip_message=False): try: params = urlencode({"text": "Connection test", "type": 2, "timeout": timeout}) params = "statusinfo" if skip_message else "message?{}".format(params) - url = "http://{}:{}/api/{}".format(host, port, params) + url = "http{}://{}:{}/api/".format("s" if use_ssl else "", host, port) # authentication - init_auth(user, password, url) + init_auth(user, password, url, use_ssl) - with urlopen(url, timeout=5) as f: + with urlopen("{}{}".format(url, params), timeout=5) as f: return json.loads(f.read().decode("utf-8")).get("message", "") except (RemoteDisconnected, URLError, HTTPError) as e: raise TestException(e) -def init_auth(user, password, url): +def init_auth(user, password, url, use_ssl=False): """ Init authentication """ pass_mgr = HTTPPasswordMgrWithDefaultRealm() pass_mgr.add_password(None, url, user, password) auth_handler = HTTPBasicAuthHandler(pass_mgr) - opener = build_opener(auth_handler) + + if use_ssl: + import ssl + from urllib.request import HTTPSHandler + # https://stackoverflow.com/a/28052583 + context = ssl._create_unverified_context() + opener = build_opener(auth_handler, HTTPSHandler(context=context)) + else: + opener = build_opener(auth_handler) + install_opener(opener) diff --git a/app/settings.py b/app/settings.py index 08425d15..ccbadb1f 100644 --- a/app/settings.py +++ b/app/settings.py @@ -62,7 +62,8 @@ class SettingsType(IntEnum): if self is self.ENIGMA_2: return {"setting_type": self.value, "host": "127.0.0.1", "port": "21", "user": "root", "password": "root", "timeout": 5, - "http_user": "root", "http_password": "", "http_port": "80", "http_timeout": 5, + "http_user": "root", "http_password": "", "http_port": "80", + "http_timeout": 5, "http_use_ssl": False, "telnet_user": "root", "telnet_password": "", "telnet_port": "23", "telnet_timeout": 5, "services_path": "/etc/enigma2/", "user_bouquet_path": "/etc/enigma2/", "satellites_xml_path": "/etc/tuxbox/", "data_local_path": DATA_PATH + "enigma2/", @@ -72,7 +73,7 @@ class SettingsType(IntEnum): elif self is self.NEUTRINO_MP: return {"setting_type": self, "host": "127.0.0.1", "port": "21", "user": "root", "password": "root", "timeout": 5, - "http_user": "", "http_password": "", "http_port": "80", "http_timeout": 2, + "http_user": "", "http_password": "", "http_port": "80", "http_timeout": 2, "http_use_ssl": False, "telnet_user": "root", "telnet_password": "", "telnet_port": "23", "telnet_timeout": 1, "services_path": "/var/tuxbox/config/zapit/", "user_bouquet_path": "/var/tuxbox/config/zapit/", "satellites_xml_path": "/var/tuxbox/config/", "data_local_path": DATA_PATH + "neutrino/", @@ -261,6 +262,14 @@ class Settings: def http_timeout(self, value): self._cp_settings["http_timeout"] = value + @property + def http_use_ssl(self): + return self._cp_settings.get("http_use_ssl", self.get_default("http_use_ssl")) + + @http_use_ssl.setter + def http_use_ssl(self, value): + self._cp_settings["http_use_ssl"] = value + @property def telnet_user(self): return self._cp_settings.get("telnet_user", self.get_default("telnet_user")) diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index c066a3ff..3406894a 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -835,7 +835,7 @@ class Application(Gtk.Application): if profile is SettingsType.ENIGMA_2: host, port, user, password = opts.host, opts.http_port, opts.http_user, opts.http_password try: - test_http(host, port, user, password, skip_message=True) + test_http(host, port, user, password, use_ssl=opts.http_use_ssl, skip_message=True) except TestException: use_http = False diff --git a/app/ui/settings_dialog.glade b/app/ui/settings_dialog.glade index 022a8b00..0388972b 100644 --- a/app/ui/settings_dialog.glade +++ b/app/ui/settings_dialog.glade @@ -162,7 +162,7 @@ Author: Dmitriy Yefremov True False - + 150 True False @@ -378,7 +378,6 @@ Author: Dmitriy Yefremov False 5 5 - 5 vertical 2 @@ -389,19 +388,6 @@ Author: Dmitriy Yefremov 2 2 True - - - True - False - center - 5 - Host: - - - 0 - 0 - - True @@ -414,6 +400,48 @@ Author: Dmitriy Yefremov 1 + + + 22 + True + False + 2 + + + True + False + end + 5 + Host: + + + False + True + 0 + + + + + SSL/TSL + False + False + end + True + + + + False + False + end + 1 + + + + + 0 + 0 + + False @@ -425,6 +453,7 @@ Author: Dmitriy Yefremov True False + 5 True @@ -507,12 +536,12 @@ Author: Dmitriy Yefremov True False + 5 + True False - 2 - 5 2 2 @@ -583,7 +612,15 @@ Author: Dmitriy Yefremov - + + True + False + Port: + + + 2 + 0 + @@ -595,8 +632,6 @@ Author: Dmitriy Yefremov True False - 2 - 5 2 2 @@ -687,8 +722,6 @@ Author: Dmitriy Yefremov True False - 2 - 5 2 2 @@ -808,7 +841,7 @@ Author: Dmitriy Yefremov False True - 1 + 2 diff --git a/app/ui/settings_dialog.py b/app/ui/settings_dialog.py index d502c60c..52bb5be1 100644 --- a/app/ui/settings_dialog.py +++ b/app/ui/settings_dialog.py @@ -42,7 +42,9 @@ class SettingsDialog: "on_profile_edited": self.on_profile_edited, "on_profile_selected": self.on_profile_selected, "on_profile_set_default": self.on_profile_set_default, - "on_lang_changed": self.on_lang_changed} + "on_lang_changed": self.on_lang_changed, + "on_current_settings_visible": self.on_current_settings_visible, + "on_http_use_ssl_toggled": self.on_http_use_ssl_toggled} builder = Gtk.Builder() builder.add_from_file(UI_RESOURCES_PATH + "settings_dialog.glade") @@ -59,6 +61,7 @@ class SettingsDialog: self._http_login_field = builder.get_object("http_login_field") self._http_password_field = builder.get_object("http_password_field") self._http_port_field = builder.get_object("http_port_field") + self._http_use_ssl_check_button = builder.get_object("http_use_ssl_check_button") self._telnet_login_field = builder.get_object("telnet_login_field") self._telnet_password_field = builder.get_object("telnet_password_field") self._telnet_port_field = builder.get_object("telnet_port_field") @@ -175,6 +178,7 @@ class SettingsDialog: self._http_login_field.set_text(self._settings.http_user) self._http_password_field.set_text(self._settings.http_password) self._http_port_field.set_text(self._settings.http_port) + self._http_use_ssl_check_button.set_active(self._settings.http_use_ssl) self._telnet_login_field.set_text(self._settings.telnet_user) self._telnet_password_field.set_text(self._settings.telnet_password) self._telnet_port_field.set_text(self._settings.telnet_port) @@ -216,6 +220,7 @@ class SettingsDialog: self._settings.http_user = self._http_login_field.get_text() self._settings.http_password = self._http_password_field.get_text() self._settings.http_port = self._http_port_field.get_text() + self._settings.http_use_ssl = self._http_use_ssl_check_button.get_active() self._settings.telnet_user = self._telnet_login_field.get_text() self._settings.telnet_password = self._telnet_password_field.get_text() self._settings.telnet_port = self._telnet_port_field.get_text() @@ -261,8 +266,9 @@ class SettingsDialog: def test_http(self): user, password = self._http_login_field.get_text(), self._http_password_field.get_text() host, port = self._host_field.get_text(), self._http_port_field.get_text() + use_ssl = self._http_use_ssl_check_button.get_active() try: - self.show_info_message(test_http(host, port, user, password), Gtk.MessageType.INFO) + self.show_info_message(test_http(host, port, user, password, use_ssl=use_ssl), Gtk.MessageType.INFO) except TestException as e: self.show_info_message(str(e), Gtk.MessageType.ERROR) finally: @@ -408,6 +414,16 @@ class SettingsDialog: if box.get_active_id() != self._settings.language: self.show_info_message("Save and restart the program to apply the settings.", Gtk.MessageType.WARNING) + def on_current_settings_visible(self, stack: Gtk.Stack, param): + self._http_use_ssl_check_button.set_visible(Property(stack.get_visible_child_name()) is Property.HTTP) + + def on_http_use_ssl_toggled(self, button): + active = button.get_active() + self._settings.http_use_ssl = active + port = "443" if active else "80" + self._http_port_field.set_text(port) + self._settings.http_port = port + @run_idle def set_fav_click_mode(self, mode): mode = FavClickMode(mode)