04-06-2025_large_update #35
							
								
								
									
										107
									
								
								common_tools.py
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								common_tools.py
									
									
									
									
									
								
							@@ -6,7 +6,7 @@ import signal
 | 
			
		||||
import base64
 | 
			
		||||
import secrets
 | 
			
		||||
import subprocess
 | 
			
		||||
from subprocess import CompletedProcess, run
 | 
			
		||||
from subprocess import CompletedProcess
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
import tkinter as tk
 | 
			
		||||
@@ -30,7 +30,7 @@ class CryptoUtil:
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def decrypt() -> str:
 | 
			
		||||
    def decrypt() -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Starts SSL dencrypt
 | 
			
		||||
        """
 | 
			
		||||
@@ -54,7 +54,7 @@ class CryptoUtil:
 | 
			
		||||
            print(f"Error process decrypt: Code {process.returncode}")
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def encrypt() -> str:
 | 
			
		||||
    def encrypt() -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Starts SSL encryption
 | 
			
		||||
        """
 | 
			
		||||
@@ -80,7 +80,7 @@ class CryptoUtil:
 | 
			
		||||
        Checks if the private key already exists in the system using an external script.
 | 
			
		||||
        Returns True only if the full key is found exactly (no partial match).
 | 
			
		||||
        """
 | 
			
		||||
        process: CompletedProcess[bool] = run(
 | 
			
		||||
        process: CompletedProcess[bool] = subprocess.run(
 | 
			
		||||
            ["pkexec", "/usr/local/bin/match_found.py", key],
 | 
			
		||||
            capture_output=True,
 | 
			
		||||
            text=True,
 | 
			
		||||
@@ -121,7 +121,7 @@ class CryptoUtil:
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LxTools(tk.Tk):
 | 
			
		||||
class LxTools:
 | 
			
		||||
    """
 | 
			
		||||
    Class LinuxTools methods that can also be used for other apps
 | 
			
		||||
    """
 | 
			
		||||
@@ -183,7 +183,7 @@ class LxTools(tk.Tk):
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
            if primary_info:
 | 
			
		||||
                # Parse the geometry: WIDTHxHEIGHT+X+Y
 | 
			
		||||
                # Parse the geometry: WIDTH x HEIGHT+X+Y
 | 
			
		||||
                geometry = primary_info.split("+")
 | 
			
		||||
                dimensions = geometry[0].split("x")
 | 
			
		||||
                primary_width = int(dimensions[0])
 | 
			
		||||
@@ -217,31 +217,6 @@ class LxTools(tk.Tk):
 | 
			
		||||
        y = (screen_height - height) // 2
 | 
			
		||||
        window.geometry(f"{width}x{height}+{x}+{y}")
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_file_name(path: Path, i: int = 5) -> List[str]:
 | 
			
		||||
        """
 | 
			
		||||
        Recursively searches the specified path for files and returns a list of filenames,
 | 
			
		||||
        with the last 'i' characters of each filename removed.
 | 
			
		||||
 | 
			
		||||
        This method is useful for obtaining filenames without specific file extensions,
 | 
			
		||||
        e.g., to remove '.conf' from Wireguard configuration files.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            path (Path): The directory path to search
 | 
			
		||||
            i (int, optional): Number of characters to remove from the end of each filename.
 | 
			
		||||
                            Default is 5, which typically corresponds to the length of '.conf'.
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            List[str]: A list of filenames without the last 'i' characters
 | 
			
		||||
 | 
			
		||||
        Example:
 | 
			
		||||
            If path contains files like 'tunnel1.conf', 'tunnel2.conf' and i=5,
 | 
			
		||||
            the method returns ['tunnel1', 'tunnel2'].
 | 
			
		||||
        """
 | 
			
		||||
        lists_file = list(path.rglob("*"))
 | 
			
		||||
        lists_file = [conf_file.name[:-i] for conf_file in lists_file]
 | 
			
		||||
        return lists_file
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_username() -> str:
 | 
			
		||||
        """
 | 
			
		||||
@@ -266,11 +241,42 @@ class LxTools(tk.Tk):
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def clean_files(TEMP_DIR: Path = None, file: Path = None) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        method that can be added after need to delete a folder and a file when quitting.
 | 
			
		||||
        Deletes temporary files and directories for cleanup when exiting the application.
 | 
			
		||||
 | 
			
		||||
        This method safely removes an optional directory defined by `AppConfig.TEMP_DIR`
 | 
			
		||||
        and a single file to free up resources at the end of the program's execution.
 | 
			
		||||
        All operations are performed securely, and errors such as `FileNotFoundError`
 | 
			
		||||
        are ignored if the target files or directories do not exist.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            :param file: default None
 | 
			
		||||
            :param AppConfig.TEMP_DIR: default None
 | 
			
		||||
            TEMP_DIR (Path, optional): Path to the temporary directory that should be deleted.
 | 
			
		||||
                If `None`, the value of `AppConfig.TEMP_DIR` is used.
 | 
			
		||||
            file (Path, optional): Path to the file that should be deleted.
 | 
			
		||||
                If `None`, no additional file will be deleted.
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            None: The method does not return any value.
 | 
			
		||||
 | 
			
		||||
        Examples:
 | 
			
		||||
            - Without parameters:
 | 
			
		||||
            ```python
 | 
			
		||||
            Tooltip.clean_files()
 | 
			
		||||
            ```
 | 
			
		||||
            Deletes the temporary directory defined in the configuration (`AppConfig.TEMP_DIR`).
 | 
			
		||||
 | 
			
		||||
            - With an explicit file path:
 | 
			
		||||
            ```python
 | 
			
		||||
            Tooltip.clean_files(file=Path("temp/file.txt"))
 | 
			
		||||
            ```
 | 
			
		||||
            Deletes the file `file.txt`, if it exists, and ignores errors.
 | 
			
		||||
 | 
			
		||||
            - Both parameters:
 | 
			
		||||
            ```python
 | 
			
		||||
            Tooltip.clean(TEMP_DIR=Path("/tmp/data"), file=Path("log.txt"))
 | 
			
		||||
            ```
 | 
			
		||||
            Deletes the directory `/tmp/data` and the file `log.txt`, if they exist.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        if AppConfig.TEMP_DIR is not None:
 | 
			
		||||
            shutil.rmtree(AppConfig.TEMP_DIR)
 | 
			
		||||
        try:
 | 
			
		||||
@@ -597,8 +603,20 @@ class Tunnel:
 | 
			
		||||
# ConfigManager with caching
 | 
			
		||||
class ConfigManager:
 | 
			
		||||
    """
 | 
			
		||||
    Universal class for managing configuration files with caching.
 | 
			
		||||
    Can be reused in different projects.
 | 
			
		||||
    Universal class for managing configuration files with caching support.
 | 
			
		||||
 | 
			
		||||
    This class provides a general solution to load, save, and manage configuration
 | 
			
		||||
    files across different projects. It uses a caching system to optimize access efficiency.
 | 
			
		||||
    The `init()` method initializes the configuration file path, while `load()` and `save()`
 | 
			
		||||
    synchronize data between the file and internal memory structures.
 | 
			
		||||
 | 
			
		||||
    Key Features:
 | 
			
		||||
    - Caching to minimize I/O operations.
 | 
			
		||||
    - Default values for missing or corrupted configuration files.
 | 
			
		||||
    - Reusability across different projects and use cases.
 | 
			
		||||
 | 
			
		||||
    The class is designed for central application configuration management, working closely
 | 
			
		||||
    with `ThemeManager` to dynamically manage themes or other settings.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    _config = None
 | 
			
		||||
@@ -664,6 +682,23 @@ class ConfigManager:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ThemeManager:
 | 
			
		||||
    """
 | 
			
		||||
    Class for central theme management and UI customization.
 | 
			
		||||
 | 
			
		||||
    This static class allows dynamic adjustment of the application's appearance.
 | 
			
		||||
    The method `change_theme()` updates the current theme and saves
 | 
			
		||||
    the selection in the configuration file via `ConfigManager`.
 | 
			
		||||
    It ensures a consistent visual design across the entire project.
 | 
			
		||||
 | 
			
		||||
    Key Features:
 | 
			
		||||
    - Central control over themes.
 | 
			
		||||
    - Automatic saving of theme settings to the configuration file.
 | 
			
		||||
    - Tight integration with `ConfigManager` for persistent storage of preferences.
 | 
			
		||||
 | 
			
		||||
    The class is designed to apply themes consistently throughout the application,
 | 
			
		||||
    ensuring that changes are traceable and uniform across all parts of the project.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def change_theme(root, theme_in_use, theme_name=None):
 | 
			
		||||
        """Change application theme centrally"""
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								wirepy.py
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								wirepy.py
									
									
									
									
									
								
							@@ -244,7 +244,7 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
        self.tl = Tunnel.parse_files_to_dictionary(directory=AppConfig.TEMP_DIR)
 | 
			
		||||
        LxTools.clean_files(AppConfig.TEMP_DIR, file=None)
 | 
			
		||||
        AppConfig.ensure_directories()
 | 
			
		||||
        # self.tl = LxTools.get_file_name(AppConfig.TEMP_DIR)
 | 
			
		||||
 | 
			
		||||
        for tunnels, values in self.tl.items():
 | 
			
		||||
            self.l_box.insert("end", tunnels)
 | 
			
		||||
            self.l_box.update()
 | 
			
		||||
@@ -475,7 +475,7 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
        a tk.Toplevel window
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        def link_btn() -> str | None:
 | 
			
		||||
        def link_btn() -> None:
 | 
			
		||||
            webbrowser.open("https://git.ilunix.de/punix/Wire-Py")
 | 
			
		||||
 | 
			
		||||
        msg_t = _(
 | 
			
		||||
@@ -583,8 +583,7 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
        )
 | 
			
		||||
        self.btn_stst.grid(column=0, row=0, padx=5, pady=8)
 | 
			
		||||
 | 
			
		||||
        tl = LxTools.get_file_name(AppConfig.TEMP_DIR)
 | 
			
		||||
        if len(self.tl) == 0:
 | 
			
		||||
        if self.l_box.size() == 0:
 | 
			
		||||
            Tooltip(self.btn_stst, Msg.TTIP["empty_list"], self.tooltip_state)
 | 
			
		||||
        else:
 | 
			
		||||
            Tooltip(self.btn_stst, Msg.TTIP["start_tl"], self.tooltip_state)
 | 
			
		||||
@@ -908,9 +907,7 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
            if self.selected_option.get() == 0:
 | 
			
		||||
                ConfigManager.set("autostart", "off")
 | 
			
		||||
 | 
			
		||||
                tl = [f"{file}" for file in AppConfig.CONFIG_DIR.glob("*.dat")]
 | 
			
		||||
 | 
			
		||||
                if len(tl) == 0:
 | 
			
		||||
                if self.l_box.size() == 0:
 | 
			
		||||
                    self.wg_autostart.configure(state="disabled")
 | 
			
		||||
 | 
			
		||||
            if self.selected_option.get() >= 1:
 | 
			
		||||
@@ -923,9 +920,12 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
 | 
			
		||||
    def tl_rename(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        method to rename a tunnel
 | 
			
		||||
        Method to rename a tunnel. Validates input for length,
 | 
			
		||||
        special characters, and duplicate names,
 | 
			
		||||
        performs the renaming via `nmcli` if valid, updates
 | 
			
		||||
        the configuration file in the directory,
 | 
			
		||||
        and adjusts UI elements such as listboxes and labels.
 | 
			
		||||
        """
 | 
			
		||||
        name_of_file = LxTools.get_file_name(AppConfig.TEMP_DIR)
 | 
			
		||||
        special_characters = ["\\", "/", "{", "}", " "]
 | 
			
		||||
 | 
			
		||||
        if len(self.lb_rename.get()) > 12:
 | 
			
		||||
@@ -955,7 +955,9 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
                Msg.STR["false_signs"],
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        elif self.lb_rename.get() in name_of_file:
 | 
			
		||||
        elif self.lb_rename.get() in [
 | 
			
		||||
            file.stem for file in AppConfig.CONFIG_DIR.glob("*.dat")
 | 
			
		||||
        ]:
 | 
			
		||||
 | 
			
		||||
            LxTools.msg_window(
 | 
			
		||||
                AppConfig.IMAGE_PATHS["icon_info"],
 | 
			
		||||
@@ -1019,7 +1021,9 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
                print(e)
 | 
			
		||||
 | 
			
		||||
    def handle_tunnel_data(self, active=None, data=None) -> None:
 | 
			
		||||
 | 
			
		||||
        """Processes tunnel data from an active connection and updates
 | 
			
		||||
        UI elements like labels with information about address, DNS, and endpoint.
 | 
			
		||||
        """
 | 
			
		||||
        tunnel = active
 | 
			
		||||
        values = data[tunnel]
 | 
			
		||||
        # Address Label
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,24 @@ from typing import Dict, Any
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AppConfig:
 | 
			
		||||
    """Central configuration class for Wire-Py application"""
 | 
			
		||||
    """Central configuration and system setup manager for the Wire-Py application.
 | 
			
		||||
 | 
			
		||||
    This class serves as a singleton-like container for all global configuration data,
 | 
			
		||||
    including paths, UI settings, localization, versioning, and system-specific resources.
 | 
			
		||||
    It ensures that required directories, files, and services are created and configured
 | 
			
		||||
    before the application starts. Additionally, it provides tools for managing translations,
 | 
			
		||||
    default settings, and autostart functionality to maintain a consistent user experience.
 | 
			
		||||
 | 
			
		||||
    Key Responsibilities:
 | 
			
		||||
    - Centralizes all configuration values (paths, UI preferences, localization).
 | 
			
		||||
    - Ensures required directories and files exist on startup.
 | 
			
		||||
    - Handles translation setup via `gettext` for multilingual support.
 | 
			
		||||
    - Manages default settings file generation.
 | 
			
		||||
    - Configures autostart services using systemd for user-specific launch behavior.
 | 
			
		||||
 | 
			
		||||
    This class is used globally across the application to access configuration data
 | 
			
		||||
    consistently and perform system-level setup tasks.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    # Localization
 | 
			
		||||
    APP_NAME: str = "wirepy"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user