870 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			870 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/python3
 | 
						|
"""
 | 
						|
this script is a simple GUI for managing Wireguard Tunnels
 | 
						|
"""
 | 
						|
import gettext
 | 
						|
import locale
 | 
						|
import os
 | 
						|
import shutil
 | 
						|
import subprocess
 | 
						|
import sys
 | 
						|
import tkinter as tk
 | 
						|
import webbrowser
 | 
						|
from pathlib import Path
 | 
						|
from subprocess import check_call
 | 
						|
from tkinter import TclError, filedialog, ttk
 | 
						|
 | 
						|
from cls_mth_fc import (Create, GiteaUpdate, Tooltip, Tunnel, LxTools)
 | 
						|
 | 
						|
LxTools.uos()
 | 
						|
Create.dir_and_files()
 | 
						|
Create.make_dir()
 | 
						|
Create.decrypt()
 | 
						|
 | 
						|
tcl_path: Path = Path("/usr/share/TK-Themes")
 | 
						|
set_file: Path = Path(Path.home() / ".config/wire_py/settings")
 | 
						|
keys: Path = Path(Path.home() / ".config/wire_py/keys")
 | 
						|
 
 | 
						|
tips = LxTools.if_tip(set_file)
 | 
						|
folder_path: Path = Path("/tmp/tlecdcwg/")
 | 
						|
user_file = Path("/tmp/.log_user")
 | 
						|
 | 
						|
# 1 = 1. Year, 09 = Month of the Year, 2924 = Day and Year of the Year
 | 
						|
VERSION: str = "v. 2.04.1725"
 | 
						|
 | 
						|
res = GiteaUpdate.api_down("https://git.ilunix.de/api/v1/repos/punix/Wire-Py/releases", VERSION, set_file)
 | 
						|
 | 
						|
# Translate
 | 
						|
APP = "wirepy"
 | 
						|
LOCALE_DIR = "/usr/share/locale/"
 | 
						|
locale.bindtextdomain(APP, LOCALE_DIR)
 | 
						|
gettext.bindtextdomain(APP, LOCALE_DIR)
 | 
						|
gettext.textdomain(APP)
 | 
						|
_ = gettext.gettext
 | 
						|
 | 
						|
img_w: str = r"/usr/share/icons/lx-icons/64/info.png"
 | 
						|
img_i: str = r"/usr/share/icons/lx-icons/48/wg_vpn.png"
 | 
						|
img_w2: str = r"/usr/share/icons/lx-icons/64/error.png"
 | 
						|
img_i2: str = r"/usr/share/icons/lx-icons/48/wg_msg.png"
 | 
						|
sl: str = _("Select tunnel")
 | 
						|
rnp: str = _("Renaming not possible")
 | 
						|
ie:str = _("Import Error")
 | 
						|
pfit: str = _("Please first import tunnel")
 | 
						|
pstl: str = _("Please select a tunnel from the list")
 | 
						|
 | 
						|
LxTools.sigi(folder_path, user_file)
 | 
						|
 | 
						|
class Wirepy(tk.Tk):
 | 
						|
    """
 | 
						|
    Class Wirepy this is the Main Window of wirepy
 | 
						|
    """
 | 
						|
    def __init__(self, *args, **kwargs):
 | 
						|
        super().__init__(*args, **kwargs)
 | 
						|
 | 
						|
        self.my_tool_tip = None
 | 
						|
        self.x_width = 600
 | 
						|
        self.y_height = 383
 | 
						|
        self.monitor_center_x = int(self.winfo_screenwidth() / 2 - (self.x_width / 2))
 | 
						|
        self.monitor_center_y = int(self.winfo_screenheight() / 2 - (self.y_height / 2))
 | 
						|
        self.resizable(width=False, height=False)
 | 
						|
        self.title("Wire-Py")
 | 
						|
        self.geometry(f"{self.x_width}x{self.y_height}+{self.monitor_center_x}+{self.monitor_center_y}")
 | 
						|
        self.columnconfigure(0, weight=1)
 | 
						|
        self.rowconfigure(0, weight=1)
 | 
						|
 | 
						|
        self.style = ttk.Style(self)
 | 
						|
        self.tk.call("source", f"{tcl_path}/water.tcl")
 | 
						|
 | 
						|
        lines = set_file.read_text()
 | 
						|
        if "light\n" in lines:
 | 
						|
            self.tk.call("set_theme", "light")
 | 
						|
        else:
 | 
						|
            self.tk.call("set_theme", "dark")
 | 
						|
 | 
						|
        # Load the image file from the disk
 | 
						|
        self.wg_icon = tk.PhotoImage(file=r"/usr/share/icons/lx-icons/48/wg_vpn.png")
 | 
						|
 | 
						|
        # Set it as the window icon
 | 
						|
        self.iconphoto(True, self.wg_icon)
 | 
						|
 | 
						|
        FrameWidgets(self).grid()
 | 
						|
 | 
						|
 | 
						|
class FrameWidgets(ttk.Frame):
 | 
						|
    """
 | 
						|
    ttk frame class for better structure
 | 
						|
    """
 | 
						|
    def __init__(self, container, **kwargs):
 | 
						|
        super().__init__(container, **kwargs)
 | 
						|
 | 
						|
        self.lb_tunnel = None
 | 
						|
        self.btn_stst = None
 | 
						|
        self.endpoint = None
 | 
						|
        self.dns = None
 | 
						|
        self.address = None
 | 
						|
        self.auto_con = None
 | 
						|
        self.wg_vpn_start = tk.PhotoImage(file=r"/usr/share/icons/lx-icons/48/wg_vpn-start.png")
 | 
						|
        self.wg_vpn_stop = tk.PhotoImage(file=r"/usr/share/icons/lx-icons/48/wg_vpn-stop.png")
 | 
						|
        self.imp_pic = tk.PhotoImage(file=r"/usr/share/icons/lx-icons/48/wg_import.png")
 | 
						|
        self.tr_pic = tk.PhotoImage(file=r"/usr/share/icons/lx-icons/48/wg_trash.png")
 | 
						|
        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")
 | 
						|
 | 
						|
        # Frame for Menu
 | 
						|
        self.menu_frame = ttk.Frame(self)
 | 
						|
        self.menu_frame.configure(relief="flat")
 | 
						|
        self.menu_frame.grid(column=0, row=0, columnspan=4, sticky="w")
 | 
						|
 | 
						|
        # App Menu
 | 
						|
        self.version_lb = ttk.Label(self.menu_frame, text=VERSION)
 | 
						|
        self.version_lb.config(font=("Ubuntu", 11), foreground="#00c4ff")
 | 
						|
        self.version_lb.grid(column=0, row=0, rowspan=4, padx=10)
 | 
						|
 | 
						|
        Tooltip(self.version_lb, f"Version: {VERSION[2:]}", tips)
 | 
						|
 | 
						|
        self.options_btn = ttk.Menubutton(self.menu_frame, text=_("Options"))
 | 
						|
        self.options_btn.grid(column=1, columnspan=1, row=0)
 | 
						|
 | 
						|
        Tooltip(self.options_btn, _("Click for Settings"), tips)
 | 
						|
 | 
						|
        set_update = tk.IntVar()
 | 
						|
        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=lambda: self.update_setting(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=self.about)
 | 
						|
        self.about_btn.grid(column=2, columnspan=2, row=0)
 | 
						|
        self.readme = tk.Menu(self)
 | 
						|
 | 
						|
        # Update and Tooltip Label
 | 
						|
        self.updates_lb = ttk.Label(self.menu_frame)
 | 
						|
        self.updates_lb.grid(column=4, columnspan=3, row=0, padx=10)
 | 
						|
 | 
						|
        # View Checkbox to enable or disable Tooltip
 | 
						|
        if tips:
 | 
						|
            set_tip.set(value=False)
 | 
						|
        else:
 | 
						|
            set_tip.set(value=True)
 | 
						|
 | 
						|
        # View Checkbox for enable or disable Updates
 | 
						|
        if res == "False":
 | 
						|
            set_update.set(value=1)
 | 
						|
            self.updates_lb.configure(text=_("Update search off"))
 | 
						|
 | 
						|
            Tooltip(self.updates_lb, _("Updates you have disabled"), tips)
 | 
						|
 | 
						|
        elif res == "No Internet Connection!":
 | 
						|
            self.updates_lb.configure(text=_("No Server Connection!"), foreground="red")
 | 
						|
        elif res == "No Updates":
 | 
						|
            self.updates_lb.configure(text=_("No Updates"))
 | 
						|
 | 
						|
            Tooltip(self.updates_lb, _("Congratulations! Wire-Py is up to date"), tips)
 | 
						|
 | 
						|
        else:
 | 
						|
            set_update.set(value=0)
 | 
						|
            text = f"Update {res} {_("available!")}"
 | 
						|
 | 
						|
            # Update BTN Menu
 | 
						|
            self.update_btn = ttk.Menubutton(self.menu_frame, text=text)
 | 
						|
            self.update_btn.grid(column=4, columnspan=3, row=0, padx=0)
 | 
						|
 | 
						|
            Tooltip(self.update_btn, _("Click to download new version"), tips)
 | 
						|
 | 
						|
            self.download = tk.Menu(self, relief="flat")
 | 
						|
 | 
						|
            self.update_btn.configure(menu=self.download, style="Toolbutton")
 | 
						|
            self.download.add_command(
 | 
						|
                label=_("Download"),
 | 
						|
                command=lambda: GiteaUpdate.download(f"https://git.ilunix.de/punix/Wire-Py/archive/{res}.zip", 
 | 
						|
                                                    res, img_w, img_i, img_w2, img_i2))
 | 
						|
 | 
						|
        # Show active Tunnel
 | 
						|
        self.a = Tunnel.active()
 | 
						|
 | 
						|
        # Label Frame 1
 | 
						|
        self.lb_frame_btn_lbox = ttk.Frame(self)
 | 
						|
        self.lb_frame_btn_lbox.configure(relief="flat")
 | 
						|
        self.lb_frame_btn_lbox.grid(column=0, rowspan=3, row=1)
 | 
						|
 | 
						|
        # Label Frame 2
 | 
						|
        self.lb_frame = ttk.Frame(self)
 | 
						|
        self.lb_frame.configure(relief="solid")
 | 
						|
        self.lb_frame.grid(column=2, row=2, sticky="snew", padx=20, pady=5)
 | 
						|
 | 
						|
        # Label Frame 3
 | 
						|
        self.lb_frame2 = ttk.Frame(self)
 | 
						|
        self.lb_frame2.configure(relief="solid")
 | 
						|
        self.lb_frame2.grid(column=2, row=3, sticky="snew", padx=20, pady=5)
 | 
						|
 | 
						|
        # Bottom Frame 4
 | 
						|
        self.lb_frame3 = ttk.Frame(self)
 | 
						|
        self.lb_frame3.configure(relief="flat")
 | 
						|
        self.lb_frame3.grid(column=0, row=5, columnspan=4, sticky="snew", padx=2, pady=2)
 | 
						|
 | 
						|
        # Bottom Frame 5
 | 
						|
        self.lb_frame4 = ttk.Frame(self)
 | 
						|
        self.lb_frame4.configure(relief="flat")
 | 
						|
        self.lb_frame4.grid(column=2, row=5, columnspan=3, sticky="e", padx=15)
 | 
						|
 | 
						|
        # Show active Label
 | 
						|
        self.select_tunnel = None
 | 
						|
        self.lb = ttk.Label(self, text=_("Active: "))
 | 
						|
        self.lb.config(font=("Ubuntu", 11, "bold"))
 | 
						|
        self.lb.grid(column=2, row=1, padx=15, pady=4, sticky="w")
 | 
						|
 | 
						|
        # Label to Show active Tunnel
 | 
						|
        self.str_var = tk.StringVar(value=self.a)
 | 
						|
        self.color_label()
 | 
						|
 | 
						|
        # Interface Label
 | 
						|
        self.interface = ttk.Label(self.lb_frame, text=_("Interface"))
 | 
						|
        self.interface.grid(column=0, row=3, sticky="we", padx=120)
 | 
						|
        self.interface.config(font=("Ubuntu", 9))
 | 
						|
 | 
						|
        # Peer Label
 | 
						|
        self.peer = ttk.Label(self.lb_frame2, text=_("Peer"))
 | 
						|
        self.peer.config(font=("Ubuntu", 9))
 | 
						|
        self.peer.grid(column=0, row=4, sticky="we", padx=130)
 | 
						|
 | 
						|
        # 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("<<ClickEvent>>", "<Button-1>")
 | 
						|
        self.l_box.bind("<<ClickEvent>>", 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)
 | 
						|
 | 
						|
        # Tunnel List
 | 
						|
        self.tl = Tunnel.list()
 | 
						|
        for tunnels in self.tl:
 | 
						|
            self.l_box.insert("end", tunnels[:-5])
 | 
						|
            self.l_box.update()
 | 
						|
 | 
						|
        # Button Vpn
 | 
						|
        if self.a != "":
 | 
						|
            self.stop()
 | 
						|
            data = self.handle_tunnel_data(self.a)
 | 
						|
        else:
 | 
						|
            self.start()
 | 
						|
 | 
						|
            # Address Label
 | 
						|
            self.add = tk.StringVar()
 | 
						|
            self.DNS = tk.StringVar()
 | 
						|
            self.enp = tk.StringVar()
 | 
						|
            self.reset_fields()
 | 
						|
            self.show_data()
 | 
						|
 | 
						|
        # Button Import
 | 
						|
        self.btn_i = ttk.Button(self.lb_frame_btn_lbox, image=self.imp_pic, command=self.import_sl, padding=0)
 | 
						|
        self.btn_i.grid(column=0, row=1, padx=15, pady=8)
 | 
						|
 | 
						|
        Tooltip(self.btn_i, _("Click to import a Wireguard Tunnel"), tips)
 | 
						|
 | 
						|
        # Button Trash
 | 
						|
        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)
 | 
						|
 | 
						|
        if self.l_box.size() == 0:
 | 
						|
            Tooltip(self.btn_tr, _("No tunnels to delete in the list"), tips)
 | 
						|
        else:
 | 
						|
            Tooltip(self.btn_tr, _("Click to delete a Wireguard Tunnel\nSelect from the list!"), tips)
 | 
						|
 | 
						|
        # Button Export
 | 
						|
        self.btn_exp = ttk.Button(self.lb_frame_btn_lbox, image=self.exp_pic,
 | 
						|
                                  command=lambda: Tunnel.export(img_w, img_i, img_w2, img_i2, sl, pfit), padding=0)
 | 
						|
        self.btn_exp.grid(column=0, row=3, padx=15, pady=8)
 | 
						|
 | 
						|
        if self.l_box.size() == 0:
 | 
						|
            Tooltip(self.btn_exp, _("No Tunnels in List for Export"), tips)
 | 
						|
        else:
 | 
						|
            Tooltip(self.btn_exp, _("Click to export all\nWireguard Tunnel to Zipfile"), tips)
 | 
						|
 | 
						|
        # Label Entry
 | 
						|
        self.lb_rename = ttk.Entry(self.lb_frame4, width=20)
 | 
						|
        self.lb_rename.grid(column=2, row=0, padx=8, pady=10, sticky="ne")
 | 
						|
        self.lb_rename.insert(0, _("Max. 12 characters!"))
 | 
						|
        self.lb_rename.config(state="disable")
 | 
						|
 | 
						|
        if self.l_box.size() != 0:
 | 
						|
            Tooltip(self.lb_rename, _("To rename a tunnel, you need to\nselect a tunnel from the list"), tips)
 | 
						|
        else:
 | 
						|
            Tooltip(self.lb_rename, _("To rename a tunnel, at least one must be in the list"), tips)
 | 
						|
 | 
						|
        # Button Rename
 | 
						|
        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")
 | 
						|
 | 
						|
        # Check Buttons
 | 
						|
        self.selected_option = tk.IntVar()
 | 
						|
        self.autoconnect_var = tk.StringVar()
 | 
						|
        self.autoconnect_var.set(f"{self.auto_con}")
 | 
						|
 | 
						|
        # Frame for Labels, Entry and Button
 | 
						|
        self.autoconnect = ttk.Label(self.lb_frame3, textvariable=self.autoconnect_var, width=15)
 | 
						|
        self.autoconnect.config(font=("Ubuntu", 11))
 | 
						|
        self.autoconnect.grid(column=1, row=0, sticky="e", pady=19)
 | 
						|
        self.wg_autostart = ttk.Checkbutton(self.lb_frame3, text=_("Autoconnect on:"), variable=self.selected_option,
 | 
						|
                                            command=self.box_set)
 | 
						|
        self.wg_autostart.grid(column=0, row=0, pady=15, padx=15, sticky="nw")
 | 
						|
 | 
						|
        if self.l_box.size() >= 1 and len(self.l_box.curselection()) >= 1:
 | 
						|
            Tooltip(self.wg_autostart, _("To use the autostart, enable this Checkbox"), tips)
 | 
						|
 | 
						|
        if self.l_box.size() == 0:
 | 
						|
            Tooltip(self.wg_autostart, _("You must have at least one\ntunnel in the list,to use the autostart"), tips)
 | 
						|
 | 
						|
        else:
 | 
						|
 | 
						|
            Tooltip(self.wg_autostart, _("To use the autostart, a tunnel must be selected from the list"), tips)
 | 
						|
 | 
						|
        self.on_off()
 | 
						|
 | 
						|
    @staticmethod
 | 
						|
    def about() -> None:
 | 
						|
        """
 | 
						|
        a tk.Toplevel window
 | 
						|
        """
 | 
						|
        def link_btn() -> str | None:
 | 
						|
            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) -> None:
 | 
						|
        """
 | 
						|
        Set a light theme
 | 
						|
        """
 | 
						|
        if self.tk.call("ttk::style", "theme", "use") == "water-dark":
 | 
						|
            self.tk.call("set_theme", "light")
 | 
						|
            lines = Path(set_file).read_text(encoding="utf-8").splitlines(keepends=True)  # (keepends=True) = not changed
 | 
						|
            lines[3] = 'light\n' 
 | 
						|
            Path(set_file).write_text(''.join(lines), encoding="utf-8")
 | 
						|
            self.color_label()
 | 
						|
 | 
						|
    def theme_change_dark(self) -> None:
 | 
						|
        """
 | 
						|
        Set a dark theme
 | 
						|
        """
 | 
						|
        if not self.tk.call("ttk::style", "theme", "use") == "water-dark":
 | 
						|
            self.tk.call("set_theme", "dark")
 | 
						|
            lines = Path(set_file).read_text(encoding="utf-8").splitlines(keepends=True)
 | 
						|
            lines[3] = 'dark\n' 
 | 
						|
            Path(set_file).write_text(''.join(lines), encoding="utf-8")
 | 
						|
            self.color_label()
 | 
						|
 | 
						|
    @staticmethod
 | 
						|
    def update_setting(update_res) -> None:
 | 
						|
        """
 | 
						|
        write off or on in file
 | 
						|
        Args:
 | 
						|
            update_res (int): argument that is passed contains 0 or 1
 | 
						|
        """
 | 
						|
        if update_res == 1:
 | 
						|
            lines = Path(set_file).read_text(encoding="utf-8").splitlines(keepends=True)
 | 
						|
            lines[1] = 'off\n' 
 | 
						|
            Path(set_file).write_text(''.join(lines), encoding="utf-8")
 | 
						|
 | 
						|
        else:
 | 
						|
            lines = Path(set_file).read_text(encoding="utf-8").splitlines(keepends=True)
 | 
						|
            lines[1] = 'on\n' 
 | 
						|
            Path(set_file).write_text(''.join(lines), encoding="utf-8")
 | 
						|
 | 
						|
    @staticmethod
 | 
						|
    def tooltip(tip) -> None:
 | 
						|
        """
 | 
						|
        write True or False in a file
 | 
						|
        Args:
 | 
						|
            tip (bool): argument that is passed contains True or False
 | 
						|
        """
 | 
						|
        if tip:
 | 
						|
            lines = Path(set_file).read_text(encoding="utf-8").splitlines(keepends=True)
 | 
						|
            lines[5] = 'False\n' 
 | 
						|
            Path(set_file).write_text(''.join(lines), encoding="utf-8")
 | 
						|
 | 
						|
        else:
 | 
						|
            lines = Path(set_file).read_text(encoding="utf-8").splitlines(keepends=True)
 | 
						|
            lines[5] = 'True\n' 
 | 
						|
            Path(set_file).write_text(''.join(lines), encoding="utf-8")
 | 
						|
 | 
						|
    def enable_check_box(self, _) -> None:
 | 
						|
        """
 | 
						|
        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) -> None:
 | 
						|
        """
 | 
						|
        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(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:
 | 
						|
        """
 | 
						|
        method to rename a tunnel
 | 
						|
        """
 | 
						|
        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) -> None:
 | 
						|
        """
 | 
						|
        validity check of wireguard config files
 | 
						|
        """
 | 
						|
        Create.dir_and_files()
 | 
						|
 | 
						|
        try:
 | 
						|
            filepath = filedialog.askopenfilename(initialdir=f"{Path.home()}", title=_("Select Wireguard config File"),
 | 
						|
                                                  filetypes=[(_("WG config files"), "*.conf")])
 | 
						|
 | 
						|
            with open(filepath, "r", encoding="utf-8") as file:
 | 
						|
                read = file.read()
 | 
						|
            path_split = filepath.split("/")
 | 
						|
            path_split1 = path_split[-1]
 | 
						|
 | 
						|
            if "PrivateKey = " in read and "PublicKey = " in read and "Endpoint =" in read:
 | 
						|
                with open(filepath, "r", encoding="utf-8") as file:
 | 
						|
                    key = Tunnel.con_to_dict(file)
 | 
						|
                    pre_key = key[3]
 | 
						|
                    if len(pre_key) != 0:
 | 
						|
                        p_key = keys.read_text(encoding="utf-8")
 | 
						|
                        if pre_key in p_key or f"{pre_key}\n" in p_key:
 | 
						|
 | 
						|
                            msg_t = _("Tunnel already available!\nPlease use another file for import")
 | 
						|
                            LxTools.msg_window(img_w2, img_i2, ie, msg_t)
 | 
						|
 | 
						|
                        else:
 | 
						|
 | 
						|
                            with open(keys, "a", encoding="utf-8") as keyfile:
 | 
						|
                                keyfile.write(f"{pre_key}\r")
 | 
						|
                                if len(path_split1) > 17:
 | 
						|
                                    p1 = shutil.copy(filepath, "/tmp/tlecdcwg/")
 | 
						|
                                    path_split = path_split1[len(path_split1) - 17:]
 | 
						|
                                    os.rename(p1, f"/tmp/tlecdcwg/{path_split}")
 | 
						|
                                    new_conf = f"/tmp/tlecdcwg/{path_split}"
 | 
						|
                                    if self.a != "":
 | 
						|
                                        check_call(["nmcli", "connection", "down", self.a])
 | 
						|
                                        self.reset_fields()
 | 
						|
 | 
						|
                                    subprocess.check_output(["nmcli", "connection", "import", "type",
 | 
						|
                                                                "wireguard", "file", new_conf], text=True)
 | 
						|
 | 
						|
                                    Create.encrypt()
 | 
						|
 | 
						|
                                else:
 | 
						|
                                    shutil.copy(filepath, "/tmp/tlecdcwg/")
 | 
						|
                                    if self.a != "":
 | 
						|
                                        check_call(["nmcli", "connection", "down", self.a])
 | 
						|
                                        self.reset_fields()
 | 
						|
 | 
						|
                                    subprocess.check_output(["nmcli", "connection", "import", "type",
 | 
						|
                                                                "wireguard", "file", filepath], text=True)
 | 
						|
 | 
						|
                                    Create.encrypt()
 | 
						|
 | 
						|
                                self.str_var.set("")
 | 
						|
                                self.a = Tunnel.active()
 | 
						|
                                self.l_box.insert(0, self.a)
 | 
						|
                                self.wg_autostart.configure(state="normal")
 | 
						|
                                self.l_box.selection_clear(0, tk.END)
 | 
						|
                                self.l_box.update()
 | 
						|
                                self.l_box.selection_set(0)
 | 
						|
 | 
						|
                                Tooltip(self.wg_autostart, _("To use the autostart, enable this Checkbox"), tips)
 | 
						|
 | 
						|
                                Tooltip(self.btn_tr, _("Click to delete a Wireguard Tunnel\nSelect from the list!")
 | 
						|
                                        , tips,)
 | 
						|
 | 
						|
                                Tooltip(self.btn_exp, _("         Click to export all\nWireguard Tunnel to Zipfile")
 | 
						|
                                        , tips)
 | 
						|
 | 
						|
                                Tooltip(self.btn_rename, _("To rename a tunnel, you need to\nselect a tunnel from"
 | 
						|
                                                            " the list"), tips)
 | 
						|
 | 
						|
                                self.lb_rename.insert(0, "Max. 12 characters!")
 | 
						|
                                self.str_var = tk.StringVar()
 | 
						|
                                self.str_var.set(self.a)
 | 
						|
                                self.color_label()
 | 
						|
                                self.stop()
 | 
						|
                                data = self.handle_tunnel_data(self.a)
 | 
						|
                                check_call(["nmcli", "con", "mod", self.a, "connection.autoconnect", "no"])
 | 
						|
 | 
						|
            if ("PrivateKey = " in read) and ("Endpoint = " in read):
 | 
						|
                pass
 | 
						|
            else:
 | 
						|
 | 
						|
                msg_t = _("Oh... no valid Wireguard File!\nPlease select a valid Wireguard File")
 | 
						|
                LxTools.msg_window(img_w2, img_i2, ie, msg_t)
 | 
						|
 | 
						|
        except EOFError as e:
 | 
						|
            print(e)
 | 
						|
        except TypeError:
 | 
						|
            print("File import: abort by user...")
 | 
						|
        except FileNotFoundError:
 | 
						|
            print("File import: abort by user...")
 | 
						|
        except subprocess.CalledProcessError:
 | 
						|
            print("Tunnel exist!")
 | 
						|
 | 
						|
    def handle_tunnel_data(self, tunnel_name: str) -> tuple[str, str, str, str | None]:
 | 
						|
        """_summary_
 | 
						|
 | 
						|
        Args:
 | 
						|
            tunnel_name (str): name of a tunnel
 | 
						|
 | 
						|
        Returns:
 | 
						|
            tuple[str, str]: tuple with tunnel data
 | 
						|
        """
 | 
						|
        wg_read = f"/tmp/tlecdcwg/{tunnel_name}.conf"
 | 
						|
        with open(wg_read, "r", encoding="utf-8") as file:
 | 
						|
            data = Tunnel.con_to_dict(file)
 | 
						|
            self.init_and_report(data)
 | 
						|
            self.show_data()
 | 
						|
            return data
 | 
						|
 | 
						|
    def box_set(self) -> None:
 | 
						|
        """
 | 
						|
        This Method will display the autostarted label which
 | 
						|
        Tunnel is automatically started regardless of the active tunnel.
 | 
						|
        The selected tunnel is written into a file to read it after the start of the system.
 | 
						|
        """
 | 
						|
        try:
 | 
						|
            select_tunnel = self.l_box.curselection()
 | 
						|
            select_tl = self.l_box.get(select_tunnel[0])
 | 
						|
 | 
						|
            if self.selected_option.get() == 0:
 | 
						|
                lines = Path(set_file).read_text(encoding="utf-8").splitlines(keepends=True)
 | 
						|
                lines[7] = 'off\n' 
 | 
						|
                Path(set_file).write_text(''.join(lines), encoding="utf-8")
 | 
						|
 | 
						|
                tl = Tunnel.list()
 | 
						|
 | 
						|
                if len(tl) == 0:
 | 
						|
                    self.wg_autostart.configure(state="disabled")
 | 
						|
 | 
						|
            if self.selected_option.get() >= 1:
 | 
						|
                lines = Path(set_file).read_text(encoding="utf-8").splitlines(keepends=True)
 | 
						|
                lines[7] = select_tl
 | 
						|
                Path(set_file).write_text(''.join(lines), encoding="utf-8")
 | 
						|
 | 
						|
        except IndexError:
 | 
						|
            self.selected_option.set(1)
 | 
						|
 | 
						|
        self.on_off()
 | 
						|
 | 
						|
    def on_off(self) -> None:
 | 
						|
        """
 | 
						|
        Here it is checked whether the path to the file is there, if not, it is created.
 | 
						|
        Set (on), the selected tunnel is displayed in the label.
 | 
						|
        At (off) the label is first emptied then filled with No Autoconnect
 | 
						|
        """
 | 
						|
        lines = Path(set_file).read_text(encoding="utf-8").splitlines(keepends=True)
 | 
						|
 | 
						|
        if lines[7] != "off\n":
 | 
						|
            print(f"{lines[7]} starts automatically when the system starts.")
 | 
						|
            self.selected_option.set(1)
 | 
						|
            self.autoconnect_var.set("")
 | 
						|
            self.auto_con = lines[7]
 | 
						|
 | 
						|
        else:
 | 
						|
            self.selected_option.set(0)
 | 
						|
            self.auto_con = _("no Autoconnect")
 | 
						|
            print("Autostart disabled.")
 | 
						|
        self.autoconnect_var.set("")
 | 
						|
        self.autoconnect_var = tk.StringVar()
 | 
						|
        self.autoconnect_var.set(self.auto_con)
 | 
						|
 | 
						|
        self.autoconnect = ttk.Label(self.lb_frame3, textvariable=self.autoconnect_var, foreground="#0071ff", width=15)
 | 
						|
        self.autoconnect.config(font=("Ubuntu", 11))
 | 
						|
        self.autoconnect.grid(column=1, row=0, sticky="e", pady=19)
 | 
						|
 | 
						|
    def init_and_report(self, data=None) -> None:
 | 
						|
        """
 | 
						|
        Displays the value address, DNS and peer in the labels
 | 
						|
        or empty it again
 | 
						|
        """
 | 
						|
        # Address Label
 | 
						|
        self.add = tk.StringVar()
 | 
						|
        self.add.set(f"{_("Address:    ")}{data[0]}")
 | 
						|
        self.DNS = tk.StringVar()
 | 
						|
        self.DNS.set(f"       DNS:   {data[1]}")
 | 
						|
        self.enp = tk.StringVar()
 | 
						|
        self.enp.set(f"{_("Endpoint:    ")}{data[2]}")
 | 
						|
 | 
						|
    def reset_fields(self) -> None:
 | 
						|
        """
 | 
						|
        reset data from labels
 | 
						|
        """
 | 
						|
        fields = [self.add, self.DNS, self.enp]
 | 
						|
        for field in fields:
 | 
						|
            field.set("")
 | 
						|
 | 
						|
    def show_data(self) -> None:
 | 
						|
        """
 | 
						|
        shows data in the label
 | 
						|
        """
 | 
						|
        # Address Label
 | 
						|
        self.address = ttk.Label(self.lb_frame, textvariable=self.add, foreground="#0071ff")
 | 
						|
        self.address.grid(column=0, row=5, sticky="w", padx=10, pady=6)
 | 
						|
        self.address.config(font=("Ubuntu", 9))
 | 
						|
 | 
						|
        # DNS Label
 | 
						|
        self.dns = ttk.Label(self.lb_frame, textvariable=self.DNS, foreground="#0071ff")
 | 
						|
        self.dns.grid(column=0, row=7, sticky="w", padx=10, pady=6)
 | 
						|
        self.dns.config(font=("Ubuntu", 9))
 | 
						|
 | 
						|
        # Endpoint Label
 | 
						|
        self.endpoint = ttk.Label(self.lb_frame2, textvariable=self.enp, foreground="#0071ff")
 | 
						|
        self.endpoint.grid(column=0, row=8, sticky="w", padx=10, pady=20)
 | 
						|
        self.endpoint.config(font=("Ubuntu", 9))
 | 
						|
 | 
						|
    def stop(self) -> None:
 | 
						|
        """
 | 
						|
        Stop Button
 | 
						|
        """
 | 
						|
        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)
 | 
						|
 | 
						|
    def start(self) -> None:
 | 
						|
        """
 | 
						|
        Start Button
 | 
						|
        """
 | 
						|
        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()
 | 
						|
        if len(tl) == 0:
 | 
						|
            Tooltip(self.btn_stst, _("No tunnels to start in the list"), tips)
 | 
						|
        else:
 | 
						|
            Tooltip(self.btn_stst, _("Click to start selected Wireguard Tunnel"), tips)
 | 
						|
 | 
						|
    def color_label(self) -> None:
 | 
						|
        """
 | 
						|
        View activ Tunnel in the color green or yellow
 | 
						|
        """
 | 
						|
        lines = set_file.read_text()
 | 
						|
        if "light\n" in lines:
 | 
						|
            self.lb_tunnel = ttk.Label(self, textvariable=self.str_var, foreground="green")
 | 
						|
 | 
						|
        else:
 | 
						|
            self.lb_tunnel = ttk.Label(self, textvariable=self.str_var, foreground="yellow")
 | 
						|
 | 
						|
        self.lb_tunnel.config(font=("Ubuntu", 11, "bold"))
 | 
						|
        self.lb_tunnel.grid(column=2, padx=10, row=1)
 | 
						|
 | 
						|
    def wg_switch(self, event=None) -> None:
 | 
						|
        """
 | 
						|
        Deals with switching the VPN connection
 | 
						|
        """
 | 
						|
        try:
 | 
						|
            if self.a == "":
 | 
						|
                self.select_tunnel = self.l_box.curselection()
 | 
						|
                select_tl = self.l_box.get(self.select_tunnel[0])
 | 
						|
                self.handle_connection_state("start", select_tl)
 | 
						|
 | 
						|
            else:
 | 
						|
                
 | 
						|
                data = self.handle_tunnel_data(self.a)
 | 
						|
                if data:
 | 
						|
 | 
						|
                    self.handle_connection_state("stop")
 | 
						|
 | 
						|
        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 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 a tunnel for a 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()
 | 
						|
    """
 | 
						|
    the hidden files are hidden in Filedialog
 | 
						|
    """
 | 
						|
    try:
 | 
						|
        window.tk.call("tk_getOpenFile", "-foobarbaz")
 | 
						|
    except TclError:
 | 
						|
        pass
 | 
						|
    window.tk.call("set", "::tk::dialog::file::showHiddenBtn", "0")
 | 
						|
    window.tk.call("set", "::tk::dialog::file::showHiddenVar", "0")
 | 
						|
    window.mainloop()
 | 
						|
 | 
						|
LxTools.clean_files(folder_path, user_file)
 | 
						|
sys.exit(0)
 |