Commit Graph
7 Commits
Author SHA1 Message Date
nathan 3bbea8e952 Phase 2b: server/client timeouts, atomic state writes, log mutex, panic and shutdown fixes
- http.Server with ReadHeaderTimeout/IdleTimeout (no read/write timeouts: /stream/ is long-lived)
- shared outbound clients: providerHTTPClient (5m), apiHTTPClient (30s), imgcache client (30s)
- imgcache: download outside the lock, per-item helper, cache URL uses the file name not the fs path
- writeFileAtomic (temp + fsync + rename) for settings/xepg/pms/urls/authentication JSON
- one package-level logMu for WebScreenLog and notifications; ring buffer keeps the newest lines
- notifications evict the oldest instead of random map entries
- xepg XMLTV file removal rebuilt after the loop; data.go range-mutation removed
- API handler returns after error body; WS request/response fresh per command
- checked type assertions in data/backup/provider/screen
- SIGINT/SIGTERM handled in main via src.Shutdown(); fatal paths exit 1
2026-09-26 13:17:07 +10:00
nathan 36303fecea Phase 1b/1c: server-side input handling and authentication
continuous-integration/drone/push Build encountered an error
Input handling:
- uploadLogo: client file name reduced to a safe base name with an image
  extension (path traversal and arbitrary-extension writes closed).
- extractZIP: zip-slip guard; entries that resolve outside the target are
  refused. Per-entry closes no longer pile up as defers.
- ffmpeg.path / vlc.path must be an existing regular file named ffmpeg,
  vlc or cvlc, checked both when saved and right before exec.
- Stream URLs passed to the external buffer must use a network scheme
  (http, https, rtsp, rtmp, rtp, udp, mms); file:, concat:, pipe: are
  refused.
- /download/ (backups with settings.json and authentication.json) requires
  the web session when web authentication is enabled.
- settings.json is written 0600; the Plex token is masked in every payload
  sent to the UI and the mask round-trips as "unchanged" on save.

Authentication:
- Passwords are stored with bcrypt. Existing HMAC-SHA256 records still
  verify (constant time) and are re-hashed on the first successful login.
  Username lookups compare in constant time.
- URL (?username=&password=) and HTTP Basic authentication verify the
  credentials per request via AuthenticateUser and no longer create a
  session token, which removes the unbounded token growth under Plex
  polling. Expired sessions are evicted whenever a new one is created.
- createFirstUserForAuthentication and checkAuthorizationLevel now return
  real errors instead of calling no-op closures.

Tests: src/security_test.go and src/internal/authentication/
authentication_test.go cover each of the above.
2026-09-26 13:04:54 +10:00
nathan 4976219857 Phase 1a: browser-side security
continuous-integration/drone/push Build encountered an error
- Provider-controlled strings (channel names, groups, file names, log
  lines, in-place mapping edits, client info) are rendered with
  textContent instead of innerHTML. PopupContent.description() takes an
  explicit isHTML flag that only the static help texts pass.
- Websocket: drop the always-true CheckOrigin so gorilla's same-origin
  check applies; read the session token from the HttpOnly cookie sent with
  the handshake (the ?Token= query parameter is still accepted for older
  clients); the client no longer puts the token in the URL, rewrites the
  cookie, or console-logs request/response payloads.
- Session cookie is HttpOnly, SameSite=Strict, Path=/, session-scoped
  (expiry stays server side) and is cleared on logout.
- Serving the first-run wizard no longer sets Settings.AuthenticationWEB
  to false; the wizard page simply bypasses login while it is active.
- Upgrade failures no longer write a second error response.
- Tests: src/websocket_test.go covers cross-origin refusal, same-origin
  and no-Origin clients, missing/unknown/legacy tokens, and cookie flags.
2026-09-26 12:59:47 +10:00
nathan 504ea3f9f4 Phase 3: Go hygiene pass, runtime PUID/PGID, fork README
continuous-integration/drone/push Build encountered an error
Go:
- staticcheck 399 -> 0 with staticcheck.conf (style checks ST1000/1003/
  1005/1016/1020/1021/1022 excluded; error strings are shown in the UI).
- io/ioutil and rand.Seed removed; CloseNotifier kept with a lint-ignore
  until the Phase 2 context rewrite.
- Dead code deleted: Auto handler, getStreamByChannelID, updateXEPG,
  indexOfInt, jsonToMapInt64, removeOldSystemData, randomTime, and the
  commented-out blocks in struct-buffer.go and internal/authentication.
- Duplicates folded: cacheImagesInBackground(), one addErrorToStream().
- Bugs found by SA4006/SA5001: os.Create handle leaked per ffmpeg segment
  (buffer.go), http.NewRequest error unchecked (buffer.go), xepg.json
  migration wrote null on read error (migrate.go), WriteUserData errors
  silently dropped (authentication.go), defer Close before error check
  (buffer.go, toolchain.go). checkFilePermission results were discarded;
  an unwritable config or temp dir is now fatal at start-up.
- gofmt applied repo-wide; Drone runs gofmt check and staticcheck.

Docker:
- Entrypoint starts as root, applies PUID/PGID (falls back to XTEVE_UID/
  XTEVE_GID, then image defaults), fixes config ownership only when it
  differs, then drops to xteve via su-exec. --user starts skip all of it.
- /xteve removed from LEGACY_CONFIG_DIRS (it is the parent of the default).
- mwader/static-ffmpeg pinned to 7.1.1; VOLUME /xteve/config.
- Compose files pull registry.coadcorp.com/nathan/xteve:latest, use
  PUID/PGID/TZ, and explain that SSDP needs host networking.
- .dockerignore excludes the npm toolchain (bundle stays in html/js).

Docs: README rewritten for the fork (about, registry, compose, env vars,
security notes); README-DEV gains a container section.
2026-09-26 12:57:43 +10:00
nathan ffd43d5217 Enhance log display behavior and menu state management
continuous-integration/drone/push Build is passing
2026-02-11 14:37:02 +11:00
nathan c5545cbf08 go fix for 1.26
continuous-integration/drone/push Build is passing
2026-02-11 12:53:35 +11:00
marmei e001b06b62 v2.0.0.0000 2019-08-02 20:12:09 +02:00