Commit Graph

10 Commits

Author SHA1 Message Date
catarrh 9ae9c39e55 v3.31.0: the EF_PBR (phonebook reference) support
EF_PBR ('4F30', TS 31.102 4.4.2.1) lists the phonebook's files as
BER-TLVs, and those files are not in pySim's model - so they were
invisible in the file tree.

- The PWA gains the decoder (efDecPbr, registered as EF.PBR/4f30): the
  'A8'/'A9'/'AA' type-1/2/3 containers, the 'C0'-'CC' kinds, the 02/03
  value lengths (FID / FID+SFI) and the master EF (the first FID after
  the first 'A8'), tolerant of FF padding, truncation, unknown tags and
  the spec's vague 'AA' path form (kept raw + noted, never a throw).
- The server reads the three PBR copies once per card session
  (best-effort, exactly like EF.ARR) into server.pbr and serves the raw
  records from the card-free GET /api/pbr.
- The file tree is populated SERVER-SIDE (no frontend involvement): a
  small Python parser reads the cached records and /api/tree appends the
  referenced files as children of the DF that holds the PBR
  ({'name','fid','isDir':false,'pbr':true,'sfi'}, deduplicated against
  the model), and /api/tree|select|read|write auto-allow the probe for
  exactly those FIDs, so the injected nodes are clickable without any
  PWA flag.  The node-to-PBR match is by the requested node's normalised
  path: a leading MF before an ADF segment is dropped and an ADF
  addressed by AID (the Profiler's walk) folds onto its name, so both
  DF_PHONEBOOK copies resolve to their own PBR; a full path never falls
  back to another DF's copy, and an ambiguous bare 5F3A injects nothing.
- Drift guard: the JS and Python parsers share
  frontend/tests/pbr_vectors.json, which includes the TS 31.102 Annex G
  record (its printed A8 length is internally inconsistent - 10
  primitives x 5 bytes = 0x32, not the printed 0x2D - so the corrected
  length is used, noted in the case name).

Docs: api.md (/api/pbr, the tree children, the auto-probe, the AA path
form), the repo AGENTS.  953 frontend + 989 Python; sw simple-v455.
2026-10-18 01:47:04 +03:00
catarrh c69a779ca4 v3.25.0 review: the structured access-rule editor
The access-rules block was read-only and its Check radio was disabled
without captured lines, so a hand-made rule could not define rules and
captured ones could not be adjusted.  It now edits the decoded rule's
structure:

- fcpArrRuleParse/fcpArrRuleEncode parse a canonical decoded line into
  the AM (bit mask, RESIZE FILE, INCREASE) + SC condition model and
  re-encode it byte-identically (round-trip tested); the template forms
  (OR/AND/NOT, SM CRTs, command descriptions) stay raw and removable.
- The editor renders each rule as operation checkboxes (or the command
  form) and condition selects (always / never / a key reference with
  its usage), with a preview line of the canonical string the check
  compares; + rule adds READ always; + condition / x adjust the rows.
- The None/Check radio no longer disables; a new rule can be built by
  hand and captured rules adjusted.  The stored format is unchanged
  (the canonical strings), so capture, the check, the set comparison
  and validation are untouched.

Tests: parse/encode round-trips (incl. raw forms), the mutators, the
editor render, plus the existing check tests.  882 frontend + 858
Python; sw cache simple-v424.
2026-10-10 23:55:07 +03:00
catarrh 73ff6a60bd fix: SCP80 RC/CPL parity, file-life-cycle labels, EF.ARR and PS template decoders (v3.5.1)
Three fixes found while filling the ETSI/3GPP registry gaps against the
SIMalliance Stepping Stones R7:

- SCP80 builder/verification parity (TS 31.115 Table 1 NOTE / 4.2 / 4.3):
  the CPL is now transmitted whenever the packet is ciphered or carries
  RC/CC/DS - it is part of their input - and whenever the packet needs SMS
  concatenation; a single unprotected SM keeps pySim's CHL-first form.
  Before, the JS dropped the CPL for every unciphered packet while the
  server reference re-added it, so "Verify vs pySim" reported a false
  MISMATCH for every unciphered RC/CC packet (SPI1 01/02/0A/12/1A...).
  All ten offered SPI1 values now match the server reference byte-for-byte.
- RC (SPI1 b2b1 = 01) was offered but not built: the JS now computes CRC-32
  (TS 102 225 5.1.3.2, pySim zlib.crc32 parity) over the same CPL frame as
  the CC; the packet no longer silently omits the 4-byte RC field.
- Server: _build_secured_packet/_ota_reference add the CPL to a concatenated
  unprotected packet too (Table 1 NOTE / 4.3).

- fcpLifeCycle: unlisted values with b8 clear are RFU, b8 set is proprietary
  (Table 11.7b); previously all unmatched values were labelled proprietary.
- EF.ARR decoder now decodes the expanded format (AM_DO/SC_DO per ISO 7816-4
  5.4.3.2 + TS 102 221 9.2.7): operation bit masks, INCREASE/RESIZE AM_DO
  0x84, OR/AND/NOT templates, PIN key references with usage qualifiers.
- FCP 'C6' PS template DO decoded (PS_DO bitmap + key references + usage
  qualifiers, TS 102 221 11.1.1.4.10/9.5.2) with a shared key-reference map.

Tests: sp.test.js (CPL/RC vectors + crc32 known answer), ef_decode.test.js
(expanded-format ARR vectors), profiler.test.js (LCSI RFU/proprietary, C6),
test_ota_helpers.py (RC reference, unprotected single-SM vs concatenated).
Help EN/RU and READMEs: CPL size 2 (SMS), RC/CC/DS 4-8, RC bullet, CPL rule.
547 frontend / 397 Python green; version 3.5.1; sw cache simple-v253.
2026-09-24 08:05:07 +03:00
catarrh f72054f61f ui: stop showing the all-FF record marker as a field; label it in the diff (v3.1.4)
A profile check comparing an empty PNN record against a populated one
showed a cryptic 'Empty: yes' row: the decoders return {empty: true} for
an all-FF record and efFlatten() rendered that marker as a pseudo-field
('empty' prettified to 'Empty', the boolean as 'yes').

- efFlatten() skips the marker (the decoded views already show their own
  translated 'empty' note next to the record).
- efDiffData() fills the cells of a side that decodes to an all-FF record
  with 'Empty (all FF)' (RU: 'Пусто (только FF)') instead of leaving them
  blank; a field merely missing from a non-empty record stays blank.
- tests: efFlatten marker, one-sided and both-sided empty diffs, and the
  PNN case from the report; help EN/RU note the new text.
- sw.js simple-v239.
2026-09-22 22:26:20 +03:00
catarrh e3502c059e fix: use the Network Name spare-bit count for PNN GSM-7 text (v2.7.21)
EF.PNN decoded 'Miranda@' for the live card's record 2: efPnnText ignored
the number of spare bits in the coding octet (TS 24.008 10.5.3.5a bits
1-3) and unpacked floor(8n/7) septets, so the 7 zero pad bits became '@'.

- gsm7Decode(octets, septets?) takes an exact character count and removes
  a final <CR> used as padding (TS 23.038 6.1.2.1.1).
- efPnnText derives the count from the spare field ((8n - spare)/7 when
  1-7; floor(8n/7) + CR drop for 000 = no information).
- tests: the seven live EF.PNN records (Alfa, Miranda, Win, Mir Telekom,
  +7 Telekom, Fenix, MKS), a UCS2 record and the CR-padding drop.
- docs/uicc/UICC_SPECS.md: CR-padding rule in 10.4 and a new 10.7
  Network Name coding section (outside the repo).
2026-09-21 22:37:26 +03:00
catarrh ef3726441b ui: decode and abbreviate long PLMN lists in the network monitor (v2.7.16)
EF.HPLMNwAcT fell back to raw hex: efFindDecoder uppercases the requested
name but compared it against the mixed-case registry names
('EF.HPLMNwAcT'), and the monitor passes no FID, so the lookup failed.
Name matching is now case-insensitive, which also fixes EF.PLMNwAcT,
EF.OPLMNwAcT, EF.PLMNsel, EF.KcGPRS and EF.LOCIGPRS for name-only callers.

The decoded HPLMNwAcT list can still be long (one entry per PLMN/AcT
combination), so netStatePlmnList keeps the first three networks and
appends a '… +N' counter; the row tooltip keeps the full decoded list.

- tests: registry case-insensitivity, netStatePlmnList limit, HPLMNwAcT
  summary abbreviation; help EN/RU.
2026-09-21 00:18:36 +03:00
catarrh 4730e81ec2 ui: show raw and decoded comparisons together, with labelled columns (v2.7.15)
Content mismatches in profile checks and snapshot comparisons used to
replace the raw expected/actual pair with the decoded per-field table
whenever a decoder could see a difference.

- The raw comparison is always shown first (heading + expected/actual
  rows); the decoded per-field table follows when the decoder finds
  differing fields.
- The decoded table gets a column-header row carrying the same
  expected/actual labels (profile/snapshot names in a comparison) that
  the raw rows and the FCI diff table use.
- Matching decoded values keep the 'Decoded values match; raw bytes
  differ' note and show no decoded table.
- tests: ef_decode report test extended (raw + decoded + column headers,
  custom labels, matching-decoded note); help EN/RU.
2026-09-21 00:09:39 +03:00
catarrh bfb455b3c8 ui: content-sized label column in decoded field tables (v2.7.14)
The decoded view used a fixed 10rem right-aligned label column, so short
labels pushed the values ~168px to the right — for transparent files the
block looked like indented record data.  efRenderFieldsHtml now uses a
grid with grid-template-columns: max-content 1fr: labels stay right
aligned and values stay aligned, but the column is only as wide as the
widest label of the block.  Applies to the file manager decoded view and
the snapshot Decoded block (transparent and per-record fields alike).

- tests: efRenderFieldsHtml markup (grid, no w-40) and decoded view.
2026-09-20 23:56:40 +03:00
catarrh b1539d7cd5 net: network-state monitor and permanent-rejection FPLMN (v2.7.0)
server:
- netsim: LOCI/PSLOCI dummy builders take a status; the EPSLOCI dummy is
  wiped to 0B F6 + FF per UICC_NAA.md C3; roaming_denied now emulates the
  permanent 'PLMN not allowed' rejection (C3a): status 010, EPSNSC dropped,
  EF.FPLMN append with TS 31.102 4.2.16 shift semantics and a home-PLMN
  guard (HPLMNwAcT/EHPLMN, IMSI fallback), optional 'Rejection: write FPLMN'
  toggle; write steps carry the logical key; SCENARIO_SERVICE map;
  insert_fplmn/fplmn_entries/parse_imsi helpers
- netstate.py: cached per-session monitor state for the 12 network EFs,
  step-based patch, simulated service state, derived location with country/
  operator (optional MCC/MNC list) and roaming class
- server: monitor read at equip right after a readable ICCID (skipped
  otherwise), cleared on card removal; GET /api/net-state and POST
  /api/net-state-refresh; net-sim patches the cache from the written bytes
  and re-reads EF.IMSI; Location-status events set the service state and
  re-read EF.IMSI (multi-IMSI applets)

frontend:
- Phone tab: 'Network state' panel next to Network simulation with the
  simulated service badge (Undefined until simulated; normal/limited/no
  service + rejection marker), location/roaming line, compact per-file
  summaries with full-decode tooltips and a Refresh button; no card polling
- EF decoders: EF.FPLMN (FFFFFF gaps are not terminators) and EF.EHPLMN
- i18n EN/RU, help updated; SW cache simple-v203

tests: 295 Python / 453 frontend
2026-09-20 12:26:17 +03:00
catarrh eb83238ae7 EF content decoders: decoded fields in the file manager, snapshots, checks and comparisons (v2.4.0)
Client-side, offline decoder layer (ported from simtrace-analyser, verified
against the pinned specs and pySim test vectors):
- file manager Decoded pill: decoded field table instead of the raw pySim
  JSON dump (per-record fields for record files); the server's
  read_*_decoded JSON stays behind a 'pySim JSON (server)' disclosure;
  switching Raw/Decoded re-reads the open file
- snapshot view: decoded field block for transparent files and a per-record
  decoded summary for record files
- profile check / snapshot comparison report: content mismatches of files
  with a decoder render as a per-field decoded diff (only the differing
  fields, expected | actual); the raw expected/actual pair is kept when the
  decoded values match
- coverage: ICCID, IMSI/IST, UST/SST, LI/PL, SPN, PLMNsel/PLMNwAcT/
  OPLMNwAcT/HPLMNwAcT, OPL, SPDI, PNN, LOCI/PSLOCI/EPSLOCI/EPSNSC/LOCIGPRS,
  Kc/KcGPRS, ACC, PHASE, CBMI/CBMID/CBMIR, ECC, AD, ACL, SMSP, SMS, ARR, DIR,
  IMPI/DOMAIN/IMPU, ADN/FDN/SDN/MSISDN/LND/BDN, EXT1-5, SUME (TS 51.011
  §10.3.34); unknown files fall back to raw
- new frontend/tests/ef_decode.test.js (14 tests); help EN/RU + READMEs
  document the decoded views; version 2.4.0, SW cache simple-v191
- also fix the README/RUS snapshot-comparison text: comparison is always
  exact (no content masking)
2026-09-19 21:07:30 +03:00