From 2ae4ac63833535df25947ff4173c51b5f6b293b6 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Sun, 11 Nov 2018 18:35:45 +0300 Subject: [PATCH] new implementation skeleton of data uploading --- app/connections.py | 127 +++++++++++++++++------------------ app/ui/download_dialog.glade | 14 ++-- app/ui/download_dialog.py | 9 ++- 3 files changed, 78 insertions(+), 72 deletions(-) diff --git a/app/connections.py b/app/connections.py index 80112bed..8837fa5f 100644 --- a/app/connections.py +++ b/app/connections.py @@ -6,15 +6,16 @@ from ftplib import FTP, error_perm from telnetlib import Telnet from urllib.error import HTTPError, URLError from urllib.parse import urlencode -from urllib.request import Request, urlopen, HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener, \ - install_opener +from urllib.request import urlopen, HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener, install_opener from xml.dom.minidom import parse from app.commons import log from app.properties import Profile -__DATA_FILES_LIST = ("tv", "radio", "lamedb", "lamedb5", "blacklist", "whitelist", # enigma 2 - "services.xml", "myservices.xml", "bouquets.xml", "ubouquets.xml") # neutrino +_BQ_FILES_LIST = ("tv", "radio", # enigma 2 + "myservices.xml", "bouquets.xml", "ubouquets.xml") # neutrino + +_DATA_FILES_LIST = ("lamedb", "lamedb5", "services.xml", "blacklist", "whitelist",) _SAT_XML_FILE = "satellites.xml" _WEBTV_XML_FILE = "webtv.xml" @@ -43,10 +44,10 @@ def download_data(*, properties, download_type=DownloadType.ALL, callback=None): if download_type is DownloadType.ALL or download_type is DownloadType.BOUQUETS: ftp.cwd(properties["services_path"]) ftp.dir(files.append) - + file_list = _BQ_FILES_LIST + _DATA_FILES_LIST if download_type is DownloadType.ALL else _BQ_FILES_LIST for file in files: name = str(file).strip() - if name.endswith(__DATA_FILES_LIST): + if name.endswith(file_list): name = name.split()[-1] download_file(ftp, name, save_path, callback) # satellites.xml and webtv section @@ -67,26 +68,18 @@ def download_data(*, properties, download_type=DownloadType.ALL, callback=None): def upload_data(*, properties, download_type=DownloadType.ALL, remove_unused=False, profile=Profile.ENIGMA_2, - callback=None, done_callback=None): + callback=None, done_callback=None, use_http=False): data_path = properties["data_dir_path"] host = properties["host"] # telnet tn = telnet(host=host, user=properties.get("telnet_user", "root"), password=properties.get("telnet_password", ""), timeout=properties.get("telnet_timeout", 5)) next(tn) - web_reachable = False - try: - # Checking if OpenWebif is reachable - urlopen(Request("http://{}/#".format(host)), timeout=1) - except HTTPError as er: - web_reachable = er.code == 401 - except Exception: - pass # NOP - else: - web_reachable = True - if profile is Profile.ENIGMA_2 and download_type is DownloadType.BOUQUETS and web_reachable: - tn.send('wget -qO - "http://localhost/web/message?text=User+bouquets+will+be+updated&type=2&timeout=10"') + if profile is Profile.ENIGMA_2 and download_type is DownloadType.BOUQUETS and use_http: + params = urlencode({"text": "User bouquets will be updated!", "type": 2, "timeout": 5}) + url = "http://{}:{}/web/message?{}".format(host, properties.get("http_port", "80"), params) + tn.send('wget -qO - "{}"'.format(url)) else: # terminate enigma or neutrino tn.send("init 4") @@ -95,22 +88,22 @@ def upload_data(*, properties, download_type=DownloadType.ALL, remove_unused=Fal ftp.encoding = "utf-8" callback("FTP OK.\n") - if download_type is DownloadType.ALL or download_type is DownloadType.SATELLITES: + if download_type is DownloadType.SATELLITES: ftp.cwd(properties["satellites_xml_path"]) - send = send_file(_SAT_XML_FILE, data_path, ftp) + send = send_file(_SAT_XML_FILE, data_path, ftp, callback) if download_type is DownloadType.SATELLITES: tn.send("init 3" if profile is Profile.ENIGMA_2 else "init 6") - if callback is not None: - callback() + if done_callback is not None: + done_callback() return send - if profile is Profile.NEUTRINO_MP and download_type in (DownloadType.ALL, DownloadType.WEBTV): + if profile is Profile.NEUTRINO_MP and download_type is DownloadType.WEBTV: ftp.cwd(properties["satellites_xml_path"]) - send = send_file(_WEBTV_XML_FILE, data_path, ftp) + send = send_file(_WEBTV_XML_FILE, data_path, ftp, callback) if download_type is DownloadType.WEBTV: tn.send("init 6") - if callback is not None: - callback() + if done_callback is not None: + done_callback() return send if download_type is DownloadType.ALL or download_type is DownloadType.BOUQUETS: @@ -120,42 +113,21 @@ def upload_data(*, properties, download_type=DownloadType.ALL, remove_unused=Fal ftp.dir(files.append) for file in files: name = str(file).strip() - if name.endswith(__DATA_FILES_LIST): + if name.endswith(("tv", "radio", "bouquets.xml", "ubouquets.xml")): name = name.split()[-1] - ftp.delete(name) - callback("Deleting file: {}\n".format(name)) + callback("Deleting file: {}. Status: {}\n".format(name, ftp.delete(name))) + file_list = _BQ_FILES_LIST + _DATA_FILES_LIST if download_type is DownloadType.ALL else _BQ_FILES_LIST for file_name in os.listdir(data_path): if file_name == _SAT_XML_FILE or file_name == _WEBTV_XML_FILE: continue - if file_name.endswith(__DATA_FILES_LIST): - callback("Uploading file: {}\n".format(file_name)) - send_file(file_name, data_path, ftp) + if file_name.endswith(file_list): + send_file(file_name, data_path, ftp, callback) if download_type is DownloadType.PICONS: - picons_dir_path = properties.get("picons_dir_path") - picons_path = properties.get("picons_path") - try: - ftp.cwd(picons_path) - except error_perm as e: - if str(e).startswith("550"): - ftp.mkd(picons_path) # if not exist - ftp.cwd(picons_path) + upload_picons(ftp, properties.get("picons_dir_path"), properties.get("picons_path")) - files = [] - ftp.dir(files.append) - picons_suf = (".jpg", ".png") - - for file in files: - name = str(file).strip() - if name.endswith(picons_suf): - name = name.split()[-1] - ftp.delete(name) - for file_name in os.listdir(picons_dir_path): - if file_name.endswith(picons_suf): - send_file(file_name, picons_dir_path, ftp) - - if profile is Profile.ENIGMA_2 and download_type is DownloadType.BOUQUETS and web_reachable: + if profile is Profile.ENIGMA_2 and download_type is DownloadType.BOUQUETS and use_http: tn.send("wget -qO - http://127.0.0.1/web/servicelistreload?mode=2") else: # resume enigma or restart neutrino @@ -165,16 +137,38 @@ def upload_data(*, properties, download_type=DownloadType.ALL, remove_unused=Fal done_callback() +def upload_picons(ftp, src, dest): + try: + ftp.cwd(dest) + except error_perm as e: + if str(e).startswith("550"): + ftp.mkd(dest) # if not exist + ftp.cwd(dest) + files = [] + ftp.dir(files.append) + picons_suf = (".jpg", ".png") + for file in files: + name = str(file).strip() + if name.endswith(picons_suf): + name = name.split()[-1] + ftp.delete(name) + for file_name in os.listdir(src): + if file_name.endswith(picons_suf): + send_file(file_name, src, ftp) + + def download_file(ftp, name, save_path, callback): with open(save_path + name, "wb") as f: - ftp.retrbinary("RETR " + name, f.write) - callback("Downloading file: {}\n".format(name)) + resp = ftp.retrbinary("RETR " + name, f.write) + callback("Downloading file: {}. Status: {}\n".format(name, str(resp))) -def send_file(file_name, path, ftp): +def send_file(file_name, path, ftp, callback): """ Opens the file in binary mode and transfers into receiver """ with open(path + file_name, "rb") as f: - return ftp.storbinary("STOR " + file_name, f) + send = ftp.storbinary("STOR " + file_name, f) + callback("Uploading file: {}. Status: {}\n".format(file_name, str(send))) + return send def telnet(host, port=23, user="", password="", timeout=5): @@ -219,11 +213,7 @@ def test_http(host, port, user, password, timeout=5): params = urlencode({"text": "Connection test", "type": 2, "timeout": timeout}) url = "http://{}:{}/web/message?{}".format(host, port, params) # authentication - pass_mgr = HTTPPasswordMgrWithDefaultRealm() - pass_mgr.add_password(None, url, user, password) - auth_handler = HTTPBasicAuthHandler(pass_mgr) - opener = build_opener(auth_handler) - install_opener(opener) + init_auth(password, url, user) with urlopen(url, timeout=5) as f: dom = parse(f) @@ -237,6 +227,15 @@ def test_http(host, port, user, password, timeout=5): raise TestException(e) +def init_auth(password, url, user): + """ Init authentication """ + pass_mgr = HTTPPasswordMgrWithDefaultRealm() + pass_mgr.add_password(None, url, user, password) + auth_handler = HTTPBasicAuthHandler(pass_mgr) + opener = build_opener(auth_handler) + install_opener(opener) + + def test_telnet(host, port, user, password, timeout=5): try: gen = telnet_test(host, port, user, password, timeout) diff --git a/app/ui/download_dialog.glade b/app/ui/download_dialog.glade index 60c4d505..7bafd304 100644 --- a/app/ui/download_dialog.glade +++ b/app/ui/download_dialog.glade @@ -50,7 +50,7 @@ Author: Dmitriy Yefremov 5 True - + True False 2 @@ -256,14 +256,14 @@ Author: Dmitriy Yefremov 5 vertical - + True False 2 2 True - + True False Receiver IP: @@ -290,7 +290,7 @@ Author: Dmitriy Yefremov - + True False Current data path: @@ -350,7 +350,7 @@ Author: Dmitriy Yefremov False 2 - + True False Use HTTP @@ -362,7 +362,7 @@ Author: Dmitriy Yefremov - + True True Use http to reload data in the receiver. @@ -402,7 +402,7 @@ Author: Dmitriy Yefremov - + True False 5 diff --git a/app/ui/download_dialog.py b/app/ui/download_dialog.py index 32b649fc..40e0830b 100644 --- a/app/ui/download_dialog.py +++ b/app/ui/download_dialog.py @@ -46,13 +46,16 @@ class DownloadDialog: self._password_entry = builder.get_object("password_entry") self._host_entry = builder.get_object("host_entry") self._port_entry = builder.get_object("port_entry") + self._timeout_entry = builder.get_object("timeout_entry") self._settings_buttons_box = builder.get_object("settings_buttons_box") + self._use_http_switch = builder.get_object("use_http_switch") self.init_properties() if profile is Profile.NEUTRINO_MP: self._webtv_radio_button.set_visible(True) builder.get_object("http_radio_button").set_visible(False) builder.get_object("use_http_box").set_visible(False) + self._use_http_switch.set_active(False) def show(self): self._dialog_window.show() @@ -90,14 +93,17 @@ class DownloadDialog: self._login_entry.set_text(self._profile_properties.get("telnet_user", "")) self._password_entry.set_text(self._profile_properties.get("telnet_password", "")) self._port_entry.set_text(self._profile_properties.get("telnet_port", "")) + self._timeout_entry.set_text(str(self._profile_properties.get("telnet_timeout", 0))) elif label == "HTTP": self._login_entry.set_text(self._profile_properties.get("http_user", "root")) self._password_entry.set_text(self._profile_properties.get("http_password", "")) self._port_entry.set_text(self._profile_properties.get("http_port", "")) + self._timeout_entry.set_text(str(self._profile_properties.get("http_timeout", 0))) elif label == "FTP": self._login_entry.set_text(self._profile_properties.get("user", "")) self._password_entry.set_text(self._profile_properties.get("password", "")) self._port_entry.set_text(self._profile_properties.get("port", "")) + self._timeout_entry.set_text("") self._current_property = label def on_preferences(self, item): @@ -129,7 +135,8 @@ class DownloadDialog: remove_unused=self._remove_unused_check_button.get_active(), profile=self._profile, callback=self.append_output, - done_callback=lambda: self.show_info_message(get_message("Done!"), Gtk.MessageType.INFO)) + done_callback=lambda: self.show_info_message(get_message("Done!"), Gtk.MessageType.INFO), + use_http=self._use_http_switch.get_active()) except Exception as e: message = str(getattr(e, "message", str(e))) self.show_info_message(message, Gtk.MessageType.ERROR)