Metadata-Version: 2.4
Name: cacadump
Version: 0.0.4
Summary: A terminal hex editor on gtcaca (libcaca) with POSA binary templates
Author-email: Seb Tricaud <sebastien.tricaud@proton.me>
License: MIT
Project-URL: Homepage, https://github.com/stricaud/cacadump
Project-URL: Repository, https://github.com/stricaud/cacadump
Keywords: hex editor,tui,libcaca,gtcaca,posa,binary,reverse-engineering
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console :: Curses
Classifier: Intended Audience :: Developers
Classifier: Topic :: Utilities
Classifier: Topic :: Security
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: gtcaca>=0.1.25
Requires-Dist: pycapng>=0.17.2

# cacadump

A terminal **hex editor** with **binary templates**.

- **[gtcaca](https://github.com/stricaud/gtcaca)** — a libcaca-based TUI toolkit — draws the interface.
- **[libpcapng / pycapng](https://github.com/stricaud/libpcapng)** and its **POSA** decoder language provide the parsing engine.

Binary structure is described declaratively in `.posa` files (not code); the
POSA engine parses a buffer into a field tree, and that same tree drives both the
**coloured hex grid** and the **template pane**.

```
 cacadump   photo.png   69 bytes   fmt:PNG                              F1 Help
 00000000  89 50 4E 47 0D 0A 1A 0A  00 00 00 0D 49 48 44 52 |.PNG........IHDR| │ Inspector @ 0x10
 00000010  00 00 00 04 00 00 00 04  08 06 00 00 00 A9 F1 9E |................| │ uint32   4
 00000020  7E 00 00 00 0C 49 44 41  54 78 9C 63 60 20 0D 00 |~....IDATx.c` ..| │ …
                                                                            │ Template: PNG
                                                                            │ PNG
                                                                            │   Signature: 8 bytes
                                                                            │   Chunks
                                                                            │     IHDR (13 bytes)
                                                                            │       Width: 4
                                                                            │       Color type: Truecolor+Alpha (6)
 0x10 (16)  HEX OVR                                                     PNG
```

## Features

- Hex + ASCII panes with a movable caret, insert/overwrite editing, undo/redo.
- **Binary templates via POSA**: autodetects the format from the buffer's magic,
  dissects it, colours each byte by the field it belongs to, and shows the parsed
  structure in a live tree that follows the cursor.
- **Data inspector**: the bytes at the cursor decoded as int8…int64 / uint / float32 /
  float64 (both byte orders), char and binary — all at once.
- Goto offset, find (text or `0x..` hex) with find-next, selection anchor, bookmarks.
- **Foldable template tree**: navigate the parsed structure, fold and unfold
  nodes, and the element you land on highlights exactly its bytes in the grid.
- Ships decoders for **PNG, GIF, BMP, GZIP, WAV** and — because POSA is
  libpcapng's own decoder language — every network protocol libpcapng/carcal
  ships (DNS, HTTP, TLS, DHCP, SMB, …), usable on any selected buffer.

## Install

```sh
pip install cacadump      # pulls in gtcaca and pycapng wheels
cacadump path/to/file
```

The `.posa` decoders live in the [fileformat.posa](https://github.com/stricaud/fileformat.posa)
submodule, so clone with `--recurse-submodules` (or run `git submodule update
--init` in an existing checkout).

For local development against checkouts of gtcaca and libpcapng:

```sh
git clone --recurse-submodules https://github.com/stricaud/cacadump
python -m venv .venv
PKG_CONFIG_PATH=$(brew --prefix libcaca)/lib/pkgconfig \
  .venv/bin/pip install scikit-build-core pybind11 setuptools-scm
PKG_CONFIG_PATH=$(brew --prefix libcaca)/lib/pkgconfig \
  .venv/bin/pip install --no-build-isolation -e ../gtcaca -e ../libpcapng
.venv/bin/pip install -e .
```

## Keys

| | |
|---|---|
| arrows / PgUp / PgDn / Home / End | move the cursor |
| `0-9 a-f` (hex pane) / any char (ASCII pane) | overwrite the byte under the cursor |
| INSERT | toggle insert / overwrite |
| DELETE / BACKSPACE | delete byte / delete left |
| Ctrl-A | set / clear the selection anchor |
| Ctrl-B | toggle a bookmark |
| F2 | run the template (POSA autodetect) |
| F3 | goto offset (`0x..`, or `+N` from cursor) |
| F4 / F5 | find (text or `0x..` hex) / find next |
| F6 / F7 | undo / redo |
| F8 | toggle the sidebar |
| F9 / F10 | open the menu bar (ESC leaves it) |
| Ctrl-S | save (Ctrl-W also works, for terminals that swallow Ctrl-S as XOFF) |
| Ctrl-D / Ctrl-U | decode the payload of a wrapped file / back out to the file bytes |
| TAB / Ctrl-X o | cycle the hex, inspector and template panes |
| F11 | switch between the hex and ASCII panes |
| mouse wheel | scroll the focused pane (3 rows a notch) |
| `+` / `-` / Enter / Space / Left / Right (template pane) | fold / unfold a tree node |
| Ctrl-X c / Ctrl-Q | quit (always confirms through a modal dialog) |
| F1 | help |

`Ctrl-X` is an emacs-style prefix, so it no longer quits on its own: `C-x o`
cycles panes, `C-x c` (or `C-x C-c`) quits, `C-x C-s` saves, `C-x k` backs out
of a decoded layer. `Ctrl-Q` quits directly — though some terminals swallow it
as XON, in which case use `C-x c`.

Everything on the menu bar is also a key, and vice versa — File, Edit, View,
Template and Help route to the same commands. F10 is gtcaca's own menu binding;
F9 is wired to the same thing because F10 is intercepted by some terminals.

## Wrapped files

Some formats are a header around a compressed stream. A NoteWorthy score is six
bytes then zlib, and `NWC1_SCORE` only matches what comes *out* of it — so
cacadump opens such a file at its payload and the template just works. The title
bar shows the layer stack (`[1/1 file > NWC (zlib)]`); `Ctrl-U` drops back to the
bytes on disk, `Ctrl-D` goes in again, and `--raw` skips decoding entirely.

Decoding is automatic only when the outer bytes have no decoder of their own. A
`.gz` keeps its `gzip.posa` view — inflating it silently would hide the very
structure that decoder exists to show — so you descend into it with `Ctrl-D`.

Each layer is a separate buffer with its own offsets, cursor and undo history,
and offsets are never mapped across layers: DEFLATE has no byte-to-byte
correspondence between input and output, so "the compressed bytes behind this
field" would be a fiction. Saving re-encodes edited payloads back through their
containers; a layer you did not edit is written back exactly as it was read, so
opening and saving a file you didn't change never rewrites it.

## Writing a template

Templates are `.posa` files (see the `src/cacadump/protos/` submodule and
libpcapng's `doc/posa.md`). A decoder is declarative — types, enums, `repeat`, `when`/`else`,
`scope`, `bits`, and a `label`/`info` line:

```posa
Object<main> PNG
    abbrev "png"
    col "PNG"
    required bytes<8> signature "Signature"
    repeat until end as chunk "Chunks"
        label "%s (%u bytes)" ctype, length
        required uint32 length "Length"
        required str<4>  ctype  "Type"
        when ctype == 0x49484452:            # "IHDR"
            required uint32 width "Width"
            required uint32 height "Height"
            required uint8  bit_depth "Bit depth"
            required uint8  color_type "Color type"
                Truecolor+Alpha = 6
        else:
            required bytes[length] data "Data"
        required uint32 crc hex "CRC"
```

Point `CACADUMP_PROTOS_DIR` at a directory of your own (or several, separated by
`:`) and the format is understood on the next open — no code change. Decoders meant for everyone belong
upstream in [fileformat.posa](https://github.com/stricaud/fileformat.posa)
rather than dropped into the submodule checkout, where they would be lost on the
next `git submodule update`.

## Notes / limitations

- POSA is byte-order-*per-type*, so formats that switch endianness or word size
  on a runtime field (ELF/PE/Mach-O 32-vs-64) are only partially expressible today.
- Editing operates on an in-memory buffer; very large files load fully into memory.

## License

MIT.
