4 Commits

Author SHA1 Message Date
pax
b8cb47badb security: fix #6 — escape source via build_source_html in InfoPanel
Replaces the inline f-string concatenation of post.source into the
RichText document with a call through build_source_html(), which
escapes both the href value and the visible display text.

Also escapes the filetype field for defense-in-depth — the value
comes from a parsed URL suffix (effectively booru-controlled) and
the previous code interpolated it raw.

Removes the dead duplicate setText() call that wrote a plain-text
version before being overwritten by the RichText version on the
next line.

Audit-Ref: SECURITY_AUDIT.md finding #6
Severity: Medium
2026-04-11 16:19:17 -05:00
pax
27c53cb237 prevent info panel from pushing splitter on long source URLs 2026-04-10 20:05:57 -05:00
pax
a86941decf info_panel: suppress flat-tag flash when category fetch is pending
When a category fetch is about to fire (Rule34/Safebooru.org/
Moebooru on first click), the info panel was rendering the full
flat tag list, then ~200ms later re-rendering with categorized
tags. The re-layout from flat→categorized looked like a visual
hitch.

Fix: new _categories_pending flag on InfoPanel. When True, the
flat-tag fallback branch is skipped — the tags area stays empty
until categories arrive and render in one clean pass.

  _ensure_post_categories_async sets _categories_pending = True
    before scheduling the fetch (or False if no fetcher = Danbooru)
  _on_categories_updated clears _categories_pending = False

Visual result:
  Danbooru/e621:        instant (inline, no flag)
  Gelbooru with auth:   instant (background prefetch beat the click)
  Rule34/SB.org/Moebooru: empty ~200ms → categories appear cleanly
                          (no flat→categorized re-layout)
2026-04-09 20:05:38 -05:00
pax
eded7790af Move InfoPanel from app.py to info_panel.py (no behavior change)
Step 11 of the gui/app.py + gui/preview.py structural refactor. Pure
copy: the toggleable info panel widget with category-coloured tag
list moves to its own module. The new module gets its own
`log = logging.getLogger("booru")` at module level — same logger
instance the rest of the app uses (logging.getLogger is idempotent
by name), matching the existing per-module convention used by
grid.py / bookmarks.py / library.py. All six tag-color Qt Properties
preserved verbatim. app.py grows another shim line. Shim removed
in commit 14.
2026-04-08 14:39:08 -05:00