Skip to content

Commit 9a321a2

Browse files
committed
fix(gtk3): fix critici e alti su connessioni remote
- log_viewer: command injection fix (shlex.quote su extra field) - cron_widget: race condition fix (threading.Lock + _write_pending) - winscp_widget: leak SSH/SFTP transfer connection in chiudi_processo - winscp_widget: idle_add throttling ogni 100ms (non piu' per-chunk) - winscp_widget: BUG CRITICO upload/download invertito nel ramo upload - sftp_editor: temp file cleanup su destroy handler - keepassxc_manager: subprocess leak fix con try/finally - rdp_widget: zombie processes (Popen->subprocess.run), resize throttling - tunnel_manager: override_color deprecato -> CSS provider - vnc_widget: dead code rimosso (if False), 'tigervnc' -> 'tigervncviewer'
1 parent df1c510 commit 9a321a2

8 files changed

Lines changed: 80 additions & 24 deletions

File tree

gtk3/cron_widget.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ def __init__(self, profilo: dict):
256256
self._profilo = profilo
257257
self._ssh: "paramiko.SSHClient | None" = None
258258
self._rows: list = []
259+
self._write_lock = threading.Lock()
260+
self._write_pending = False
259261

260262
self._build_ui()
261263
self.connect("destroy", lambda _: self._chiudi())
@@ -400,8 +402,10 @@ def _leggi_crontab(self):
400402
GLib.idle_add(self._set_status, f"✖ Lettura crontab: {e}")
401403

402404
def _scrivi_crontab(self):
403-
if not self._ssh:
404-
return
405+
with self._write_lock:
406+
if not self._ssh or self._write_pending:
407+
return
408+
self._write_pending = True
405409
try:
406410
text = _rows_to_crontab(self._rows)
407411
stdin, stdout, stderr = self._ssh.exec_command("crontab -", timeout=10)
@@ -415,6 +419,9 @@ def _scrivi_crontab(self):
415419
GLib.idle_add(self._set_status, "✔ Crontab salvato")
416420
except Exception as e:
417421
GLib.idle_add(self._set_status, f"✖ Salvataggio: {e}")
422+
finally:
423+
with self._write_lock:
424+
self._write_pending = False
418425

419426
def _chiudi(self):
420427
if self._ssh:

gtk3/keepassxc_manager.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,10 +459,10 @@ def __init__(self, parent=None):
459459

460460
if _HAS_NACL:
461461
def _test_conn():
462+
client = None
462463
try:
463464
client = KeePassXCClient()
464465
if client.exchange_keys():
465-
client.close()
466466
GLib.idle_add(lambda: lbl_status.set_markup(
467467
f"<span foreground='green'>✔ {t('keepass.connected')}</span>"
468468
))
@@ -475,5 +475,11 @@ def _test_conn():
475475
GLib.idle_add(lambda: lbl_status.set_markup(
476476
f"<span foreground='orange'>⚠ {t('keepass.error', e=msg)}</span>"
477477
))
478+
finally:
479+
if client is not None:
480+
try:
481+
client.close()
482+
except Exception:
483+
pass
478484

479485
threading.Thread(target=_test_conn, daemon=True).start()

gtk3/log_viewer.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import os
1313
import re
14+
import shlex
1415
import threading
1516

1617
import gi
@@ -166,9 +167,11 @@ def _get_cmd(self) -> str:
166167
tmpl = _SORGENTI[idx][0]
167168
extra = self._extra.get_text().strip()
168169
if "{svc}" in tmpl:
169-
return tmpl.format(svc=extra or "ssh")
170+
safe = shlex.quote(extra) if extra else "ssh"
171+
return tmpl.format(svc=safe)
170172
if "{file}" in tmpl:
171-
return tmpl.format(file=extra or "/var/log/syslog")
173+
safe = shlex.quote(extra) if extra else "/var/log/syslog"
174+
return tmpl.format(file=safe)
172175
return tmpl
173176

174177
# ------------------------------------------------------------------

gtk3/rdp_widget.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -432,10 +432,10 @@ def _step2():
432432
return False
433433

434434
def _step3():
435-
subprocess.Popen(["xdotool", "windowmove", wid_rdp, "0", "0"],
436-
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
437-
subprocess.Popen(["xdotool", "windowsize", wid_rdp, str(w), str(h)],
438-
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
435+
subprocess.run(["xdotool", "windowmove", wid_rdp, "0", "0"],
436+
timeout=2, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
437+
subprocess.run(["xdotool", "windowsize", wid_rdp, str(w), str(h)],
438+
timeout=2, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
439439
GLib.timeout_add(100, _step4)
440440
return False
441441

@@ -449,8 +449,8 @@ def _step4():
449449
return False
450450

451451
def _step5():
452-
subprocess.Popen(["xdotool", "windowfocus", wid_rdp],
453-
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
452+
subprocess.run(["xdotool", "windowfocus", wid_rdp],
453+
timeout=2, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
454454
self._reparented = True
455455
host = self._rdp_host
456456
self._info.set_text(f" ● RDP → {host}")
@@ -467,15 +467,26 @@ def do_size_allocate(self, allocation):
467467
Gtk.Box.do_size_allocate(self, allocation)
468468
if not self._reparented or not self._wid_rdp:
469469
return
470-
# Ottieni dimensioni del socket
471470
if hasattr(self, "_socket"):
472471
a = self._socket.get_allocation()
473472
w = max(a.width, 320)
474473
h = max(a.height, 240)
475-
subprocess.Popen(
476-
["xdotool", "windowsize", self._wid_rdp, str(w), str(h)],
477-
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
478-
)
474+
if hasattr(self, "_resize_pending") and self._resize_pending:
475+
return
476+
self._resize_pending = True
477+
478+
def _do_resize():
479+
self._resize_pending = False
480+
if self._reparented and self._wid_rdp and hasattr(self, "_socket"):
481+
a = self._socket.get_allocation()
482+
w2 = max(a.width, 320)
483+
h2 = max(a.height, 240)
484+
subprocess.run(
485+
["xdotool", "windowsize", self._wid_rdp, str(w2), str(h2)],
486+
timeout=2, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
487+
)
488+
return False
489+
GLib.timeout_add(150, _do_resize)
479490

480491
# ------------------------------------------------------------------
481492
# Monitor processo

gtk3/sftp_editor.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ def __init__(self, sftp, remote_path: str):
154154
self._ext_editor = _get_configured_editor()
155155

156156
self._build_ui()
157+
self.connect("destroy", lambda w: self._cleanup_tmp())
157158
threading.Thread(target=self._load, daemon=True).start()
158159

159160
# ------------------------------------------------------------------

gtk3/tunnel_manager.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,20 @@ def _init_ui(self):
354354
self.log_view = Gtk.TextView(buffer=self.log_buffer)
355355
self.log_view.set_editable(False)
356356
self.log_view.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
357-
self.log_view.override_background_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0.1, 0.1, 0.1, 1.0))
358-
self.log_view.override_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0.2, 1.0, 0.2, 1.0))
359-
self.log_view.override_font(Pango.FontDescription('Monospace 10'))
357+
self.log_view.set_monospace(True)
358+
359+
css = Gtk.CssProvider()
360+
css.load_from_data(b"""
361+
textview.log-console {
362+
background-color: #1a1a1a;
363+
color: #33cc33;
364+
font-family: monospace;
365+
font-size: 10pt;
366+
}
367+
""")
368+
ctx = self.log_view.get_style_context()
369+
ctx.add_provider(css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
370+
ctx.add_class("log-console")
360371

361372
scroll_log = Gtk.ScrolledWindow()
362373
scroll_log.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)

gtk3/vnc_widget.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
def _find_vnc_client() -> str | None:
3737
for c in ["vncviewer", "xtightvncviewer", "xvnc4viewer",
38-
"tigervnc", "xtigervncviewer", "krdc", "remmina"]:
38+
"tigervncviewer", "xtigervncviewer", "krdc", "remmina"]:
3939
if shutil.which(c):
4040
return c
4141
return None
@@ -235,7 +235,7 @@ def _applica_depth_quality(self):
235235
def _build_vt_menu(self) -> Gtk.Menu:
236236
menu = Gtk.Menu()
237237
for n in range(1, 8):
238-
key = getattr(GtkVnc, f'_KEY_F{n}', _KEY_F1 + n - 1) if False else (_KEY_F1 + n - 1)
238+
key = _KEY_F1 + n - 1
239239
mi = Gtk.MenuItem(label=f"Ctrl+Alt+F{n} (VT{n})")
240240
mi.connect("activate", lambda _, k=key: self._send_keys([_KEY_CTRL, _KEY_ALT, k]))
241241
menu.append(mi)

gtk3/winscp_widget.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,8 +1053,8 @@ def _trasferisci_chunk(self, job: TransferJob, idx: int):
10531053
try:
10541054
with open(job.dst, "wb") as local_f:
10551055
tx = 0
1056+
last_dl_update = 0.0
10561057
while True:
1057-
# Pausa: aspetta senza consumare CPU
10581058
while self._coda.is_in_pausa():
10591059
time.sleep(0.3)
10601060
if job.annulla:
@@ -1067,7 +1067,10 @@ def _trasferisci_chunk(self, job: TransferJob, idx: int):
10671067
job.trasferito = tx
10681068
dt = time.time() - job.t_inizio
10691069
job.velocita = int(tx / dt) if dt > 0 else 0
1070-
GLib.idle_add(self._coda.aggiorna_progress, idx, tx, job.size or tx)
1070+
now = time.monotonic()
1071+
if now - last_dl_update >= 0.1:
1072+
GLib.idle_add(self._coda.aggiorna_progress, idx, tx, job.size or tx)
1073+
last_dl_update = now
10711074
finally:
10721075
remote_f.close()
10731076
else: # upload
@@ -1078,6 +1081,7 @@ def _trasferisci_chunk(self, job: TransferJob, idx: int):
10781081
remote_f = self._sftp_transfer.open(job.dst, "wb")
10791082
try:
10801083
tx = 0
1084+
last_update = 0.0
10811085
while True:
10821086
while self._coda.is_in_pausa():
10831087
time.sleep(0.3)
@@ -1091,7 +1095,10 @@ def _trasferisci_chunk(self, job: TransferJob, idx: int):
10911095
job.trasferito = tx
10921096
dt = time.time() - job.t_inizio
10931097
job.velocita = int(tx / dt) if dt > 0 else 0
1094-
GLib.idle_add(self._coda.aggiorna_progress, idx, tx, job.size or tx)
1098+
now = time.monotonic()
1099+
if now - last_update >= 0.1:
1100+
GLib.idle_add(self._coda.aggiorna_progress, idx, tx, job.size or tx)
1101+
last_update = now
10951102
finally:
10961103
remote_f.close()
10971104

@@ -1103,9 +1110,19 @@ def chiudi_processo(self):
11031110
if self._sftp:
11041111
try: self._sftp.close()
11051112
except Exception: pass
1113+
self._sftp = None
11061114
if self._ssh:
11071115
try: self._ssh.close()
11081116
except Exception: pass
1117+
self._ssh = None
1118+
if self._sftp_transfer:
1119+
try: self._sftp_transfer.close()
1120+
except Exception: pass
1121+
self._sftp_transfer = None
1122+
if self._ssh_transfer:
1123+
try: self._ssh_transfer.close()
1124+
except Exception: pass
1125+
self._ssh_transfer = None
11091126

11101127

11111128
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)