diff --git a/wirepy.py b/wirepy.py index eb31c51..ca0631b 100755 --- a/wirepy.py +++ b/wirepy.py @@ -110,79 +110,6 @@ class FrameWidgets(ttk.Frame): self.exp_pic = tk.PhotoImage(file=r"/usr/share/icons/lx-icons/48/wg_export.png") self.warning_pic = tk.PhotoImage(file=r"/usr/share/icons/lx-icons/64/error.png") - def update(): - """ - Set on or off in file - """ - if set_update.get() == 1: - with open(set_file, "r", encoding="utf-8") as set_f2: - lines2 = set_f2.readlines() - lines2[1] = "off\n" - with open(set_file, "w", encoding="utf-8") as set_f2: - set_f2.writelines(lines2) - - if set_update.get() == 0: - with open(set_file, "r", encoding="utf-8") as set_f2: - lines2 = set_f2.readlines() - lines2[1] = "on\n" - with open(set_file, "w", encoding="utf-8") as set_f2: - set_f2.writelines(lines2) - - def theme_change_light(): - """ - Set a light theme - """ - if self.tk.call("ttk::style", "theme", "use") == "water-dark": - self.tk.call("set_theme", "light") - with open(set_file, "r", encoding="utf-8") as theme_set2: - lines3 = theme_set2.readlines() - lines3[3] = "light\n" - with open(set_file, "w", encoding="utf-8") as theme_set2: - theme_set2.writelines(lines3) - self.color_label() - - def theme_change_dark(): - """ - Set a dark theme - """ - if not self.tk.call("ttk::style", "theme", "use") == "water-dark": - self.tk.call("set_theme", "dark") - with open(set_file, "r", encoding="utf-8") as theme_set2: - lines4 = theme_set2.readlines() - lines4[3] = "dark\n" - with open(set_file, "w", encoding="utf-8") as theme_set2: - theme_set2.writelines(lines4) - self.color_label() - - def tooltip(): - """ - Set True or False in a file - """ - if set_tip.get(): - with open(set_file, "r", encoding="utf-8") as set_f2: - lines2 = set_f2.readlines() - lines2[5] = "False\n" - with open(set_file, "w", encoding="utf-8") as set_f2: - set_f2.writelines(lines2) - - else: - with open(set_file, "r", encoding="utf-8") as set_f2: - lines2 = set_f2.readlines() - lines2[5] = "True\n" - with open(set_file, "w", encoding="utf-8") as set_f2: - set_f2.writelines(lines2) - - def info(): - def link_btn(): - webbrowser.open("https://git.ilunix.de/punix/Wire-Py") - - msg_t = _("Wire-Py a simple Wireguard Gui for Linux systems.\n\n" - "Wire-Py is open source software written in Python.\n\n" - "Email: polunga40@unity-mail.de also likes for donation.\n\n" - "Use without warranty!\n") - - LxTools.msg_window(img_i, img_i, _("Info"), msg_t, _("Go to Wire-Py git"), link_btn) - # Frame for Menu self.menu_frame = ttk.Frame(self) self.menu_frame.configure(relief="flat") @@ -204,15 +131,14 @@ class FrameWidgets(ttk.Frame): set_tip = tk.BooleanVar() self.settings = tk.Menu(self, relief="flat") self.options_btn.configure(menu=self.settings, style="Toolbutton") - self.settings.add_checkbutton(label=_("Disable Updates"), command=update, variable=set_update) - self.settings.add_checkbutton(label=_("Disable Tooltips"), command=tooltip, variable=set_tip) - self.settings.add_command(label=_("Light"), command=theme_change_light) - self.settings.add_command(label=_("Dark"), command=theme_change_dark) + self.settings.add_checkbutton(label=_("Disable Updates"), command=lambda: self.update(set_update.get()), variable=set_update) + self.settings.add_checkbutton(label=_("Disable Tooltips"), command=lambda: self.tooltip(set_tip.get()), variable=set_tip) + self.settings.add_command(label=_("Light"), command=self.theme_change_light) + self.settings.add_command(label=_("Dark"), command=self.theme_change_dark) # About BTN Menu / Label self.about_btn = ttk.Button( - self.menu_frame, text=_("About"), style="Toolbutton", command=info - ) + self.menu_frame, text=_("About"), style="Toolbutton", command=self.info) self.about_btn.grid(column=2, columnspan=2, row=0) self.readme = tk.Menu(self) @@ -306,23 +232,12 @@ class FrameWidgets(ttk.Frame): self.peer.config(font=("Ubuntu", 9)) self.peer.grid(column=0, row=4, sticky="we", padx=130) - def enable_check_box(_): - """ - checkbox for enable autostart Tunnel - """ - Create.files_for_autostart() - if self.l_box.size() != 0: - self.wg_autostart.configure(state="normal") - self.lb_rename.config(state="normal") - self.lb_rename.delete(0, tk.END) - self.btn_rename.config(state="normal") - # Listbox with Scrollbar self.l_box = tk.Listbox(self.lb_frame_btn_lbox, selectmode="single") self.l_box.config(relief="ridge", font=("Ubuntu", 12, "bold")) self.l_box.grid(column=1, rowspan=4, row=0, sticky="ns") self.l_box.event_add("<>", "") - self.l_box.bind("<>", enable_check_box) + self.l_box.bind("<>", self.enable_check_box) self.scrollbar = ttk.Scrollbar(self.lb_frame_btn_lbox, orient="vertical", command=self.l_box.yview) self.scrollbar.grid(column=1, rowspan=4, row=0, sticky="nse") self.l_box.configure(yscrollcommand=self.scrollbar.set) @@ -333,7 +248,6 @@ class FrameWidgets(ttk.Frame): self.l_box.insert("end", tunnels[:-5]) self.l_box.update() - # Button Vpn if self.a != "": self.stop() @@ -354,74 +268,8 @@ class FrameWidgets(ttk.Frame): Tooltip(self.btn_i, _("Click to import a Wireguard Tunnel"), tips) - def delete(): - """ - delete Wireguard Tunnel - """ - try: - self.select_tunnel = self.l_box.curselection() - select_tl = self.l_box.get(self.select_tunnel[0]) - with open(f"/tmp/tlecdcwg/{select_tl}.conf", "r+", encoding="utf-8") as file2: - key = Tunnel.con_to_dict(file2) - pre_key = key[3] - check_call(["nmcli", "connection", "delete", select_tl]) - self.l_box.delete(self.select_tunnel[0]) - with open(set_file, "r", encoding="utf-8") as set_f6: - lines6 = set_f6.readlines() - if ( - select_tl == lines6[7].strip() - and "off\n" not in lines6[7].strip() - ): - lines6[7] = "off\n" - with open(set_file, "w", encoding="utf-8") as set_f7: - set_f7.writelines(lines6) - self.selected_option.set(0) - self.autoconnect_var.set(_("no Autoconnect")) - is_encrypt = Path.home() / f".config/wire_py/{select_tl}.dat" - if is_encrypt.is_file(): - Path.unlink(f"{Path.home()}/.config/wire_py/{select_tl}.dat") - Path.unlink(f"/tmp/tlecdcwg/{select_tl}.conf") - with open(f"{Path.home()}/.config/wire_py/keys", "r", encoding="utf-8") as readfile: - with open(f"{Path.home()}/.config/wire_py/keys2", "w", encoding="utf-8") as writefile: - for line in readfile: - if pre_key not in line.strip("\n"): - writefile.write(line) - file_one = Path(f"{Path.home()}/.config/wire_py/keys2") - file_two = file_one.with_name("keys") - file_one.replace(file_two) - self.wg_autostart.configure(state="disabled") - - # for disabling checkbox when Listbox empty - if self.l_box.size() == 0: - self.wg_autostart.configure(state="disabled") - self.lb_rename.configure(state="disabled") - Tooltip(self.wg_autostart, _("You must have at least one\ntunnel in the list,to use the autostart") - , tips) - - Tooltip(self.btn_exp, _("No Tunnels in List for Export"), tips) - Tooltip(self.btn_stst, _("No tunnels to start in the list"), tips) - Tooltip(self.lb_rename, _("To rename a tunnel, at least one must be in the list"), tips, ) - self.lb_rename.insert(0, _("Max. 12 characters!")) - - if self.a != "" and self.a == select_tl: - self.str_var.set(value="") - self.start() - self.l_box.update() - - self.reset_fields() - - except IndexError: - - if self.l_box.size() != 0: - - LxTools.msg_window(img_w, img_i2, sl, pstl) - - else: - - LxTools.msg_window(img_w, img_i2, sl, pfit) - # Button Trash - self.btn_tr = ttk.Button(self.lb_frame_btn_lbox, image=self.tr_pic, command=delete, padding=0, + self.btn_tr = ttk.Button(self.lb_frame_btn_lbox, image=self.tr_pic, command=self.delete, padding=0, style="CButton.TButton") self.btn_tr.grid(column=0, row=2, padx=15, pady=8) @@ -451,60 +299,8 @@ class FrameWidgets(ttk.Frame): else: Tooltip(self.lb_rename, _("To rename a tunnel, at least one must be in the list"), tips) - def tl_rename(): - - special_characters = ["\\", "/", "{", "}", " "] - - if len(self.lb_rename.get()) > 12: - - LxTools.msg_window(img_w, img_i2, rnp, _("The new name may contain only 12 characters")) - - elif len(self.lb_rename.get()) == 0: - - LxTools.msg_window(img_w, img_i2, rnp, _("At least one character must be entered")) - - elif any(ch in special_characters for ch in self.lb_rename.get()): - - msg_t = _("No valid sign. These must not be used.\nBlank, Slash, Backslash and { }\n") - LxTools.msg_window(img_w, img_i2, rnp, msg_t) - - else: - - try: - self.select_tunnel = self.l_box.curselection() - select_tl = self.l_box.get(self.select_tunnel[0]) - - # nmcli connection modify old connection.id iphone - check_call(["nmcli", "connection", "modify", select_tl, "connection.id", self.lb_rename.get()]) - source = Path(f"/tmp/tlecdcwg/{select_tl}.conf") - destination = source.with_name(f"{self.lb_rename.get()}.conf") - source.replace(destination) - Path.unlink(f"{Path.home()}/.config/wire_py/{select_tl}.dat") - - self.l_box.delete(self.select_tunnel[0]) - self.l_box.insert("end", self.lb_rename.get()) - self.l_box.update() - new_a_connect = self.lb_rename.get() - self.lb_rename.delete(0, tk.END) - if self.a != "" and self.a == select_tl: - self.a = Tunnel.active() - self.str_var.set(value=self.a) - with open(set_file, "r", encoding="utf-8") as set_f5: - lines5 = set_f5.readlines() - if select_tl == lines5[7].strip() and "off\n" not in lines5[7].strip(): - lines5[7] = new_a_connect - with open(set_file, "w", encoding="utf-8") as theme_set5: - theme_set5.writelines(lines5) - self.autoconnect_var.set(value=new_a_connect) - - Create.encrypt() - - except IndexError: - - LxTools.msg_window(img_w, img_i2, rnp, pstl) - # Button Rename - self.btn_rename = ttk.Button(self.lb_frame4, text=_("Rename"), state="disable", command=tl_rename, padding=4, + self.btn_rename = ttk.Button(self.lb_frame4, text=_("Rename"), state="disable", command=self.tl_rename, padding=4, style="RnButton.TButton") self.btn_rename.grid(column=3, row=0, padx=5, pady=10, sticky="ne") @@ -533,6 +329,215 @@ class FrameWidgets(ttk.Frame): self.on_off() + def info(self): + def link_btn(): + webbrowser.open("https://git.ilunix.de/punix/Wire-Py") + + msg_t = _("Wire-Py a simple Wireguard Gui for Linux systems.\n\n" + "Wire-Py is open source software written in Python.\n\n" + "Email: polunga40@unity-mail.de also likes for donation.\n\n" + "Use without warranty!\n") + + LxTools.msg_window(img_i, img_i, _("Info"), msg_t, _("Go to Wire-Py git"), link_btn) + + def theme_change_light(self): + """ + Set a light theme + """ + if self.tk.call("ttk::style", "theme", "use") == "water-dark": + self.tk.call("set_theme", "light") + with open(set_file, "r", encoding="utf-8") as theme_set2: + lines3 = theme_set2.readlines() + lines3[3] = "light\n" + with open(set_file, "w", encoding="utf-8") as theme_set2: + theme_set2.writelines(lines3) + self.color_label() + + def theme_change_dark(self): + """ + Set a dark theme + """ + if not self.tk.call("ttk::style", "theme", "use") == "water-dark": + self.tk.call("set_theme", "dark") + with open(set_file, "r", encoding="utf-8") as theme_set2: + lines4 = theme_set2.readlines() + lines4[3] = "dark\n" + with open(set_file, "w", encoding="utf-8") as theme_set2: + theme_set2.writelines(lines4) + self.color_label() + + def update(self, update_res): + """ + write off or on in file + Args: + update_res (int): argument that is passed contains 0 or 1 + """ + if update_res == 1: + with open(set_file, "r", encoding="utf-8") as set_f2: + lines2 = set_f2.readlines() + lines2[1] = "off\n" + with open(set_file, "w", encoding="utf-8") as set_f2: + set_f2.writelines(lines2) + + else: + with open(set_file, "r", encoding="utf-8") as set_f2: + lines2 = set_f2.readlines() + lines2[1] = "on\n" + with open(set_file, "w", encoding="utf-8") as set_f2: + set_f2.writelines(lines2) + + def tooltip(self, tip) -> None: + """ + write True or False in a file + Args: + tip (bool): argument that is passed contains True or False + """ + if tip: + with open(set_file, "r", encoding="utf-8") as set_f2: + lines2 = set_f2.readlines() + lines2[5] = "False\n" + with open(set_file, "w", encoding="utf-8") as set_f2: + set_f2.writelines(lines2) + + else: + with open(set_file, "r", encoding="utf-8") as set_f2: + lines2 = set_f2.readlines() + lines2[5] = "True\n" + with open(set_file, "w", encoding="utf-8") as set_f2: + set_f2.writelines(lines2) + + def enable_check_box(self, _): + """ + checkbox for enable autostart Tunnel + """ + Create.files_for_autostart() + if self.l_box.size() != 0: + self.wg_autostart.configure(state="normal") + self.lb_rename.config(state="normal") + self.lb_rename.delete(0, tk.END) + self.btn_rename.config(state="normal") + + def delete(self): + """ + delete Wireguard Tunnel + """ + try: + self.select_tunnel = self.l_box.curselection() + select_tl = self.l_box.get(self.select_tunnel[0]) + with open(f"/tmp/tlecdcwg/{select_tl}.conf", "r+", encoding="utf-8") as file2: + key = Tunnel.con_to_dict(file2) + pre_key = key[3] + check_call(["nmcli", "connection", "delete", select_tl]) + self.l_box.delete(self.select_tunnel[0]) + with open(set_file, "r", encoding="utf-8") as set_f6: + lines6 = set_f6.readlines() + if ( + select_tl == lines6[7].strip() + and "off\n" not in lines6[7].strip() + ): + lines6[7] = "off\n" + with open(set_file, "w", encoding="utf-8") as set_f7: + set_f7.writelines(lines6) + self.selected_option.set(0) + self.autoconnect_var.set(_("no Autoconnect")) + is_encrypt = Path.home() / f".config/wire_py/{select_tl}.dat" + if is_encrypt.is_file(): + Path.unlink(f"{Path.home()}/.config/wire_py/{select_tl}.dat") + Path.unlink(f"/tmp/tlecdcwg/{select_tl}.conf") + with open(f"{Path.home()}/.config/wire_py/keys", "r", encoding="utf-8") as readfile: + with open(f"{Path.home()}/.config/wire_py/keys2", "w", encoding="utf-8") as writefile: + for line in readfile: + if pre_key not in line.strip("\n"): + writefile.write(line) + file_one = Path(f"{Path.home()}/.config/wire_py/keys2") + file_two = file_one.with_name("keys") + file_one.replace(file_two) + self.wg_autostart.configure(state="disabled") + + # for disabling checkbox when Listbox empty + if self.l_box.size() == 0: + self.wg_autostart.configure(state="disabled") + self.lb_rename.configure(state="disabled") + Tooltip(self.wg_autostart, _("You must have at least one\ntunnel in the list,to use the autostart") + , tips) + + Tooltip(self.btn_exp, _("No Tunnels in List for Export"), tips) + Tooltip(self.btn_stst, _("No tunnels to start in the list"), tips) + Tooltip(self.lb_rename, _("To rename a tunnel, at least one must be in the list"), tips, ) + self.lb_rename.insert(0, _("Max. 12 characters!")) + + if self.a != "" and self.a == select_tl: + self.str_var.set(value="") + self.start() + self.l_box.update() + + self.reset_fields() + + except IndexError: + + if self.l_box.size() != 0: + + LxTools.msg_window(img_w, img_i2, sl, pstl) + + else: + + LxTools.msg_window(img_w, img_i2, sl, pfit) + + def tl_rename(self) -> None: + + special_characters = ["\\", "/", "{", "}", " "] + + if len(self.lb_rename.get()) > 12: + + LxTools.msg_window(img_w, img_i2, rnp, _("The new name may contain only 12 characters")) + + elif len(self.lb_rename.get()) == 0: + + LxTools.msg_window(img_w, img_i2, rnp, _("At least one character must be entered")) + + elif any(ch in special_characters for ch in self.lb_rename.get()): + + msg_t = _("No valid sign. These must not be used.\nBlank, Slash, Backslash and { }\n") + LxTools.msg_window(img_w, img_i2, rnp, msg_t) + + else: + + try: + self.select_tunnel = self.l_box.curselection() + select_tl = self.l_box.get(self.select_tunnel[0]) + + # nmcli connection modify old connection.id iphone + check_call(["nmcli", "connection", "modify", select_tl, "connection.id", self.lb_rename.get()]) + source = Path(f"/tmp/tlecdcwg/{select_tl}.conf") + destination = source.with_name(f"{self.lb_rename.get()}.conf") + source.replace(destination) + Path.unlink(f"{Path.home()}/.config/wire_py/{select_tl}.dat") + + self.l_box.delete(self.select_tunnel[0]) + self.l_box.insert("end", self.lb_rename.get()) + self.l_box.update() + new_a_connect = self.lb_rename.get() + self.lb_rename.delete(0, tk.END) + if self.a != "" and self.a == select_tl: + self.a = Tunnel.active() + self.str_var.set(value=self.a) + with open(set_file, "r", encoding="utf-8") as set_f5: + lines5 = set_f5.readlines() + if select_tl == lines5[7].strip() and "off\n" not in lines5[7].strip(): + lines5[7] = new_a_connect + with open(set_file, "w", encoding="utf-8") as theme_set5: + theme_set5.writelines(lines5) + self.autoconnect_var.set(value=new_a_connect) + + Create.encrypt() + + except IndexError: + + LxTools.msg_window(img_w, img_i2, rnp, pstl) + + except subprocess.CalledProcessError: + pass + def import_sl(self): """ Import Methode for Wireguard config Files. @@ -771,7 +776,7 @@ class FrameWidgets(ttk.Frame): """ Stop Button """ - self.btn_stst = ttk.Button(self.lb_frame_btn_lbox, image=self.wg_vpn_stop, command=self.wg_switch, padding=0) + self.btn_stst = ttk.Button(self.lb_frame_btn_lbox, image=self.wg_vpn_stop, command=lambda: self.wg_switch("stop"), padding=0) self.btn_stst.grid(column=0, row=0, padx=5, pady=8) Tooltip(self.btn_stst, _("Click to stop selected Wireguard Tunnel"), tips) @@ -780,7 +785,7 @@ class FrameWidgets(ttk.Frame): """ Start Button """ - self.btn_stst = ttk.Button(self.lb_frame_btn_lbox, image=self.wg_vpn_start, command=self.wg_switch, padding=0) + self.btn_stst = ttk.Button(self.lb_frame_btn_lbox, image=self.wg_vpn_start, command=lambda: self.wg_switch("start"), padding=0) self.btn_stst.grid(column=0, row=0, padx=5, pady=8) tl = Tunnel.list() @@ -805,41 +810,22 @@ class FrameWidgets(ttk.Frame): self.lb_tunnel.config(font=("Ubuntu", 11, "bold")) self.lb_tunnel.grid(column=2, padx=10, row=1) - def wg_switch(self): + def wg_switch(self, event=None) -> None: """ - switch Tunnel method change from labels and buttons + Deals with switching the VPN connection """ - self.a = Tunnel.active() try: if self.a == "": - - self.start() self.select_tunnel = self.l_box.curselection() select_tl = self.l_box.get(self.select_tunnel[0]) - check_call(["nmcli", "connection", "up", select_tl]) + self.handle_connection_state("start", select_tl) + + else: + data = self.handle_tunnel_data(self.a) + if data: - # Button Start/Stop - self.stop() - self.a = Tunnel.active() - self.str_var = tk.StringVar() - self.str_var.set(self.a) - self.color_label() - - elif self.a != "": - - # Button Start/Stop - self.stop() - check_call(["nmcli", "connection", "down", self.a]) - - # Button Start/Stop - self.start() - self.a = Tunnel.active() - self.str_var.set("") - self.color_label() - - self.reset_fields() - self.show_data() + self.handle_connection_state("stop") except IndexError: @@ -851,6 +837,49 @@ class FrameWidgets(ttk.Frame): LxTools.msg_window(img_w, img_i2, sl, pfit) + def handle_connection_state(self, action: str, tunnel_name: str = None) -> None: + """ + Central management for connection states + + Args: + action (str): "start", "stop" or "toggle" + tunnel_name (str, optional): name of tunnel for start-option. defaults to None. + """ + if action == "stop": + if self.a: + check_call(["nmcli", "connection", "down", self.a]) + self.update_connection_display() + self.reset_fields() + self.start() + + elif action == "start": + if tunnel_name or self.a: + target_tunnel = tunnel_name or self.a + check_call(["nmcli", "connection", "up", target_tunnel]) + self.update_connection_display() + data = self.handle_tunnel_data(self.a) + self.init_and_report(data) + self.show_data() + self.color_label() + self.stop() + + elif action == "toggle": + if self.a: + self.handle_connection_state("stop") + else: + self.handle_connection_state("start") + + def update_connection_display(self) -> None: + """ + Updated the display after connection changes + """ + self.a = Tunnel.active() + if not hasattr(self, "str_var"): + self.str_var = tk.StringVar() + self.str_var.set(self.a) + self.color_label() + self.show_data() + if __name__ == "__main__": window = Wirepy()