diff --git a/frontend/index.html b/frontend/index.html index ed02af4..5b817e5 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -857,8 +857,8 @@ - - + + @@ -1711,7 +1711,7 @@ // ===== Version ===== // Single source of truth for the PWA version: shown in the header and used // by the server version check in pysimConnect(). -const SIMPLE_VERSION = '3.6.19'; +const SIMPLE_VERSION = '3.6.20'; document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION; // ===== Tab switching ===== @@ -2748,11 +2748,13 @@ function ramQuotaValue(n) { // The applet-specific prefix of the install parameters, in the vendor's // order: `C9 ` + `EF `. -// The server appends the STK (`EA`/`EF+CA`) part after it. +// The server appends the STK (`EA`/`EF+CA`) part after it. C9 is mandatory +// in the Install Parameters (GP Table 11-49), so an empty field is sent as +// `C9 00` - like the reference tools; a prefix without C9 makes the card +// reject the data field with 6A80 (live 2026-09-28). function ramParamsPrefix(c9Hex, c7, c8) { const c9 = (c9Hex || '').replace(/[^0-9a-fA-F]/g, '').toUpperCase(); - let out = ''; - if (c9) out += 'C9' + berLenStr(c9.length / 2) + c9; + let out = 'C9' + berLenStr(c9.length / 2) + c9; let ef = ''; if (String(c7 ?? '') !== '' && !isNaN(parseInt(c7, 10))) ef += 'C7' + ramQuotaValue(c7); if (String(c8 ?? '') !== '' && !isNaN(parseInt(c8, 10))) ef += 'C8' + ramQuotaValue(c8); @@ -2772,7 +2774,7 @@ function updateInstallParamsHex() { const el = document.getElementById('ram-install-params-hex'); // The field carries extra raw TLVs; the generated prefix is shown in the // placeholder so the composed parameters stay visible. - el.placeholder = prefix ? prefix + ' …' : 'C9 TLV'; + el.placeholder = prefix ? prefix + ' …' : 'extra TLVs (optional)'; } // ===== GSM 7-bit alphabet ===== @@ -16813,6 +16815,7 @@ const LANG_RU = { 'Select a card preset with keys first (RAM subtab → Card preset)': 'Сначала выберите пресет карты с ключами (RAM → Пресет карты)', 'Select a .cap file': 'Выберите файл .cap', 'RAM install (CAP file)': 'RAM-установка (файл CAP)', + 'Extra install parameters (hex, optional)': 'Дополнительные параметры установки (hex, опционально)', 'Install parameters (hex, optional)': 'Параметры установки (hex, опционально)', 'STK parameters (hex, optional)': 'STK-параметры (hex, опционально)', 'Make selectable': 'Сделать выбираемым', diff --git a/frontend/sw.js b/frontend/sw.js index 23e6c45..ead91e0 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'simple-v292'; +const CACHE = 'simple-v293'; const URLS = [ 'index.html', 'help.html', diff --git a/frontend/tests/stk_params.test.js b/frontend/tests/stk_params.test.js index b980665..08cbde3 100644 --- a/frontend/tests/stk_params.test.js +++ b/frontend/tests/stk_params.test.js @@ -131,11 +131,13 @@ test('adfAidFromFci extracts the DF name (tag 84) from an FCI', () => { test('ramParamsPrefix composes C9 + EF (C7/C8) like the vendor scripts', () => { // The vendor's working install (samples/uicc/applets/STK3): // C9 22 EF 08 C7 02 0000 C8 02 0000 EA ... - assert.strictEqual(ramParamsPrefix('', '', ''), ''); + // C9 is mandatory (GP Table 11-49): an empty field is sent as C9 00 - + // without it the card rejects the data field with 6A80 (live 2026-09-28). + assert.strictEqual(ramParamsPrefix('', '', ''), 'C900'); assert.strictEqual(ramParamsPrefix('082905112000012066', '', ''), 'C909082905112000012066'); - assert.strictEqual(ramParamsPrefix('', '0', '0'), 'EF08C7020000C8020000'); - assert.strictEqual(ramParamsPrefix('', '32768', ''), 'EF06C70400008000'); + assert.strictEqual(ramParamsPrefix('', '0', '0'), 'C900EF08C7020000C8020000'); + assert.strictEqual(ramParamsPrefix('', '32768', ''), 'C900EF06C70400008000'); assert.strictEqual(ramParamsPrefix('AA', '', '1234'), 'C901AAEF04C80204D2'); }); diff --git a/pyproject.toml b/pyproject.toml index d4b0614..2224f0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pysim-simple-server" -version = "3.6.19" +version = "3.6.20" description = "HTTP REST server wrapping pysim for the SIMple PWA" requires-python = ">=3.8" # pysim is a git-only dependency installed explicitly by setup.bat/setup.sh. diff --git a/pysim_simple_server/server.py b/pysim_simple_server/server.py index c5aaf32..4388753 100644 --- a/pysim_simple_server/server.py +++ b/pysim_simple_server/server.py @@ -31,7 +31,7 @@ from osmocom.tlv import BER_TLV_IE from osmocom.utils import rpad -VERSION = '3.6.19' +VERSION = '3.6.20' MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE