From a5f7ca840d3397d91330148dfd17048421b05aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=A2=D1=80=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Wed, 23 Sep 2026 08:34:27 +0300 Subject: [PATCH] ui: start the SELECT picker session in MF for both RFM builders The file picker's implicit current DF now defaults to MF for SIM RFM and USIM RFM alike (the real context follows the TAR the packet is sent to, TS 102 226 7.2/7.3, so the default is neutral and the per-row "starts in" selector covers ADF sessions - ADF.USIM files appear once it is switched). Tests set the ADF session explicitly where they exercise ADF-relative fills plus a new default assertion; help 2.1 EN/RU, READMEs and AGENTS updated. sw cache -> simple-v244; version stays 3.4.0. --- README.md | 2 +- README_RUS.md | 2 +- frontend/help-ru.html | 2 +- frontend/help.html | 2 +- frontend/index.html | 5 ++++- frontend/sw.js | 2 +- frontend/tests/uicc_files.test.js | 12 ++++++++++-- 7 files changed, 19 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 46d60f1..3a50bf8 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ CLA = `A0` (GSM 11.11 / ISO 7816-4). Every SELECT row offers a file picker: a filter box, an **all files** toggle, the session start root with the current DF, and the file list grouped by root (`MF`, `ADF.USIM`, ...). Picking a file fills the fields for the current method; when the method cannot express the selection the picker switches to one that can - preferring **path** (one SELECT), then **chain** - and says so, e.g. `7F106F40` (path from MF) or `7F20,6F46` (relative FID chain). - **List source**: with a card equipped the loaded file-manager tree wins (card names, probed presence; probed-absent files are hidden). Without a card, or for branches the tree has not loaded, the shipped standard list is used: `uicc_files.json`, generated from pySim's profiles/application classes by `pysim_simple_server/uicc_files.py` and drift-guarded by `tests/test_uicc_files.py`. It is specs-default until **Probe all files** runs in the file manager. Custom files are always merged. -- **Session start**: the implicit current DF follows the TAR the secured packet is sent to (UICC Shared File System RFM -> MF, TS 102 226 §7.2; ADF RFM -> its ADF, §7.3). Defaults: MF here, ADF.USIM for USIM RFM; changeable per row. +- **Session start**: the implicit current DF follows the TAR the secured packet is sent to (UICC Shared File System RFM -> MF, TS 102 226 §7.2; ADF RFM -> its ADF, §7.3). Defaults: MF for both builders; changeable per row (pick the ADF to work in an ADF session). - **Path** is the FID sequence from MF without the MF identifier (ISO 7816-4); the USIM "from current DF" variant uses the relative tail. **Chain** stays relative to the current DF and follows the TS 102 221 §11.1.1.2 FID search order (children, parent, siblings). - ADF roots are not pickable - an application is selected by AID, which the **By AID** method keeps manual (TS 102 226 §7.1 forbids P1=`04` for RFM). diff --git a/README_RUS.md b/README_RUS.md index 63aed67..9fb03e0 100644 --- a/README_RUS.md +++ b/README_RUS.md @@ -82,7 +82,7 @@ CLA = `A0` (GSM 11.11 / ISO 7816-4). У каждой строки SELECT есть выбор файла: поле фильтра, переключатель **all files**, корень начала сессии с текущим DF и список файлов по корням (`MF`, `ADF.USIM`, ...). Выбор файла заполняет поля текущего метода; если метод не может выразить выбор, помощник переключается на подходящий - предпочитая **path** (один SELECT), затем **chain** - и сообщает об этом, например `7F106F40` (путь от MF) или `7F20,6F46` (относительная цепочка FID). - **Источник списка**: при подключённой карте приоритет у загруженного дерева файлового менеджера (имена карты, проверенное наличие; отсутствующие скрываются). Без карты и для незагруженных ветвей используется поставляемый стандартный список: `uicc_files.json`, собранный из профилей/классов приложений pySim скриптом `pysim_simple_server/uicc_files.py` и проверяемый `tests/test_uicc_files.py`. До запуска **«Проверить все файлы»** список соответствует спецификациям. Пользовательские файлы добавляются всегда. -- **Начало сессии**: неявный текущий DF зависит от TAR, на который отправляется защищённый пакет (UICC Shared File System RFM -> MF, TS 102 226 §7.2; ADF RFM -> свой ADF, §7.3). По умолчанию: MF здесь и ADF.USIM для USIM RFM; меняется для каждой строки. +- **Начало сессии**: неявный текущий DF зависит от TAR, на который отправляется защищённый пакет (UICC Shared File System RFM -> MF, TS 102 226 §7.2; ADF RFM -> свой ADF, §7.3). По умолчанию: MF для обоих конструкторов; меняется для каждой строки (выберите ADF для работы в сессии ADF). - **Path** - последовательность FID от MF без идентификатора MF (ISO 7816-4); вариант USIM «from current DF» использует относительный хвост. **Chain** остаётся относительным к текущему DF и следует порядку поиска FID из TS 102 221 §11.1.1.2 (дети, родитель, соседи). - Корни ADF не выбираются - приложение выбирается по AID, и метод **By AID** остаётся ручным (TS 102 226 §7.1 запрещает P1=`04` для RFM). diff --git a/frontend/help-ru.html b/frontend/help-ru.html index 5dbe109..19488c3 100644 --- a/frontend/help-ru.html +++ b/frontend/help-ru.html @@ -98,7 +98,7 @@

У каждой строки SELECT под полями метода есть выбор файла: поле фильтра, переключатель all files, корень начала сессии с текущим DF и список файлов, сгруппированный по корню (MF, ADF.USIM, …). Выбор файла заполняет поля текущего метода; если метод не может выразить выбор, помощник переключается на подходящий — предпочитая path (один SELECT), затем chain — и пишет об этом в строке примечания, например файл из другого DF становится 7F106F40 (путь от MF) или 7F20,6F46 (относительная цепочка FID).

diff --git a/frontend/help.html b/frontend/help.html index 138f045..a240f16 100644 --- a/frontend/help.html +++ b/frontend/help.html @@ -98,7 +98,7 @@

Every SELECT row has a file picker below the method fields: a filter box, an all files toggle, the session start root with the current DF, and the file list grouped by root (MF, ADF.USIM, …). Picking a file fills the fields for the current method; when the method cannot express the selection the picker switches to one that can — preferring path (one SELECT), else chain — and says so in the note line, e.g. a file under another DF becomes 7F106F40 (path from MF) or 7F20,6F46 (relative FID chain).

diff --git a/frontend/index.html b/frontend/index.html index 4605e63..e505743 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3311,7 +3311,10 @@ function rfmFileEntries() { // packet is sent to, not on the builder, so the picker lets it be changed. function rfmStartDf(chainId) { if (!_rfmStartDf[chainId]) { - _rfmStartDf[chainId] = chainKind(chainId) === 'usim' ? 'ADF.USIM' : 'MF'; + // MF for both builders: the real implicit DF follows the TAR the + // secured packet is sent to (TS 102 226 7.2/7.3), so the picker + // starts neutral and the per-row selector covers ADF sessions. + _rfmStartDf[chainId] = 'MF'; } return _rfmStartDf[chainId]; } diff --git a/frontend/sw.js b/frontend/sw.js index cb6daa2..35b11d8 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'simple-v243'; +const CACHE = 'simple-v244'; const URLS = [ 'index.html', 'help.html', diff --git a/frontend/tests/uicc_files.test.js b/frontend/tests/uicc_files.test.js index a20eff5..f388d12 100644 --- a/frontend/tests/uicc_files.test.js +++ b/frontend/tests/uicc_files.test.js @@ -112,8 +112,10 @@ test('rfmSelectFill prefers path when the method has to switch', () => { assert.deepStrictEqual(fill, { method: 'path', fields: { path: '7F106F40', base: 'mf' }, switched: true }); // ADF entry cannot be reached from MF by FID/path/chain. assert.strictEqual(rfmSelectFill('chain-sim', 0, entry('ADF.USIM/6F07'), rfmFileEntries()), null); - // USIM RFM starts in ADF.USIM: its files are direct children, deep ones use - // the relative path from the current DF. + // USIM RFM in an ADF session (the picker defaults to MF for both + // builders, so the ADF context is selected explicitly): ADF files are + // direct children, deep ones use the relative path from the current DF. + rfmSetStartDf('chain-usim', 'ADF.USIM'); setChain('chain-usim', [row('select', { method: 'fid' })]); fill = rfmSelectFill('chain-usim', 0, entry('ADF.USIM/6F07'), rfmFileEntries()); assert.deepStrictEqual(fill, { method: 'fid', fields: { fid: '6F07' }, switched: false }); @@ -131,6 +133,7 @@ test('rfmSelectFill falls back to chain when path cannot express it', () => { // DF.GSM-ACCESS branch is not under the current DF and not in the MF tree, // so only the relative chain works. const list = rfmFileEntries(); + rfmSetStartDf('chain-usim', 'ADF.USIM'); setChain('chain-usim', [row('select', { method: 'path', path: '5F3A', base: 'df' })]); const fill = rfmSelectFill('chain-usim', 1, entry('ADF.USIM/5F3B/4F20'), list); assert.strictEqual(fill.method, 'chain'); @@ -153,6 +156,10 @@ test('rfmCurrentDf tracks the session context across rows', () => { assert.strictEqual(rfmCurrentDf('chain-sim', 2, list), 'MF/7F10'); // A path select sets the DF to the file's parent. assert.strictEqual(rfmCurrentDf('chain-sim', 3, list), 'MF/7F10'); + // The picker defaults to MF for both builders; an ADF session is explicit. + delete _rfmStartDf['chain-usim']; + assert.strictEqual(rfmStartDf('chain-usim'), 'MF'); + rfmSetStartDf('chain-usim', 'ADF.USIM'); setChain('chain-usim', [ row('select', { method: 'path', path: '5F3A', base: 'df' }), row('select', { method: 'chain', chain: '4F22' }), @@ -196,6 +203,7 @@ test('rfmFileEntries merges card tree, custom files and the standard list', () = test('rfmFileOptionsHtml labels files with their path within the root', () => { const list = rfmFileEntries(); + rfmSetStartDf('chain-usim', 'ADF.USIM'); setChain('chain-usim', [row('select', { method: 'fid' })]); const opts = rfmFileOptionsHtml('chain-usim', 0, list); // ADF.USIM session: EF.IMSI is a direct child of the root.