From 4b5508169338396b448ac8acaa3434ff68f6440c Mon Sep 17 00:00:00 2001 From: BarsTiger Date: Thu, 27 Jan 2022 13:46:26 +0200 Subject: [PATCH] GUI development --- horsygui.py | 8 ++- modules/gui.py | 3 + modules/gui_manager.py | 136 +++++++++++++++++++++++++++++++++++++++++ modules/manager.py | 2 +- modules/source.py | 8 ++- modules/uploader.py | 27 ++++---- 6 files changed, 162 insertions(+), 22 deletions(-) create mode 100644 modules/gui_manager.py diff --git a/horsygui.py b/horsygui.py index c323b0d..86ab9ba 100644 --- a/horsygui.py +++ b/horsygui.py @@ -74,13 +74,13 @@ def search_gui(): ui.search_table.setItem(i // 4, i % 4, QtWidgets.QTableWidgetItem(str(found[i]))) def install_app(): - from modules.manager import install + from modules.gui_manager import install try: app_name = ui.search_table.currentItem().text() if app_name == "": return else: - install(app_name, True) + install(app_name, UiDownloadWindow, download_ui) except: return @@ -91,7 +91,9 @@ def get_source_gui(): if app_name == "": return else: - get_source(app_name) + source = get_source(app_name) + if source is not None: + gui.popup("Error", source) except: return diff --git a/modules/gui.py b/modules/gui.py index 356d4b5..ffec9ea 100644 --- a/modules/gui.py +++ b/modules/gui.py @@ -829,6 +829,9 @@ class Ui_DownloadWindow(object): self.logs_box.setPlaceholderText(_translate("MainWindow", "Logs")) +def popup(title, text): + QtWidgets.QMessageBox.information(QtWidgets.QMainWindow(), title, text) + if __name__ == "__main__": import sys diff --git a/modules/gui_manager.py b/modules/gui_manager.py new file mode 100644 index 0000000..81f556b --- /dev/null +++ b/modules/gui_manager.py @@ -0,0 +1,136 @@ +import json +import threading +import requests +import modules.vars as horsy_vars +import os +import zipfile +from modules.virustotal import get_key, scan_file, get_report + + +def install(package, UiDownloadWindow=None, ui_download=None): + r = requests.get(f"{horsy_vars.protocol}{horsy_vars.server_url}/packages/json/{package}").text + if r == "": + print(f"[red]Package {package} not found[/]") + return + try: + r = json.loads(r) + except: + print("[red]Error with unsupported message[/]") + return + try: + if r["message"] == "Internal server error": + print("[red]Internal server error[/]") + return + except: + pass + + try: + print(f"[green]App {r['name']} found, information loaded[/]") + + if not os.path.exists('{1}apps/{0}'.format(r['name'], horsy_vars.horsypath)): + os.makedirs('{1}apps/{0}'.format(r['name'], horsy_vars.horsypath)) + + # if not is_gui: + print(f"Downloading {r['url'].split('/')[-1]}") + + chunk_size = 1024 + file_r = requests.get(r['url'], stream=True) + with open('{2}apps/{0}/{1}'.format(r['name'], r['url'].split('/')[-1], horsy_vars.horsypath), "wb") as f: + pbar = tqdm(unit="B", unit_scale=True, total=int(file_r.headers['Content-Length'])) + for chunk in file_r.iter_content(chunk_size=chunk_size): + if chunk: + pbar.update(len(chunk)) + f.write(chunk) + pbar.close() + + print(f"Starting virustotal scan") + if not get_key(): + print(f"[red]Virustotal api key not found[/]") + print(f"You can add it by entering [bold]horsy --vt \[your key][/] in terminal") + else: + print(f"[green]Virustotal api key found[/]") + print(f"[italic white]If you want to disable scan, type [/][bold]horsy --vt disable[/]" + f"[italic white] in terminal[/]") + scan_file('{2}apps/{0}/{1}'.format(r['name'], r['url'].split('/')[-1], horsy_vars.horsypath)) + print(f"[green]Virustotal scan finished[/]") + analysis = get_report('{2}apps/{0}/{1}'.format(r['name'], r['url'].split('/')[-1], + horsy_vars.horsypath)) + print(f"[green]You can see report by opening: [white]{analysis['link']}[/]") + print(f"{analysis['detect']['malicious']} antivirus flagged this file as malicious") + + print(f"[green][OK] Done[/]") + + def unzip(file, where): + with zipfile.ZipFile(file, 'r') as zip_ref: + zip_ref.extractall(where) + print(f"[green]Extracted[/]") + + if r['url'].split('.')[-1] == 'zip': + print(f"Extracting {r['url'].split('/')[-1]}") + unzip('{2}apps/{0}/{1}'.format(r['name'], r['url'].split('/')[-1], horsy_vars.horsypath), + '{1}apps/{0}'.format(r['name'], horsy_vars.horsypath)) + + if r['download']: + print(f"Found dependency") + # if not is_gui: + print(f"Downloading {r['download'].split('/')[-1]}") + + chunk_size = 1024 + file_r = requests.get(r['download'], stream=True) + with open('{2}apps/{0}/{1}'.format(r['name'], r['download'].split('/')[-1], horsy_vars.horsypath), + "wb") as f: + pbar = tqdm(unit="B", unit_scale=True, total=int(file_r.headers['Content-Length'])) + for chunk in file_r.iter_content(chunk_size=chunk_size): + if chunk: + pbar.update(len(chunk)) + f.write(chunk) + pbar.close() + + print(f"Starting virustotal scan") + if not get_key(): + print(f"[red]Virustotal api key not found[/]") + print(f"You can add it by entering [italic white]horsy --vt \[your key][/] in terminal") + else: + print(f"[green]Virustotal api key found[/]") + scan_file('{2}apps/{0}/{1}'.format(r['name'], r['download'].split('/')[-1], horsy_vars.horsypath)) + print(f"[green]Virustotal scan finished[/]") + analysis = get_report('{2}apps/{0}/{1}'.format(r['name'], r['download'].split('/')[-1], + horsy_vars.horsypath)) + print(f"[green]You can see report by opening: [white]{analysis['link']}[/]") + print(f"{analysis['detect']['malicious']} antivirus flagged this file as malicious") + if analysis['detect']['malicious'] > 0: + print(f"[red]Dependency can be malicious. It may run now, if this added to installation " + f"config[/]") + input("Press enter if you want continue, or ctrl+c to exit") + + if r['install']: + print(f"Found install option") + threading.Thread(target=os.system, args=('{2}apps/{0}/{1}'.format(r['name'], r['install'], + horsy_vars.horsypath),)).start() + + print(f"Generating launch script") + + with open('{1}apps/{0}.bat'.format(r['name'], horsy_vars.horsypath), 'w') as f: + f.write(f"@ECHO off\n") + f.write(f"{horsy_vars.horsypath}apps/{r['name']}/{r['run']} %*\n") + + print(f"[green][OK] All done![/]") + print(f"[green]You can run your app by entering [italic white]{r['name']}[/] in terminal[/]") + + except: + print("[red]Unexpected error[/]") + # raise + return + + +def uninstall(package, is_gui=False): + if os.path.exists('{1}apps/{0}'.format(package, horsy_vars.horsypath)): + os.system('rmdir /s /q "{1}apps/{0}"'.format(package, horsy_vars.horsypath)) + print(f"[green][OK] Files deleted[/]") + else: + print(f"[red]App {package} is not installed or doesn't have files[/]") + if os.path.isfile('{1}apps/{0}.bat'.format(package, horsy_vars.horsypath)): + os.remove("{1}apps/{0}.bat".format(package, horsy_vars.horsypath)) + print(f"[green][OK] Launch script deleted[/]") + else: + print(f"[red]App {package} is not installed or doesn't have launch script[/]") diff --git a/modules/manager.py b/modules/manager.py index e0340b3..94c8900 100644 --- a/modules/manager.py +++ b/modules/manager.py @@ -9,7 +9,7 @@ import zipfile from modules.virustotal import get_key, scan_file, get_report -def install(package, is_gui=False): +def install(package, is_gui=False, UiDownloadWindow=None, ui_download=None): r = requests.get(f"{horsy_vars.protocol}{horsy_vars.server_url}/packages/json/{package}").text if r == "": print(f"[red]Package {package} not found[/]") diff --git a/modules/source.py b/modules/source.py index 1ffda24..991061c 100644 --- a/modules/source.py +++ b/modules/source.py @@ -11,18 +11,20 @@ def get_source(package): r = json.loads(r) except: print("[red]Error with unsupported message[/]") - return + return "Error with unsupported message" try: if r["message"] == "not found": print("[red]Package not found[/]") - return + return "Package not found" if r["message"] == "Internal server error": print("[red]Internal server error[/]") - return + return "Internal server error" except: pass try: webbrowser.open(r["sourceUrl"]) + return None except: print("[red]No source code available for this app[/]") + return "No source code available for this app" diff --git a/modules/uploader.py b/modules/uploader.py index f1e2931..270c4d6 100644 --- a/modules/uploader.py +++ b/modules/uploader.py @@ -97,18 +97,15 @@ def upload(is_gui=False, ui=None, login_ui=None, Ui_LoginWindow=None): project_name = ui.packagename_box.text() if not matches(project_name) or len(project_name) > 64 or len(project_name) < 3: - print('[red]Invalid project name[/red]') - return + return 'Invalid project name' description = ui.package_desc_box.toPlainText() if len(description) > 256: - print('[red]Description is too long[/red]') - return + return 'Description is too long' url = ui.url_of_exe_box.text() if not urlmatch(url): - print('[red]Invalid file url, also it should end on .exe or .zip[/red]') - return + return 'Invalid file url, also it should end on .exe or .zip' source_url = ui.source_url_box.text() source_url = None if source_url == '' else source_url @@ -117,16 +114,14 @@ def upload(is_gui=False, ui=None, login_ui=None, Ui_LoginWindow=None): if download == '': download = None elif not urlmatch(download): - print('[red]Invalid download url[/red]') - return + return 'Invalid download url' install = ui.dependency_run_box.text() install = None if install == '' else install run = ui.main_exe_box.text() if run == '': - print('[red]Please, specify runtime[/red]') - return + return 'Please, specify runtime' request = { 'auth': auth, @@ -154,22 +149,24 @@ def upload(is_gui=False, ui=None, login_ui=None, Ui_LoginWindow=None): r = None elif r['message'] == 'Internal server error': - print('[red]Internal server error, request is broken[/red]') - break + print('[red]Internal server error[/red]') + return 'Internal server error' elif r['message'] == 'Success': print('[green]Success, your project is created. You can install it by running[/] ' '[i]horsy install {0}[/]'.format(request['name'])) - break + return 'Success, your project is created. You can install it by running horsy install {0}'.format( + request['name']) elif 'already exists' in r['message']: - print(f"[red]{r['message']}[/red]") + print(r['message']) + return {r['message']} else: print('[red]Unknown error, please try again[/red]') print('Server response:') print(r) - break + return 'Unknown error, please try again, \n Server response: \n' + str(r) except: with open(f'error_{time.time()}.txt', 'w') as f: f.write(str(r))