- the tracker kept only the immediate parent DF, so a phonebook file read as
"DF_PHONEBOOK/4FA1" — the trace's own selection path (00a4080406
7F105F3A4FA1) spells out the whole chain; the channel state now carries it
(selected_df_state() returns (df, path), e.g. ('5f3a', ['7f10', '5f3a'])),
the tracker stores it per file and _file_path() renders it:
"DF_TELECOM/DF_PHONEBOOK/4FA1"
- chain rules: a child DF selected by FID appends to the current chain, MF and
the ADF restart it, an AID is its own root, a path selection uses the DFs
in the path (an explicit '7fff' collapsing to the ADF), and an EF selects
keeps it. A leading MF is implicit in a longer path; MF-only files keep
"MF/…", ADF files "ADF/…" (the previous labels unchanged)
- the chain is learned from the FCP sighting too and extends a shorter path
recorded earlier, so entries created from a GET RESPONSE still get the full
path
- verified on the live traces (sessions 47/193): 5f3a/4fa1 ->
DF_TELECOM/DF_PHONEBOOK/4FA1, 5f3a/4f30 -> DF_TELECOM/DF_PHONEBOOK/EF_PBR
(4F30), while 3f00/2fe2 -> MF/EF_ICCID (2FE2) and 7fff/6f07 ->
ADF/EF_IMSI (6F07) stay as before
- tests: selected_df_state (path/FID/MF/ADF/AID/EF cases) and a tracker flow
with a path selection asserting the full path; 529 Python + 76 Node tests
- README/README_RUS show the chain; PWA_VERSION/pyproject/version.py 2.7.6,
SW cache simtrace-analyser-v86
- CLA decode (TS 102 221 §10.1.1/§10.3): standard channels 0-3 from b2-b1
and the extended channels 4-19 from b4-b1. The old further-format rule
read only b2-b1 (channel 8 read as 6, 19 as 7) and the ETSI '11x0 xxxx'
coding (0xC0-0xEF) was not handled at all; the class ranges now follow the
specs (0x80-0x8F UICC, 0xA0-0xAF SIM, 0xC0-0xEF ETSI extended, 0x20-0x3F
reserved, 0xFF invalid) and SM/chain are decoded per family — the SM
extraction and the chaining bit (b5, not b6) were off by one bit
- per-channel state: database._decode_rows/_replay_context use the shared
cla_channel() helper — before, CLA & 0x03 with no +4, so a channel-5
SELECT clobbered channel 1's selection and a channel-8 one channel 0's
(the local traces already open channels: 29 MANAGE CHANNEL opens, 1-2)
- COMPRION T=0 import: the synthesized GET RESPONSE keeps the channel —
a plain CLA for 0-3 (as real terminals do) and 01x0 for 4-19
- ATR historical bytes: the UICC's COMPACT-TLV objects (TS 102 221 §6.3.1)
with card service data, the card capabilities (ISO 7816-4 §8.1.1.2.7
Table 88: assignment methods and max logical channels — the workspace
cards announce 4 and "8 or more") and the status indicator ('00' trailing
bytes / the '8Y' TLV); a truncated ATR no longer raises
- MANAGE CHANNEL success replies decode the assigned channel byte
- capture/import: a 'tpdu' packet that is not APDU-shaped (shorter than the
header, CLA FF, ISO-reserved class) is skipped and counted, so a
character-level or mis-sampled stream no longer pollutes the decode
(the local DB's outlier sessions are exactly that)
- tests: CLA table vectors, per-channel state isolation on channels 8/12,
COMPRION GR channels, filetrack extended channels, ATR compact-TLV and
card-capability cases, the capture skip counter, the PWA rows; 527 Python
+ 47 Node tests
- README/README_RUS document the extended channels, card capabilities and
the skip counter; PWA_VERSION/pyproject/version.py 2.6.0, SW v72
- the timeline's Δ glyph became a **Details** button, and it now appears on
Update rows too (not just card-side changes); EN "Changed (card)" ->
"Changed on card", RU "Изменено (картой)" -> "Изменено картой"
- the details modal shows the affected unit — the whole file, or the single
record that changed — **before and after** the change as hex views (16 bytes
per row, ASCII column, never-observed bytes as `--`), with the bytes that
changed and the bytes the operation *first observed* highlighted in two
different colours, plus the changed/new byte counts and the APDU reference;
the old before/after byte table is gone
- `GET /api/sessions/<id>/files/image?key=…&change=…` returns those two views
(segments with offsets) plus the change's metadata; the images are
reconstructed from the current image by undoing the later changes
(`FileTracker.change_images`), so nothing is duplicated per event — every
value change is an event, hence the values are exact (a byte only first
observed later can appear as known in both views)
- tracker: change events carry `observed_ranges` (bytes that were unknown
before the operation) next to `ranges`; an update that only observes new
bytes now records an event (so it can be inspected); record-file ranges are
in-record byte offsets (the record number stays in its own field), which the
previous "record number as position" could not express for a hex highlight
- tests: change-images reconstruction (before/after per event, later changes
undone, records isolated, observation-only events, unknown gaps), the image
endpoint (200/404/400), and Node tests for the hex-image helper (highlight
classes, unknown gaps, ASCII, row limit) and the modal rendering
- v2.4.0; SW cache simtrace-analyser-v65
- new `simtrace_analyser/filetrack.py`: a single-pass tracker over a
session's decoded messages, keyed by (DF, FID) and trace-wide (resets only
wipe the per-channel selection): counters (`select`/`read`/`update`,
successful operations only), a sparse image of the observed bytes
(transparent files by offset, record files per record number) and the
change log
- changes: **device** = an UPDATE seen in the trace (applied to the image,
`no_change` flags a provable no-op); **card** = a READ whose bytes differ
from the image on bytes already known (logged at the surfacing read with
the changed ranges and the before/after hex; never-seen bytes just fill
the image, they are an observation, not a change)
- SFI-addressed accesses join the same entry as path/FID ones: the SFI ↔ FID
relations come from the normative tables and from every surfaced FCP `88`
DO (including the spec's "SFI = 5 LSBs of the FID" rule when the DO is
absent); an SFI used before its relation is learned stays provisional and
merges into the resolved entry
- the DF identity follows TS 102 221 §8.4/Table 8.2: `selected_df_fid()` now
resolves an EF path selection to its parent DF and returns `aid:<hex>` for
applications selected by an unknown AID (named from EF.DIR when the trace
surfaced it); `Database._decode_rows` gained an `on_message` hook and
`track_files()`
- `GET /api/sessions/<id>/files`: the operation timeline, the per-file
counters/coverage/change log, the SFI relations and the AID labels
- PWA: the side panel's Map/Stats tabs became a view selector (Map / Stats /
Files); the Files view is a timeline of Read / Update / Changed (card) rows
(colour-coded, the same file names as the Map view), a row click jumps to
the APDU (loading the pages it needs) and a card-change row's Δ opens the
changed ranges with the previous and the new bytes; EN/RU
- bounds: the image freezes past 64 KB of observed bytes per file, the change
log keeps the last 1000 events per file (counters keep counting)
- tests: tests/test_filetrack.py (counters, resets, channels, image/diff
semantics, record files, SFI resolution and the provisional merge, EF.DIR
labels, caps, the endpoint) and Node tests for the Files-view helpers and
wiring
- v2.3.0; MIN_SERVER_VERSION 2.3.0; SW cache simtrace-analyser-v63
- move the analysis server out of simtrace2_pysniff into simtrace_analyser;
simtrace2_pysniff stays as the simtrace2-sniff replacement capture utility
- new server CLI: simtrace-analyser-server; python -m simtrace_analyser
(simtrace2-pysniff-server and python -m simtrace2_pysniff.server dropped)
- simtrace2_pysniff lazy-imports hardware symbols, so the server no longer
pulls PyUSB at startup; the GSMTAP/PCAP codecs work without libusb
- version 2.0.0 everywhere (was 1.22.21); PWA SW cache simtrace-analyser-v54
- frontend: server name, clone URL and i18n strings updated; vendored-parser
reference otaman -> SIMple
- README/README_RUS reworked product-first (analyser first, utility second)
- DB dir ~/.simtrace-analyser, /api status payload and hosted PWA unchanged