Infer the card's ETSI release from its installed uicc.toolkit version

The explorer's card-resources block now names the card's ETSI release, using
the same mapping as the CAP analysis (capmem.ETSI_TOOLKIT_RELEASE: uicc.toolkit
version -> REL-N, basis in brackets; the live card's 1.12 -> REL-15/16/17).
The table is mirrored in the PWA (drift-guarded by tests/test_cap_memory.py,
like JC_FRAMEWORK_SDK); the version comes from the expanded registry's CE tag
and degrades to the version hint when the listing has none; SIM-only cards (no
uicc.toolkit) get no label, the same rule as SIM-only CAPs.

- cardEtsiRelease(elfs) (pure) + UICC_TOOLKIT_AID / ETSI_TOOLKIT_RELEASE in the
  PWA; rendered after the free-memory lines with a tooltip naming the basis.
- Tests: helper vectors (1.12/1.11/1.5, unknown version, versionless,
  SIM-only), the rendering guard, and the table/AID drift guard.
- Help EN/RU; sw cache simple-v354.
This commit is contained in:
2026-10-02 00:48:45 +03:00
parent 6e4eb5932c
commit 00181ba3ad
6 changed files with 91 additions and 4 deletions
+14
View File
@@ -407,6 +407,20 @@ class TestCapAnalyzer(unittest.TestCase):
pwa = dict(re.findall(r"'([\d.]+)':\s*'([^']+)'", m.group(1)))
self.assertEqual(pwa, capmem.JC_FRAMEWORK_JDK)
def test_etsi_table_matches_the_pwa(self):
# the PWA infers the card's ETSI release from its installed
# uicc.toolkit version with the same table as the CAP analysis
# (drift guard, like JC_FRAMEWORK_SDK above)
html = pathlib.Path(__file__).resolve().parents[1].joinpath(
'frontend', 'index.html').read_text(encoding='utf-8')
m = re.search(r"const ETSI_TOOLKIT_RELEASE = \{(.*?)\};", html, re.S)
self.assertIsNotNone(m, 'ETSI_TOOLKIT_RELEASE not found in index.html')
pwa = dict(re.findall(r"'([\d.]+)':\s*'([^']+)'", m.group(1)))
self.assertEqual(pwa, capmem.ETSI_TOOLKIT_RELEASE)
a = re.search(r"const UICC_TOOLKIT_AID = '([0-9A-F]+)';", html)
self.assertIsNotNone(a, 'UICC_TOOLKIT_AID not found in index.html')
self.assertEqual(a.group(1), capmem.UICC_TOOLKIT_AID)
def test_platform_requirement_from_the_framework_import(self):
# java.lang only: no Java Card level named, but the int flag shows
report, _ = capmem.analyze_bytes(