diff --git a/com.angoosh.RDPConnect/main.py b/com.angoosh.RDPConnect/main.py index 5db6fbc..01c9deb 100755 --- a/com.angoosh.RDPConnect/main.py +++ b/com.angoosh.RDPConnect/main.py @@ -328,11 +328,18 @@ class MyApp(Adw.Application): if settings["save_conn"]: password = conn_info["passwd"] useratip = conn_info["user"] + "@" + conn_info["ip"] - with open(HOMEDIR+"/.config/rdpconnect/history.json", "w") as hist_file: - hist_id = str(int(max(hist_info, default=0)) + 1) - hist_info[hist_id] = useratip - js = json.dumps(hist_info, sort_keys=True, indent=4, separators=(',', ': ')) - hist_file.write(js) + + new_conn = 1 + for i in hist_info: + if hist_info[i] == useratip: + new_conn = 0 + if new_conn == 1: + with open(HOMEDIR+"/.config/rdpconnect/history.json", "w") as hist_file: + hist_id = str(int(max(hist_info, default=0)) + 1) + hist_info[hist_id] = useratip + js = json.dumps(hist_info, sort_keys=True, indent=4, separators=(',', ': ')) + hist_file.write(js) + try: keyring.set_password("com.angoosh.RDPConnect", useratip, password) except: diff --git a/testing.py b/testing.py new file mode 100644 index 0000000..cc75c40 --- /dev/null +++ b/testing.py @@ -0,0 +1,385 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Mon Nov 18 12:04:53 2024 + +@author: angoosh + +references: +https://pygobject.gnome.org/tutorials/gtk4/introduction.html +https://docs.gtk.org/gtk3/index.html#classes +""" +import sys +import os +import gi +import subprocess +import json +from cryptography.fernet import Fernet +gi.require_version('Gtk', '4.0') +gi.require_version('Adw', '1') +from gi.repository import Gtk, Adw, Gdk, Gio +import keyring + +APPID = "com.angoosh.RDPConnect" +HOMEDIR = os.path.expanduser('~') + +VERSION = "1.3.0" + +conn_info = {} +hist_info = {} +settings = {} +settings["extra_params"] = {} +fernet = "" + +def load_keys(): + global fernet + cryptoKey = "" + try: + with open(HOMEDIR+"/.config/rdpconnect/.key", "r") as keyfile: + cryptoKey = str.encode(keyfile.readline()) + print("Encription key loaded") + except: + cryptoKey = Fernet.generate_key() + with open(HOMEDIR+"/.config/rdpconnect/.key", "w") as keyfile: + keyfile.write(cryptoKey.decode("utf-8")) + print("Encription key generated") + + fernet = Fernet(cryptoKey) + +def load_config(): + global conn_info, settings + loaded_json = "" + try: + with open(HOMEDIR+"/.config/rdpconnect/history.json", "r") as history_file: + for line in history_file: + loaded_json += line + + hist_info = json.loads(loaded_json) + last_conn = hist_info[max(hist_info)] + conn_info["user"] = last_conn.split('@')[0] + conn_info["ip"] = last_conn.split('@')[1] + conn_info["passwd"] = keyring.get_password("com.angoosh.RDPConnect", last_conn) + + except: + try: + with open(HOMEDIR+"/.config/rdpconnect/connection.json", "r") as connection_file: + for line in connection_file: + loaded_json += line + + conn_info = json.loads(loaded_json) + + conn_info["passwd"] = fernet.decrypt(str.encode(conn_info["passwd"])).decode() + except: + print("[WARN] FILE: "+HOMEDIR+"/.config/rdpconnect/connection.json doesn't exist") + + loaded_json = "" + try: + with open(HOMEDIR+"/.config/rdpconnect/settings.json", "r") as settings_file: + for line in settings_file: + loaded_json += line + + settings = json.loads(loaded_json) + except: + print("[WARN] FILE: "+HOMEDIR+"/.config/rdpconnect/settings.json doesn't exist") + +class HistoryWindow(Gtk.Window): + def __init__(self, **kargs): + super().__init__(**kargs, title='History') + + self.set_default_size(100, 300) + + self.scroll = Gtk.ScrolledWindow() + self.scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) + + self.grid = Gtk.Grid() + + self.scroll.set_child(self.grid) + + index = 0 + for i in hist_info: + self.addRow(hist_info[i], index) + index += 1 + + self.set_child(self.scroll) + + def addRow(self, entry, index): + runb = Gtk.Button(label=entry) + runb.connect("clicked", self.apply_contents) + + self.grid.attach(runb, 0, index, 1, 1) + + def apply_contents(self, button): + conn_info["user"] = button.get_label().split('@')[0] + conn_info["ip"] = button.get_label().split('@')[1] + try: + conn_info["passwd"] = keyring.get_password("com.angoosh.RDPConnect", button.get_label()) + except: + pass + +class PreferencesWindow(Gtk.Window): + global settings + def __init__(self, **kwargs): + super().__init__(**kwargs) + + self.builder = Gtk.Builder(self) + self.builder.add_from_file("/app/preferences.ui") + + self.resx = self.builder.get_object("resx") + self.resy = self.builder.get_object("resy") + self.monitors = self.builder.get_object("monitors") + self.fullscreen = self.builder.get_object("fullscreen") + self.xfree = self.builder.get_object("xfree") + self.sound = self.builder.get_object("sound") + self.mic = self.builder.get_object("mic") + self.dynres = self.builder.get_object("dynres") + self.clipboard = self.builder.get_object("clipboard") + + try: + self.clipboard.set_state(settings["extra_params"]["clipboard"]) + self.clipboard.set_active(settings["extra_params"]["clipboard"]) + except: + pass + try: + self.dynres.set_state(settings["extra_params"]["dynamic-resolution"]) + self.dynres.set_active(settings["extra_params"]["dynamic-resolution"]) + except: + pass + try: + self.mic.set_state(settings["extra_params"]["microphone"]) + self.mic.set_active(settings["extra_params"]["microphone"]) + except: + pass + try: + self.sound.set_state(settings["extra_params"]["sound"]) + self.sound.set_active(settings["extra_params"]["sound"]) + except: + pass + try: + if settings["rdp_bin"] == "xfreerdp": + self.xfree.set_state(True) + self.xfree.set_active(True) + except: + pass + try: + self.fullscreen.set_state(settings["extra_params"]["f"]) + self.fullscreen.set_active(settings["extra_params"]["f"]) + except: + pass + try: + self.monitors.get_buffer().set_text(str(settings["extra_params"]["monitors"]), len(settings["extra_params"]["monitors"])) + except: + pass + try: + self.resx.get_buffer().set_text(str(settings["extra_params"]["w"]), len(settings["extra_params"]["w"])) + except: + pass + try: + self.resy.get_buffer().set_text(str(settings["extra_params"]["h"]), len(settings["extra_params"]["h"])) + except: + pass + + pref_window = self.builder.get_object("pref_window") + pref_window.show() + + def f_resx(self, app): + settings["extra_params"]["w"] = self.resx.get_buffer().get_text() + + def f_resy(self, app): + settings["extra_params"]["h"] = self.resy.get_buffer().get_text() + + def monconf(self, app): + settings["extra_params"]["monitors"] = self.monitors.get_buffer().get_text() + + def clipboard(self, app, state): + if state: + settings["extra_params"]["clipboard"] = True + else: + settings["extra_params"]["clipboard"] = False + + def dynres(self, app, state): + if state: + settings["extra_params"]["dynamic-resolution"] = True + else: + settings["extra_params"]["dynamic-resolution"] = False + + def microphone(self, app, state): + if state: + settings["extra_params"]["microphone"] = True + else: + settings["extra_params"]["microphone"] = False + + def sound(self, app, state): + if state: + settings["extra_params"]["sound"] = True + else: + settings["extra_params"]["sound"] = False + + def xfree(self, app, state): + if state: + settings["rdp_bin"] = "xfreerdp" + else: + settings["rdp_bin"] = "sdl-freerdp" + + def fscr(self, app, state): + if state: + settings["extra_params"]["f"] = True + else: + settings["extra_params"]["f"] = False + + def on_destroy(self, app): + print("Saving settings config to "+HOMEDIR+"/.config/rdpconnect/settings.json") + with open(HOMEDIR+"/.config/rdpconnect/settings.json", "w") as settings_file: + js = json.dumps(settings, sort_keys=True, indent=4, separators=(',', ': ')) + settings_file.write(js) + + +class MyApp(Adw.Application): + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.connect('activate', self.on_activate) + + def on_activate(self, app): + builder = Gtk.Builder() + builder.add_from_file("/app/"+APPID+".ui") + buildermenu = Gtk.Builder() + buildermenu.add_from_file("/app/menu.ui") + menu_model = buildermenu.get_object('app-menu') + + css_provider = Gtk.CssProvider() + if Adw.StyleManager().get_default().get_dark(): + css_provider.load_from_file(Gio.File.new_for_path("/app/style-dark.css")) + else: + css_provider.load_from_file(Gio.File.new_for_path("/app/style-light.css")) + Gtk.StyleContext.add_provider_for_display(Gdk.Display.get_default(), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) + + connect = builder.get_object("connect") + connect.connect("clicked", self.connectRDP) + + self.ip = builder.get_object("ip") + self.user = builder.get_object("user") + self.passwd = builder.get_object("pass") + + self.save_conf = builder.get_object("save_conf") + + try: + if settings["save_conn"]: + self.ip.get_buffer().set_text(str(conn_info["ip"]), len(conn_info["ip"])) + self.user.get_buffer().set_text(str(conn_info["user"]), len(conn_info["user"])) + self.passwd.get_buffer().set_text(str(conn_info["passwd"]), len(conn_info["passwd"])) + + self.save_conf.set_active(True) + except: + pass + +#menu config + self.win = builder.get_object("main_window") + header_bar = Gtk.HeaderBar() + self.win.set_titlebar(header_bar) + + menubutton = Gtk.MenuButton(menu_model=menu_model, icon_name='open-menu-symbolic') + header_bar.pack_end(menubutton) + + self.win.set_application(self) + self.win.present() + + def do_startup(self): + Gtk.Application.do_startup(self) + + action = Gio.SimpleAction(name='preferences') + action.connect('activate', self.on_preferences) + self.add_action(action) + + action = Gio.SimpleAction(name='about') + action.connect('activate', self.on_about) + self.add_action(action) + + #action = Gio.SimpleAction(name='history') + #action.connect('activate', self.on_history) + #self.add_action(action) + + def on_about(self, action, param): + about_dialog = Gtk.AboutDialog(transient_for=self.win, modal=True) + about_dialog.set_copyright("Antonin Kaplan") + about_dialog.set_program_name("RDP Connect") + about_dialog.set_license_type(Gtk.License(16)) + about_dialog.set_logo_icon_name("com.angoosh.RDPConnect") + about_dialog.set_version(VERSION) + about_dialog.set_website("https://gitea.farmdash.org/angoosh/Flatpaks") + about_dialog.present() + + def on_preferences(self, action, param): + PreferencesWindow() + + def on_history(self, action, param): + HistoryWindow() + + def saveConnConf(self): + if settings["save_conn"]: + password = conn_info["passwd"] + useratip = conn_info["user"] + "@" + conn_info["ip"] + with open(HOMEDIR+"/.config/rdpconnect/history.json", "w") as hist_file: + hist_id = str(int(max(hist_info, default=0)) + 1) + hist_info[hist_id] = useratip + js = json.dumps(hist_info, sort_keys=True, indent=4, separators=(',', ': ')) + hist_file.write(js) + try: + keyring.set_password("com.angoosh.RDPConnect", useratip, password) + except: + conn_info["passwd"] = fernet.encrypt(password.encode()).decode("utf-8") + + print("Saving connection config to "+HOMEDIR+"/.config/rdpconnect/connection.json") + with open(HOMEDIR+"/.config/rdpconnect/connection.json", "w") as connection_file: + js = json.dumps(conn_info, sort_keys=True, indent=4, separators=(',', ': ')) + connection_file.write(js) + + conn_info["passwd"] = password + else: + with open(HOMEDIR+"/.config/rdpconnect/connection.json", "w") as connection_file: + connection_file.write("") + + print("Saving settings config to "+HOMEDIR+"/.config/rdpconnect/settings.json") + with open(HOMEDIR+"/.config/rdpconnect/settings.json", "w") as settings_file: + js = json.dumps(settings, sort_keys=True, indent=4, separators=(',', ': ')) + settings_file.write(js) + + def connectRDP(self, button): + conn_info["ip"] = self.ip.get_buffer().get_text() + conn_info["user"] = self.user.get_buffer().get_text() + conn_info["passwd"] = self.passwd.get_buffer().get_text() + + if self.save_conf.get_active(): + settings["save_conn"] = True + else: + settings["save_conn"] = False + if not "rdp_bin" in settings: + settings["rdp_bin"] = "sdl-freerdp" + + self.saveConnConf() + + extra_params = [] + for item in settings["extra_params"]: + #check if is boolean + if type(settings["extra_params"][item]) == type(True): + if settings["extra_params"][item]: + extra_params.append("/"+str(item)) + else: + if str(settings["extra_params"][item]) != "": + print(str(settings["extra_params"][item])) + extra_params.append("/"+str(item)+":"+str(settings["extra_params"][item])) + + print(extra_params) + + try: + print("Running", settings["rdp_bin"]) + subprocess.run([settings["rdp_bin"], "/cert:ignore", "/v:"+str(conn_info["ip"]), "/u:"+str(conn_info["user"]), "/p:"+str(conn_info["passwd"])]+extra_params) + except: + print("Running sdl-freerdp") + subprocess.run(["sdl-freerdp", "/cert:ignore", "/v:"+str(conn_info["ip"]), "/u:"+str(conn_info["user"]), "/p:"+str(conn_info["passwd"])]+extra_params) + +if not os.path.isdir(HOMEDIR+"/.config/rdpconnect"): + os.makedirs(HOMEDIR+"/.config/rdpconnect") + +load_keys() +load_config() +app = MyApp(application_id=APPID) +app.run(sys.argv)