import base64 import json import os import subprocess import sys from .I18N import _ # Na Windowsie używamy DPAPI if sys.platform.startswith("win"): try: import win32crypt import winreg except ImportError: win32crypt = None # Upewnij się, że masz zainstalowany pywin32 winreg = None # Upewnij się, że masz zainstalowany pywin32 def get_browser_paths_windows(): """Returns a dictionary of browsers and their executable paths from Windows registry and Start Menu.""" browsers = {"Default": None} # "Default" for default system browser # Check the registry for installed browsers registry_paths = [ r"SOFTWARE\Clients\StartMenuInternet", # 64-bit Windows r"SOFTWARE\WOW6432Node\Clients\StartMenuInternet", # 32-bit applications ] for reg_path in registry_paths: try: with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, reg_path) as key: for i in range(winreg.QueryInfoKey(key)[0]): # Iterate over subkeys browser_name = winreg.EnumKey(key, i) try: browser_key_path = os.path.join( reg_path, browser_name, r"shell\open\command" ) with winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, browser_key_path ) as subkey: command, _ = winreg.QueryValueEx(subkey, None) browsers[browser_name] = command.strip( '"' ) # Clean command string except FileNotFoundError: pass # Skip if no command found except FileNotFoundError: pass # Registry path not found, continue return browsers def get_browsers_linux(): """Detects installed browsers on Linux by checking available executables.""" browsers = {"Default": None} browser_names = [ "firefox", "google-chrome", "chromium", "opera", "brave", "vivaldi", ] for browser in browser_names: if ( subprocess.run( ["which", browser], stdout=subprocess.PIPE, stderr=subprocess.PIPE ).returncode == 0 ): browsers[browser] = browser return browsers def detect_installed_browsers(): """Detects available browsers depending on the OS.""" if sys.platform == "win32" and winreg: # Windows and winreg is available browsers = get_browser_paths_windows() elif sys.platform.startswith("linux"): # Linux browsers = get_browsers_linux() return browsers # --- Funkcje pomocnicze do szyfrowania/odszyfrowania hasła na Windowsie --- def encrypt_password(password): """Szyfruje hasło przy użyciu DPAPI i zwraca zakodowaną base64 postać.""" if win32crypt is None: return password # jeśli brak win32crypt, zwróć hasło w postaci jawnej blob = win32crypt.CryptProtectData( password.encode("utf-8"), None, None, None, None, 0 ) return base64.b64encode(blob).decode("utf-8") def decrypt_password(enc_password): """Odszyfrowuje hasło zapisane w formacie base64 przy użyciu DPAPI.""" if win32crypt is None: return enc_password enc_data = base64.b64decode(enc_password) data = win32crypt.CryptUnprotectData(enc_data, None, None, None, 0) return data[1].decode("utf-8") class Settings: def __init__(self): # Ustawienia domyślne self.username = "" self.password = "" self.base_url = "http://192.168.1.11:8001" self.default_tags = "artist:kapitan meta:ai-generated" self.cache_expiry = 604800 # 7 dni w sekundach self.browser = "" self.i18n = _ self.installed_browsers = detect_installed_browsers() self.load_settings() self.installed_browsers_reverse = { v: k for k, v in self.installed_browsers.items() } def get_settings_path(self): """Ustala ścieżkę do pliku ustawień w zależności od systemu.""" if sys.platform.startswith("win"): base_dir = os.path.join(os.environ.get("APPDATA", ""), "Kapitanbooru") else: base_dir = os.path.expanduser("~/.kapitanbooru") if not os.path.exists(base_dir): os.makedirs(base_dir) return os.path.join(base_dir, "settings.json") def load_settings(self): """Ładuje ustawienia z pliku, jeżeli plik istnieje.""" # Ustawienia domyślne self.username = "" self.password = "" self.base_url = "http://192.168.1.11:8001" self.default_tags = "artist:kapitan meta:ai-generated" self.cache_expiry = 604800 # 7 dni w sekundach self.browser = "" self.i18n.set_language("en") try: if os.path.exists(self.get_settings_path()): with open(self.get_settings_path(), "r", encoding="utf-8") as f: data = json.load(f) self.username = data.get("username", self.username) # Jeśli system Windows, odszyfruj hasło if sys.platform.startswith("win") and "password" in data: self.password = decrypt_password(data["password"]) else: self.password = data.get("password", self.password) self.base_url = data.get("base_url", self.base_url) self.default_tags = data.get("default_tags", self.default_tags) self.cache_expiry = data.get("cache_expiry", self.cache_expiry) self.browser = data.get("browser", self.browser) if self.browser not in self.installed_browsers: self.browser = "" self.i18n.set_language(data.get("language", "en")) except Exception as e: print(_("Błąd podczas ładowania ustawień:"), e) def save_settings(self): """Zapisuje ustawienia do pliku.""" data = { "username": self.username, "base_url": self.base_url, "default_tags": self.default_tags, "cache_expiry": self.cache_expiry, "browser": self.browser, "language": self.i18n.current_lang, } # Na Windowsie szyfrujemy hasło if sys.platform.startswith("win"): data["password"] = encrypt_password(self.password) else: data["password"] = self.password try: with open(self.get_settings_path(), "w", encoding="utf-8") as f: json.dump(data, f, indent=4) except Exception as e: print(_("Błąd podczas zapisywania ustawień:"), e)