fix: parse Disc qwinsta rows so RDG flap auto-logoff works (0.5.14)
Empty SESSIONNAME broke session matching; auto-disconnect failed with 'No matching Windows session'.
This commit is contained in:
@@ -409,28 +409,54 @@ def filter_windows_sessions_for_user(
|
||||
return [s for s in sessions if windows_user_matches_session(user, s.user)]
|
||||
|
||||
|
||||
def parse_qwinsta_sessions(stdout: str, *, filter_user: str | None = None) -> list[HostSessionRow]:
|
||||
rows: list[HostSessionRow] = []
|
||||
norm_filter = (filter_user or "").strip().lower()
|
||||
def _qwinsta_sam_account(value: str) -> str:
|
||||
text = (value or "").strip()
|
||||
if "\\" in text:
|
||||
text = text.split("\\")[-1]
|
||||
if "@" in text:
|
||||
text = text.split("@")[0]
|
||||
return text.casefold()
|
||||
|
||||
def norm_user(value: str) -> str:
|
||||
return value.replace("B26\\", "").replace("b26\\", "").lower()
|
||||
|
||||
def parse_qwinsta_sessions(stdout: str, *, filter_user: str | None = None) -> list[HostSessionRow]:
|
||||
"""Parse ``qwinsta`` output.
|
||||
|
||||
Disconnected sessions often have an empty SESSIONNAME column, so the line
|
||||
becomes ``USERNAME ID STATE`` (3 tokens). Older parsing required 4 tokens
|
||||
and skipped those rows — that broke RDG flap auto-logoff for Disc sessions.
|
||||
"""
|
||||
rows: list[HostSessionRow] = []
|
||||
filter_sam = _qwinsta_sam_account(filter_user or "")
|
||||
skip_users = frozenset({"services"})
|
||||
|
||||
for line in stdout.splitlines():
|
||||
text = line.strip()
|
||||
if not text or re.match(r"^SESSION", text, re.I) or text.startswith("---"):
|
||||
continue
|
||||
parts = text.split()
|
||||
if len(parts) < 4:
|
||||
id_idx: int | None = None
|
||||
sid = 0
|
||||
for i, part in enumerate(parts):
|
||||
token = part.lstrip(">")
|
||||
if token.isdigit():
|
||||
id_idx = i
|
||||
sid = int(token)
|
||||
break
|
||||
if id_idx is None or id_idx < 1:
|
||||
continue
|
||||
session_name = parts[0].lstrip(">")
|
||||
user_name = parts[1]
|
||||
try:
|
||||
sid = int(parts[2])
|
||||
except ValueError:
|
||||
state = " ".join(parts[id_idx + 1 :]) if id_idx + 1 < len(parts) else ""
|
||||
if not state or state.casefold().startswith("listen"):
|
||||
continue
|
||||
state = " ".join(parts[3:])
|
||||
if norm_filter and norm_filter not in norm_user(user_name):
|
||||
before = parts[:id_idx]
|
||||
if len(before) == 1:
|
||||
session_name = ""
|
||||
user_name = before[0].lstrip(">")
|
||||
else:
|
||||
session_name = before[0].lstrip(">")
|
||||
user_name = before[1]
|
||||
if user_name.casefold() in skip_users:
|
||||
continue
|
||||
if filter_sam and filter_sam not in _qwinsta_sam_account(user_name):
|
||||
continue
|
||||
rows.append(
|
||||
HostSessionRow(
|
||||
@@ -441,7 +467,7 @@ def parse_qwinsta_sessions(stdout: str, *, filter_user: str | None = None) -> li
|
||||
)
|
||||
)
|
||||
|
||||
if rows or not norm_filter:
|
||||
if rows or not filter_sam:
|
||||
return rows
|
||||
|
||||
return parse_qwinsta_sessions(stdout, filter_user=None)
|
||||
|
||||
Reference in New Issue
Block a user