Подключение к локальному pysim-simple-server для работы с картой: введите URL сервера (по умолчанию http://127.0.0.1:8080) и нажмите Подключиться. Область статуса показывает состояние ридера/карты, а Подключить карту (пере)инициализирует карту после вставки. Подвкладки: Файловый менеджер, Командная строка pySim и Отправка APDU. «Профайлер» и «Симулятор телефона» — отдельные вкладки верхнего уровня.
6.1 Файловый менеджер
-
Дерево файловой системы отображается слева; выбор файла открывает панель деталей справа. Элементы сгруппированы: DF выше EF, сортировка по FID или символьному имени (пиллы и кнопка «Проверить все файлы» закреплены над прокручиваемым деревом; выбор сохраняется в localStorage). При выборе файла над содержимым также показываются FID, тип файла, размер / структура записей и декодированный FCI.
+
Дерево файловой системы отображается слева; выбор файла открывает панель деталей справа. Элементы сгруппированы: DF выше EF, сортировка по FID или символьному имени (пиллы и кнопка «Проверить все файлы» закреплены над прокручиваемым деревом; выбор сохраняется в localStorage). При выборе файла над содержимым также показываются FID, тип файла, размер / структура записей и декодированный FCI — в рамке с символьным именем файла.
Читать сырые данные / Декодировать — чтение выбранного файла в виде hex-дампа или таблицы декодированных полей (клиентские декодеры EF: IMSI, ICCID, SPN, списки PLMN, LOCI/PSLOCI/EPSLOCI, ADN/MSISDN, таблицы сервисов, SUME, …); серверный pySim JSON того же чтения остаётся доступен в свёрнутом блоке pySim JSON (сервер). Подсвеченная кнопка — текущий вид; нажатие любой из них (пере)читывает файл. «Декодировать» недоступна, если для файла нет клиентского декодера (проверка по имени/FID до чтения).
Редактировать сырые данные — изменение hex-данных, Сохранить для записи (или Отмена); transparent-файлы редактируются в textarea, record-файлы — по одному полю на запись с флажками выбора. Декодированный вид доступен только для чтения — «Редактировать сырые данные» сначала переключает на hex-вид и при необходимости читает файл.
Connects to a local pysim-simple-server for live card operations: enter the server URL (default http://127.0.0.1:8080) and press Connect. The status area shows the reader/card state, and Equip card (re)initializes the card after insertion. Sub-tabs: File manager, pySim command line, and Raw APDU. The Profiler and Phone simulator are separate top-level tabs.
6.1 File manager
-
The file system tree is displayed on the left; selecting a file opens its detail pane on the right. Entries are grouped with DFs above EFs and sorted by FID or symbolic Name (pills pinned above the scrolling tree together with Probe all files; the choice is remembered in localStorage). Selecting a file also shows its FID, file type, size / record layout and the decoded FCI above the content pane.
+
The file system tree is displayed on the left; selecting a file opens its detail pane on the right. Entries are grouped with DFs above EFs and sorted by FID or symbolic Name (pills pinned above the scrolling tree together with Probe all files; the choice is remembered in localStorage). Selecting a file also shows its FID, file type, size / record layout and the decoded FCI — in a bordered block labelled with the file’s symbolic name — above the content pane.
Read raw / Read decoded — read the selected file as a hex dump or as a decoded field table (client-side EF decoders: IMSI, ICCID, SPN, PLMN lists, LOCI/PSLOCI/EPSLOCI, ADN/MSISDN, service tables, SUME, …); the server-side pySim JSON of the same read stays available in the collapsed pySim JSON (server) disclosure. The highlighted pill is the current view; clicking either pill (re-)reads the file. Read decoded is disabled when the client-side decoders do not cover the file (name/FID check, before reading).
Edit raw — edit the raw hex data, Save to write back (or Cancel); transparent files use a textarea, record files one input per record with selection checkboxes. The decoded view is read-only — Edit raw switches to the hex view first and reads the file if needed.
diff --git a/frontend/index.html b/frontend/index.html
index 8ca9abd..93cf656 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -1413,7 +1413,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 = '2.7.11';
+const SIMPLE_VERSION = '2.7.12';
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
// ===== Tab switching =====
@@ -7152,7 +7152,7 @@ async function pysimFsToggleDir(name) {
let pysimFsSelected = null;
-function pysimFsInfoHtml(sel) {
+function pysimFsInfoHtml(sel, name) {
if (!sel) return '';
const num = v => (v === null || v === undefined) ? null : String(v);
const attrs = [];
@@ -7164,7 +7164,11 @@ function pysimFsInfoHtml(sel) {
let html = '';
if (attrs.length) html += '
';
+ html += '';
}
return html;
}
@@ -7181,7 +7185,7 @@ async function pysimFsClickFile(name) {
pysimFsRenderTree();
}
pysimFsSelected = name;
- document.getElementById('pysim-fs-info').innerHTML = exists ? pysimFsInfoHtml(sel) : '';
+ document.getElementById('pysim-fs-info').innerHTML = exists ? pysimFsInfoHtml(sel, name) : '';
document.getElementById('pysim-fs-content').innerHTML = '';
document.getElementById('pysim-fs-status').textContent = exists ? '' : '✗ File not found on card';
if (exists) {
diff --git a/frontend/sw.js b/frontend/sw.js
index 4c31bdc..2cca930 100644
--- a/frontend/sw.js
+++ b/frontend/sw.js
@@ -1,4 +1,4 @@
-const CACHE = 'simple-v214';
+const CACHE = 'simple-v215';
const URLS = [
'index.html',
'help.html',
diff --git a/frontend/tests/html.test.js b/frontend/tests/html.test.js
index f9457a7..7c3495d 100644
--- a/frontend/tests/html.test.js
+++ b/frontend/tests/html.test.js
@@ -205,7 +205,7 @@ test('file manager shows FCI info and keeps the selection in state, not the DOM'
const content = html.indexOf('id="pysim-fs-content"');
assert.ok(detail !== -1 && info > detail && info < content, 'pysim-fs-info must sit above the content');
assert.ok(html.includes('function pysimFsInfoHtml'));
- assert.ok(html.includes("pysimFsInfoHtml(sel)"));
+ assert.ok(html.includes('pysimFsInfoHtml(sel, name)'));
assert.ok(!html.includes('pysim-fs-filename'));
assert.ok(html.includes('let pysimFsSelected = null;'));
assert.ok(html.includes('pysimFsSelected = name;'));
diff --git a/frontend/tests/profiler.test.js b/frontend/tests/profiler.test.js
index 1013176..7ee2ef6 100644
--- a/frontend/tests/profiler.test.js
+++ b/frontend/tests/profiler.test.js
@@ -762,7 +762,7 @@ test('fcpDiffHtml highlights differing FCI parameters', () => {
test('pysimFsInfoHtml shows FID, type, size and the decoded FCI', () => {
global.t = s => s;
const hex = '621A82054221000F0583026F4F8A01058B036F06098002004B8801B0';
- const out = pysimFsInfoHtml({ fid: '6f4f', file_type: 'linear_fixed', file_size: 75, record_len: 15, num_of_rec: 5, fci_hex: hex });
+ const out = pysimFsInfoHtml({ fid: '6f4f', file_type: 'linear_fixed', file_size: 75, record_len: 15, num_of_rec: 5, fci_hex: hex }, 'EF.SAMPLE');
assert.ok(out.includes('FID: 6F4F'), out);
assert.ok(out.includes('File type: linear_fixed'), out);
assert.ok(out.includes('Size: 75'), out);
@@ -776,6 +776,10 @@ test('pysimFsInfoHtml shows FID, type, size and the decoded FCI', () => {
// the short file identifier is merged into the file identifier row
assert.ok(out.includes('6F4F · Short file identifier: 22'), out);
assert.ok(!out.includes('
Short file identifier:'), out);
+ // the FCI sits in a bordered container whose legend is the symbolic name,
+ // below the metadata line
+ assert.ok(out.indexOf('FID: 6F4F') < out.indexOf('