@@ -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