""" Remote desktop launchers — RDP and VNC via external clients. """ import os import platform import subprocess import tempfile from core.logger import log class RemoteDesktopLauncher: """Launch external RDP/VNC clients for remote desktop connections.""" @staticmethod def launch_rdp(server: dict) -> str: """Generate a .rdp temp file and launch the system RDP client. Returns: Status message string. """ hostname = server["ip"] port = server.get("port", 3389) user = server.get("user", "Administrator") rdp_content = ( f"full address:s:{hostname}:{port}\r\n" f"username:s:{user}\r\n" "prompt for credentials:i:1\r\n" "screen mode id:i:2\r\n" "desktopwidth:i:1920\r\n" "desktopheight:i:1080\r\n" "session bpp:i:32\r\n" "compression:i:1\r\n" "disable wallpaper:i:0\r\n" "allow font smoothing:i:1\r\n" "networkautodetect:i:1\r\n" "bandwidthautodetect:i:1\r\n" ) alias = server.get("alias", "remote") rdp_file = os.path.join(tempfile.gettempdir(), f"sm_{alias}.rdp") with open(rdp_file, "w", encoding="utf-8") as f: f.write(rdp_content) log.info(f"RDP file created: {rdp_file}") system = platform.system() if system == "Windows": os.startfile(rdp_file) return f"RDP launched via mstsc for {alias}" elif system == "Linux": try: subprocess.Popen( ["xfreerdp", f"/v:{hostname}:{port}", f"/u:{user}", "/dynamic-resolution"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) return f"RDP launched via xfreerdp for {alias}" except FileNotFoundError: log.warning("xfreerdp not found, trying rdesktop") subprocess.Popen( ["rdesktop", f"{hostname}:{port}", "-u", user], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) return f"RDP launched via rdesktop for {alias}" elif system == "Darwin": subprocess.Popen(["open", rdp_file]) return f"RDP launched via macOS for {alias}" else: return f"Unsupported platform: {system}. RDP file saved to {rdp_file}" @staticmethod def launch_vnc(server: dict) -> str: """Launch a VNC viewer for the given server. Returns: Status message string. """ hostname = server["ip"] port = server.get("port", 5900) alias = server.get("alias", "remote") target = f"{hostname}:{port}" log.info(f"VNC launching for {alias} at {target}") system = platform.system() if system == "Windows": # Try common VNC viewer paths viewers = [ r"C:\Program Files\TightVNC\tvnviewer.exe", r"C:\Program Files (x86)\TightVNC\tvnviewer.exe", r"C:\Program Files\RealVNC\VNC Viewer\vncviewer.exe", r"C:\Program Files (x86)\RealVNC\VNC Viewer\vncviewer.exe", ] for viewer in viewers: if os.path.exists(viewer): subprocess.Popen([viewer, target]) return f"VNC launched via {os.path.basename(viewer)} for {alias}" # Fallback: try vncviewer in PATH try: subprocess.Popen(["vncviewer", target]) return f"VNC launched via vncviewer for {alias}" except FileNotFoundError: return "No VNC viewer found. Install TightVNC or RealVNC Viewer." elif system == "Linux": for cmd in ["vncviewer", "xtigervncviewer", "remmina"]: try: args = [cmd, target] if cmd != "remmina" else [cmd, f"vnc://{target}"] subprocess.Popen(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) return f"VNC launched via {cmd} for {alias}" except FileNotFoundError: continue return "No VNC viewer found. Install tigervnc-viewer or remmina." elif system == "Darwin": subprocess.Popen(["open", f"vnc://{target}"]) return f"VNC launched via macOS Screen Sharing for {alias}" else: return f"Unsupported platform: {system}"