Skip to content

1.10.6 - #452

Merged
awehttam merged 8 commits into
mainfrom
claudesbbs
Sep 11, 2026
Merged

1.10.6#452
awehttam merged 8 commits into
mainfrom
claudesbbs

Conversation

@awehttam

Copy link
Copy Markdown
Owner

No description provided.

sync claudesbbs from main
TelnetUtils::wrapTextLines() used a byte-oriented wordwrap() with cut=true
that counted ANSI escape bytes and multi-byte UTF-8 glyphs toward the line
width. Coloured and ANSI-art messages could be hard-cut in the middle of an
escape sequence (rendering a literal "[35m") or a multi-byte character
(mojibake), and lines could overflow the terminal width.

This surfaced on ANSI-art posts after the 1.10.5 TerminalTextSanitizer
change: stripping absolute cursor positioning collapses positioned art
fragments into long logical lines that then overflow the wrap width.

Add wrapAnsiLine()/escapeSequenceLength(): escape sequences are treated as
zero-width atomic units and never split, wrapping breaks only on character
boundaries, and visible width is measured with mb_strwidth. Lines with no
escape sequences and no high bytes keep the fast wordwrap() path.
Since 1.10.5, TerminalTextSanitizer strips absolute cursor positioning
from message bodies before the inline reader shows them, so genuine ANSI
art reflows into unreadable text. Add a dedicated full-screen art view
that renders such bodies with cursor positioning intact, while still
removing OSC (title/clipboard), DCS/APC/PM, private-mode sequences and
device-status/answerback queries -- the input-injection and clipboard
vectors stay closed; only in-screen drawing is restored.

- TerminalTextSanitizer::sanitize() gains a POLICY_POSITIONING mode and a
  hasPositionedAnsi() detector.
- New AnsiArtViewer (telnet/src/): full-screen render + dismiss prompt;
  mode() reads the TERM_ANSI_ART_MODE env setting.
- EchomailHandler / NetmailHandler message viewers detect art on the raw
  body, add an 'A' key (viewart) + Ctrl-K help item, and in 'inline' mode
  auto-launch the art view once per message open.
- TERM_ANSI_ART_MODE: viewer (default, press A) | inline (auto-launch).

i18n keys for all locales, unit tests, daemon include lists, and docs
(UPGRADING_1.10.6, TerminalServer, TerminalServerDevGuide) updated.
TERM_ANSI_ART_MODE gains a third value, 'raw': for art message bodies the
normal Telnet/SSH reader sanitizes with POLICY_POSITIONING and skips
word-wrapping, so cursor-positioning and erase codes pass straight through
and the art renders in place while scrolling. The sysop opts in to
in-screen display spoofing; OSC/DCS/answerback vectors stay blocked.

- AnsiArtViewer::mode() recognises 'raw'; readerBodyPolicy()/readerSkipsWrap()
  gate the loosened path on (isArt && mode === raw) so every non-art message
  and the viewer/inline modes keep the strict path.
- EchomailHandler / NetmailHandler viewers compute isArt before sanitizing,
  pass the policy through, and branch $buildView to split-on-newline instead
  of wrapTextLines() when readerSkipsWrap() is true.

Unit tests, .env.example, and the three terminal-server docs updated.
Add AnsiCanvasRenderer: resolves an ANSI-art byte stream against an
off-screen character grid (cursor moves, erase, SGR, save/restore) and
serialises the used rows back to SGR-only lines with no positioning.
Ported from the browser AnsiTerminal in public_html/js/ansisys.js.

TERM_ANSI_ART_MODE gains 'canvas' and it is now the default: art bodies
are canvas-rendered and shown inline in the normal reader, which scrolls,
repaints and resizes them like any other message -- no cursor-control
code reaches the terminal, only colour. 'viewer' (old default), 'inline'
and 'raw' remain. The full-screen positioned view is still on the 'A' key
in every mode.

- AnsiArtViewer::readerRenderMode() replaces readerSkipsWrap(); returns
  strict | canvas | raw and drives both the sanitize policy and the
  $buildView line-production branch in the Echomail/Netmail viewers.
- Height capped at 1000 rows; lines clipped to the reader width and
  re-rendered on resize.

Unit tests for the renderer and the mode helpers, daemon include lists,
.env.example and the three terminal-server docs updated.
@awehttam
awehttam merged commit 2ddb510 into main Sep 11, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant