diff --git a/frontend/help-ru.html b/frontend/help-ru.html index 52aba7f..23b14b4 100644 --- a/frontend/help-ru.html +++ b/frontend/help-ru.html @@ -421,7 +421,7 @@
  • Атрибуты файла — тип файла, размер, длина записи и число записей из FCP-шаблона (любой можно оставить незаданным).
  • Проверить содержимое (опционально) — Точное (точное совпадение hex) или Маска, где ? — шаблон на один полубайт (маска без ? — совпадение префикса, например 0891 для MCC/MNC из IMSI). Для record-файлов хранится список по записям.
  • -

    Проверить карту выполняет каждое правило на подключённой карте и показывает строку прогресса и отчёт прохождения. Рядом с путём файла указывается, что именно проверялось (например, тип файла и размер, содержимое или полный FCI); если часть проверок прошла, а часть нет — каждый аспект помечается (тип файла ✓, размер ✗, содержимое ✓), а расхождения расписываются ниже. Несовпавшие сырые данные (FCI, содержимое, данные записей) показываются как поля только для чтения с моноширинным шрифтом — ожидаемое над фактическим, в одной и той же колонке — для удобного сравнения; расхождения содержимого файлов с декодером показываются декодированным сравнением по полям (только отличающиеся поля, ожидаемое и фактическое рядом; сырая пара остаётся, когда декодированные значения совпадают), а для расхождений FCI дополнительно показывается декодированное сравнение по параметрам (размер файла, дескриптор/структура, жизненный цикл, FID, SFI, проприетарные параметры…). Декодированный просмотр FCI также отображается рядом с полем FCI hex при редактировании правила. Если данные FCI повреждены, показывается всё, что удалось декодировать до места ошибки, вместе с явным сообщением об ошибке декодирования. Для record-файлов при расхождении содержимого добавляется пометка совпадающие записи: 1-5, 7-10 со списком записей, которые совпали. В отчёте поля расхождений и колонки сравнения FCI подписаны ожидалось (имя профиля) и фактически (ICCID карты), а в заголовке отчёта выводится Результаты проверки профиля: <профиль> → <ICCID карты>. Опция «Только расхождения» в заголовке отчёта скрывает все совпавшие файлы и оставляет только несовпадения и ошибки.

    +

    Проверить карту выполняет каждое правило на подключённой карте и показывает строку прогресса и отчёт прохождения. Рядом с путём файла указывается, что именно проверялось (например, тип файла и размер, содержимое или полный FCI); если часть проверок прошла, а часть нет — каждый аспект помечается (тип файла ✓, размер ✗, содержимое ✓), а расхождения расписываются ниже. Несовпавшие сырые данные (FCI, содержимое, данные записей) показываются как поля только для чтения с моноширинным шрифтом — ожидаемое над фактическим, в одной и той же колонке — для удобного сравнения; расхождения содержимого дополнительно показывают для файлов с декодером декодированное сравнение по полям (только отличающиеся поля, с заголовками колонок «ожидаемое/фактическое» над значениями; если декодированные значения совпадают, вместо таблицы выводится пометка об этом), а для расхождений FCI дополнительно показывается декодированное сравнение по параметрам (размер файла, дескриптор/структура, жизненный цикл, FID, SFI, проприетарные параметры…). Декодированный просмотр FCI также отображается рядом с полем FCI hex при редактировании правила. Если данные FCI повреждены, показывается всё, что удалось декодировать до места ошибки, вместе с явным сообщением об ошибке декодирования. Для record-файлов при расхождении содержимого добавляется пометка совпадающие записи: 1-5, 7-10 со списком записей, которые совпали. В отчёте поля расхождений и колонки сравнения FCI подписаны ожидалось (имя профиля) и фактически (ICCID карты), а в заголовке отчёта выводится Результаты проверки профиля: <профиль> → <ICCID карты>. Опция «Только расхождения» в заголовке отчёта скрывает все совпавшие файлы и оставляет только несовпадения и ошибки.

    Опции сканирования «Профиль с карты»

    Диалог сканирования запрашивает имя профиля и предлагает селектор «Проверка FCP/FCI» (те же три режима, по умолчанию Тип файла + размер (FCP)), применяемый ко всем создаваемым правилам, а также список «Игнорировать содержимое файлов» (все отмечены по умолчанию, кроме EF.ARR; флажок в заголовке отмечает или снимает весь список) часто перезаписываемых файлов, содержимое которых пропускается: EF.LOCI, EF.PSLOCI, EF.EPSLOCI, EF.5GS3GPPLOCI, EF.Keys, EF.KeysPS, EF.SMS, EF.Kc, EF.KcGPRS, EF.LOCIGPRS, EF.CBMID, EF.SMSS, EF.ACC, EF.EPSNSC, EF.START-HFN, EF.ARR. Ещё две отмеченные по умолчанию опции «Сравнивать первые 4 байта для» EF.IMSI и EF.ICCID захватывают содержимое этих файлов как маску только первых 4 байт (снимите для точного сравнения). Строка прогресса показывает N / всего файлов с текущим путём файла во время сканирования; при сканировании опции скрываются, а кнопки блокируются. Правила создаются только для файлов, которые реально существуют на карте (возвращён FCP-шаблон); отсутствующие файлы пропускаются. Пользовательские файлы из подвкладки «Пользовательские файлы» включаются с той же проверкой существования. Тот же диалог и опции использует «Профиль из снимка»: вместо карты обходятся захваченные файлы выбранного снимка; для файлов, содержимое которых не было захвачено, правило создаётся без проверки содержимого (при последующей проверке профиля они помечаются как непроверяемые).

    diff --git a/frontend/help.html b/frontend/help.html index acf9da4..7f8e9c1 100644 --- a/frontend/help.html +++ b/frontend/help.html @@ -421,7 +421,7 @@
  • File attributes — file type, size, record length and record count, taken from the FCP template (any may be left unset).
  • Check contents (optional) — Exact hex equality, or Mask where ? is a per-nibble wildcard (a mask with no ? is a prefix match, e.g. 0891 for the IMSI MCC/MNC). Record files store a per-record list.
  • -

    Check card runs every rule against the equipped card and shows a live progress line plus a pass/fail report. Each row states exactly what was verified next to the file path (e.g. filetype and size, contents or exact FCI); when some checks pass and others fail, each aspect is marked (filetype ✓, size ✗, contents ✓) with the mismatches detailed below. Mismatched raw data (FCI, contents, record data) is shown as read-only monospace fields — expected above actual, aligned in the same column — for easy comparison; content mismatches of files with a decoder are shown as a decoded per-field comparison instead (only the differing fields, expected and actual side by side; the raw pair is kept when the decoded values match), and FCI mismatches additionally show a decoded per-parameter comparison (file size, file descriptor/structure, life cycle, FID, SFI, proprietary parameters…). A decoded FCI preview is also shown beside the FCI hex field while editing a rule. If the FCI data is corrupt, whatever was decoded before the faulty part is shown together with an explicit decode-failure note. For record files with a contents mismatch, a matching records: 1-5, 7-10 note lists the records that did match. In the report the mismatch fields and FCI comparison columns are labelled expected (profile name) and actual (card ICCID), and the results header reads Profile verification results for: <profile> → <card ICCID>. An Only mismatches option in the results header hides all passing files and keeps only failures and errors.

    +

    Check card runs every rule against the equipped card and shows a live progress line plus a pass/fail report. Each row states exactly what was verified next to the file path (e.g. filetype and size, contents or exact FCI); when some checks pass and others fail, each aspect is marked (filetype ✓, size ✗, contents ✓) with the mismatches detailed below. Mismatched raw data (FCI, contents, record data) is shown as read-only monospace fields — expected above actual, aligned in the same column — for easy comparison; content mismatches additionally show, for files with a decoder, a decoded per-field comparison (only the differing fields, with expected/actual column headers above the side-by-side values; when the decoded values match, a note says so instead of the table), and FCI mismatches additionally show a decoded per-parameter comparison (file size, file descriptor/structure, life cycle, FID, SFI, proprietary parameters…). A decoded FCI preview is also shown beside the FCI hex field while editing a rule. If the FCI data is corrupt, whatever was decoded before the faulty part is shown together with an explicit decode-failure note. For record files with a contents mismatch, a matching records: 1-5, 7-10 note lists the records that did match. In the report the mismatch fields and FCI comparison columns are labelled expected (profile name) and actual (card ICCID), and the results header reads Profile verification results for: <profile> → <card ICCID>. An Only mismatches option in the results header hides all passing files and keeps only failures and errors.

    “Profile from card” scan options

    The scan dialog asks for a profile name and offers a “FCP/FCI check” selector (the same three modes above, default Filetype + size) applied to every generated rule, plus an “Ignore contents of files” checklist (all checked by default except EF.ARR; the header checkbox checks or unchecks the whole list) of frequently-overwritten files whose contents are skipped: EF.LOCI, EF.PSLOCI, EF.EPSLOCI, EF.5GS3GPPLOCI, EF.Keys, EF.KeysPS, EF.SMS, EF.Kc, EF.KcGPRS, EF.LOCIGPRS, EF.CBMID, EF.SMSS, EF.ACC, EF.EPSNSC, EF.START-HFN, EF.ARR. Two further checked-by-default options “Match first 4 bytes for” EF.IMSI and EF.ICCID capture those files’ contents as a mask of only the first 4 bytes (uncheck for exact matching). A progress line shows N / total files with the current file path while scanning; during the scan the options are hidden and the buttons are locked. Rules are created only for files that actually exist on the card (a FCP template is returned); missing files are skipped. Custom files from the Custom files sub-tab are included under the same existence check. The same dialog and options are used by Profile from snapshot, which walks the selected snapshot’s captured files instead of the card; rules for files whose contents were not captured during the scan get no content check (they are reported as unverifiable when the profile is later checked).

    diff --git a/frontend/index.html b/frontend/index.html index 9297c44..092d8c3 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.14'; +const SIMPLE_VERSION = '2.7.15'; document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION; // ===== Tab switching ===== @@ -11780,25 +11780,34 @@ function profilerRenderReport(results, labels) { const isContent = c.label === 'content' || /^content\.rec\d+$/.test(c.label); const dd = isContent && typeof efContentDiff === 'function' ? efContentDiff(r.name, efFidFromPath(r.path), String(c.expected), String(c.actual)) : null; + const inputCls = 'flex-1 min-w-0 font-mono text-xs border border-gray-300 dark:border-slate-600 rounded px-2 py-1 bg-gray-100 dark:bg-slate-800'; html += '
    '; html += '
    ' + esc(c.label) + '
    '; + // Raw bytes first: the ground truth, always shown. + html += '
    ' + esc(t('Raw comparison')) + '
    '; + html += '
    ' + + '' + esc(expLabel) + '' + + '
    '; + html += '
    ' + + '' + esc(actLabel) + '' + + '
    '; + // Per-field decoded diff, when the decoder can see one; the + // expected/actual column headers carry the comparison labels. if (dd && dd.rows.length) { - html += '
    ' + esc(t('Decoded comparison')) + ' — ' + esc(expLabel) + ' | ' + esc(actLabel) + '
    '; + html += '
    ' + esc(t('Decoded comparison')) + '
    '; + html += '
    ' + + '' + + '' + esc(expLabel) + '' + + '' + esc(actLabel) + '
    '; for (const [label, ev, av] of dd.rows) { html += '
    ' + '' + esc(label) + '' + - '' + - '' + + '' + + '' + '
    '; } - } else { - if (dd && dd.sameDecoded) html += '
    ' + esc(t('Decoded values match; raw bytes differ')) + '
    '; - html += '
    ' + - '' + esc(expLabel) + '' + - '
    '; - html += '
    ' + - '' + esc(actLabel) + '' + - '
    '; + } else if (dd && dd.sameDecoded) { + html += '
    ' + esc(t('Decoded values match; raw bytes differ')) + '
    '; } if (c.label === 'fci') html += fcpDiffHtml(String(c.expected), String(c.actual), labels); html += '
    '; @@ -13327,6 +13336,7 @@ const LANG_RU = { 'showing raw data': 'показаны сырые данные', 'No decodable fields': 'Нет декодируемых полей', 'pySim JSON (server)': 'pySim JSON (сервер)', + 'Raw comparison': 'Сравнение сырых данных', 'Decoded comparison': 'Декодированное сравнение', 'Decoded values match; raw bytes differ': 'Декодированные значения совпадают; отличаются сырые байты', 'Back to list': 'Назад к списку', diff --git a/frontend/sw.js b/frontend/sw.js index 6ed5715..b6df5ac 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'simple-v217'; +const CACHE = 'simple-v218'; const URLS = [ 'index.html', 'help.html', diff --git a/frontend/tests/ef_decode.test.js b/frontend/tests/ef_decode.test.js index 01e32ab..aed0be7 100644 --- a/frontend/tests/ef_decode.test.js +++ b/frontend/tests/ef_decode.test.js @@ -233,19 +233,32 @@ test('efRenderFieldsHtml sizes the label column to its content', () => { assert.match(efRenderFieldsHtml([]), /No decodable fields/); }); -test('profilerRenderReport shows decoded field diffs and the raw-only note', () => { +test('profilerRenderReport shows raw and decoded comparisons for content mismatches', () => { const res = { path: 'ADF.USIM/6F07', name: 'EF.IMSI', status: 'fail', checks: [{ label: 'content', expected: '082982608200002080', actual: '082982608200002081', ok: false }], }; const out = profilerRenderReport([res], null); + // the raw pair is always shown + assert.match(out, /Raw comparison/); + assert.ok(out.includes('value="082982608200002080"')); + assert.ok(out.includes('value="082982608200002081"')); + // the decoded per-field diff follows, with expected/actual column headers assert.match(out, /Decoded comparison/); assert.match(out, /IMSI/); assert.match(out, /228062800000208/); assert.match(out, /228062800000218/); + assert.match(out, /expected<\/span>actual<\/span>/); + // custom comparison labels are used for the raw rows and the decoded headers + const named = profilerRenderReport([res], { expected: 'master', actual: 'checked' }); + assert.ok(named.includes('>master')); + assert.ok(named.includes('>checked')); + // matching decoded values -> note instead of the decoded table, raw pair kept const same = profilerRenderReport([{ path: 'ADF.USIM/6F07', name: 'EF.IMSI', status: 'fail', checks: [{ label: 'content', expected: '082982608200002080', actual: '092982608200002080', ok: false }], }], null); + assert.match(same, /Raw comparison/); assert.match(same, /Decoded values match/); + assert.doesNotMatch(same, /Decoded comparison/); }); diff --git a/pyproject.toml b/pyproject.toml index 09249ea..adcc571 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pysim-simple-server" -version = "2.7.14" +version = "2.7.15" 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 ccd1f60..b72ee3f 100644 --- a/pysim_simple_server/server.py +++ b/pysim_simple_server/server.py @@ -26,7 +26,7 @@ from osmocom.tlv import BER_TLV_IE from osmocom.utils import rpad -VERSION = '2.7.14' +VERSION = '2.7.15' MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE