diff options
Diffstat (limited to 'PLAN.md')
| -rw-r--r-- | PLAN.md | 73 |
1 files changed, 73 insertions, 0 deletions
@@ -674,3 +674,76 @@ after use - never part of the build) confirmed the captured messages in `ws_messages` via `ipc.Client.ListWSMessages`, matching what the test client actually sent and received, correctly attributed to direction and opcode. + +## Sorting and highlighting + +Filtering already existed (FTS5 search plus `status:`/`source:`/ +`flagged:` and column filters - see Search above); sorting and +highlighting didn't, at all, until now. + +Sorting is client-side, applied on top of whatever order List/Search +already returned (newest-first, or FTS5 relevance) - `o` cycles the +sort column (the default "captured" - no override - then status, +size, time taken, method, host, path), `O` reverses it. +`refreshTable()` doesn't just re-render sorted rows, it reorders +`m.entries` itself to match: every "act on the selected row" key +handler (enter/r/i/f/c/x, and the mouse equivalents) reads +`m.table.Cursor()` and indexes straight into `m.entries` at that +position, with no indirection layer. If the table's rendered order and +`m.entries`'s order ever diverged, the highlighted row and the entry +an action actually targets would silently disagree. Keeping them +identical sidesteps that whole bug class rather than updating every +one of those call sites to go through a lookup. + +Highlighting has two parts, and they needed genuinely different +solutions because they render through different paths: + +- **JSON syntax highlighting** (`cmd/mitmux/jsoncolor.go`): walks the + token stream via `json.Decoder.Token()` with an explicit stack + rather than recursive calls, so depth is bounded by available memory + rather than Go's call stack for deeply nested attacker-controlled + JSON. Every string value and object key gets re-escaped via + `json.Marshal` before being written - which is also the entire + safety argument for *not* running the colorized output through + `sanitizeControl` afterward the way every other raw-text view in + this codebase does: JSON's own encoding rules forbid a literal + control character (ESC included) in a string, so re-marshaling one + neutralizes it as a side effect of just producing valid JSON text. + Running the already-colored output through `sanitizeControl` + afterward would instead corrupt the ANSI codes this function adds - + it treats ESC like any other control byte, correctly, for content + that hasn't been through this treatment. `prettyResponse` sanitizes + the header/status block (still server-controlled, still raw text) + separately from the colorized body for exactly this reason. This + path renders into a `viewport`, a plain scrolling text pane with no + fixed-width cell model, so ANSI content survives untouched. +- **Status-code color-coding** (2xx green through 5xx red, Burp/ + Caido's own convention) does *not* live in the history or Intruder- + results tables, despite an initial attempt to put it there. Confirmed + live, not guessed: `bubbles/table` v1.0.0 - the newest version + available, there is no newer one to upgrade to - fits cell text to + its column width via `go-runewidth`'s `Truncate`, which has zero ANSI + awareness; it counts every visible character of a + `"\x1b[38;5;42m"` escape sequence as real display width. Coloring the + Status cell didn't misalign the table, it silently deleted the status + text from the row entirely - the width-fitting truncation cut into + the escape sequence itself. `styledStatus` exists but is deliberately + unused inside any `table.Row`; it's used once, in `detailView`'s + title, which is a plain string lipgloss-renders whole with no width + constraint - nesting one nested `Render()` call inside another works + correctly there (confirmed live via raw escape-code inspection), at + the cost of one trailing space losing the outer title's bold/color + after the inner reset code, placed at the very end of the string + specifically to keep that cost minimal. + +Verified live in tmux against a running daemon with six real captured +entries spanning 200/302/404/500 responses: `o` sorted ascending by +status (200, 200, 200, 302, 404, 500), `O` reversed it; the detail +view's title rendered the status code in the correct color per class +(confirmed red for the 500 entry via raw escape-code capture, not just +visually); pretty-printing a real JSON response produced correctly +colored, correctly indented output - keys blue, string values green, +numbers orange, booleans/null magenta, punctuation gray, confirmed +against the raw captured ANSI codes, not just eyeballed - and the +request tab (never JSON, never pretty-printed) rendered as plain +unstyled text, unaffected. |