Command filter: FETCH and TERMINAL RESPONSE are separate entries (v2.7.1)

- the old "FETCH: ANY PROACTIVE" grouping label is gone: filter_label() now
  gives every command its own label, so the menu lists FETCH and TERMINAL
  RESPONSE individually — the multi-select filter (and the presets) cover the
  combinations that the grouping used to bundle
- the proactive presets keep their meaning: they name FETCH and TERMINAL
  PROFILE and reach the rest (a TERMINAL RESPONSE included) through the SW
  91xx rule; selecting FETCH now also brings its GET RESPONSE, which carries
  the fetched proactive command
- tests: the proactive-preset case follows the split (a TERMINAL RESPONSE is
  covered by 91xx, not by its name) plus a new case pinning the separate
  labels and the FETCH/GR pairing; 527 Python + 73 Node tests
- PWA_VERSION/pyproject/version.py 2.7.1, SW cache simtrace-analyser-v81
This commit is contained in:
catarrh committed 2026-10-17 23:58:23 +03:00
1 parent e0134c769a
commit 024527ada4
6 files changed
+30 -10

No files matched your search

+6 -4
View File
@@ -630,7 +630,9 @@ function filter_label(msg) {
const d = msg.decoded; const d = msg.decoded;
if (d) { if (d) {
if (d.ins_name === 'ENVELOPE') return 'ENVELOPE'; if (d.ins_name === 'ENVELOPE') return 'ENVELOPE';
if (d.ins_name === 'FETCH' || d.ins_name === 'TERMINAL RESPONSE') return 'FETCH: ANY PROACTIVE'; // Every command keeps its own label (the filter is multi-select, so
// FETCH and TERMINAL RESPONSE are picked individually — or through
// the proactive preset's SW 91xx rule).
if (d.ins_name) return d.ins_name; if (d.ins_name) return d.ins_name;
} }
return _fallback_label(msg); return _fallback_label(msg);
@@ -2348,12 +2350,12 @@ const FILTER_PRESETS = [
id: 'preset:proactive', name: 'Proactive sessions', id: 'preset:proactive', name: 'Proactive sessions',
// FETCH / TERMINAL PROFILE plus every proactive-session initiator: // FETCH / TERMINAL PROFILE plus every proactive-session initiator:
// a command the card answers with SW 91xx. // a command the card answers with SW 91xx.
labels: ['FETCH: ANY PROACTIVE', 'TERMINAL PROFILE'], labels: ['FETCH', 'TERMINAL PROFILE'],
test: m => _sw1(m) === 0x91, test: m => _sw1(m) === 0x91,
}, },
{ {
id: 'preset:proactive-events', name: 'Proactive + events', id: 'preset:proactive-events', name: 'Proactive + events',
labels: ['FETCH: ANY PROACTIVE', 'TERMINAL PROFILE', 'ENVELOPE'], labels: ['FETCH', 'TERMINAL PROFILE', 'ENVELOPE'],
test: m => _sw1(m) === 0x91, test: m => _sw1(m) === 0x91,
}, },
{ {
@@ -3344,7 +3346,7 @@ function onSearchChange() {
} }
// ──────────────────── Versioning ──────────────────── // ──────────────────── Versioning ────────────────────
const PWA_VERSION = '2.7.0'; const PWA_VERSION = '2.7.1';
const MIN_SERVER_VERSION = '2.3.0'; const MIN_SERVER_VERSION = '2.3.0';
function parseVersion(v) { function parseVersion(v) {
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE = 'simtrace-analyser-v80'; const CACHE = 'simtrace-analyser-v81';
const PRECACHE = [ const PRECACHE = [
'index.html', 'index.html',
+20 -2
View File
@@ -26,6 +26,8 @@ eval(
); );
let el = () => ({}); let el = () => ({});
function filterLabelOf(m) { return filter_label(m); }
const INS = { const INS = {
SELECT: 'a4', 'READ BINARY': 'b0', 'READ RECORD': 'b2', SELECT: 'a4', 'READ BINARY': 'b0', 'READ RECORD': 'b2',
'UPDATE BINARY': 'd6', 'UPDATE RECORD': 'dc', 'UPDATE BINARY': 'd6', 'UPDATE RECORD': 'dc',
@@ -73,15 +75,31 @@ test('the GET RESPONSE linkage follows the selected commands', () => {
test('the proactive preset: FETCH, TERMINAL PROFILE and SW 91xx initiators', () => { test('the proactive preset: FETCH, TERMINAL PROFILE and SW 91xx initiators', () => {
const set = new Set(['preset:proactive']); const set = new Set(['preset:proactive']);
assert.equal(matchesFilter(msg('FETCH'), 0, set), true); assert.equal(matchesFilter(msg('FETCH'), 0, set), true);
assert.equal(matchesFilter(msg('TERMINAL RESPONSE'), 0, set), true);
assert.equal(matchesFilter(msg('TERMINAL PROFILE'), 0, set), true); assert.equal(matchesFilter(msg('TERMINAL PROFILE'), 0, set), true);
// A TERMINAL RESPONSE comes along through its 91xx answer, not its name.
assert.equal(matchesFilter(msg('TERMINAL RESPONSE', { sw1: '91', sw2: '00' }), 0, set), true);
assert.equal(matchesFilter(msg('ENVELOPE', { sw1: '91', sw2: '30' }), 0, set), true); assert.equal(matchesFilter(msg('ENVELOPE', { sw1: '91', sw2: '30' }), 0, set), true);
assert.equal(matchesFilter(msg('UPDATE BINARY', { sw1: '91', sw2: '00' }), 0, set), true); assert.equal(matchesFilter(msg('UPDATE BINARY', { sw1: '91', sw2: '00' }), 0, set), true);
// Novelties: a plain ENVELOPE (90 00) and unrelated commands stay out. // A plain ENVELOPE/TERMINAL RESPONSE (90 00) and unrelated commands stay out.
assert.equal(matchesFilter(msg('ENVELOPE'), 0, set), false); assert.equal(matchesFilter(msg('ENVELOPE'), 0, set), false);
assert.equal(matchesFilter(msg('TERMINAL RESPONSE'), 0, set), false);
assert.equal(matchesFilter(msg('SELECT'), 0, set), false); assert.equal(matchesFilter(msg('SELECT'), 0, set), false);
}); });
test('FETCH and TERMINAL RESPONSE are separate commands now', () => {
// Every command keeps its own label; the multi-select filter (or the
// preset's SW 91xx rule) covers the combinations.
assert.equal(filterLabelOf(msg('FETCH')), 'FETCH');
assert.equal(filterLabelOf(msg('TERMINAL RESPONSE')), 'TERMINAL RESPONSE');
const set = new Set(['cmd:FETCH']);
assert.equal(matchesFilter(msg('FETCH'), 0, set), true);
assert.equal(matchesFilter(msg('TERMINAL RESPONSE'), 0, set), false);
// The FETCH's GET RESPONSE (the proactive command itself) follows it.
const gr = msg('GET RESPONSE', { response_for: 'FETCH' });
STATE = { messages: [msg('FETCH'), gr] };
assert.equal(matchesFilter(gr, 1, set), true);
});
test('the proactive+events preset adds ENVELOPE', () => { test('the proactive+events preset adds ENVELOPE', () => {
const set = new Set(['preset:proactive-events']); const set = new Set(['preset:proactive-events']);
assert.equal(matchesFilter(msg('ENVELOPE'), 0, set), true); assert.equal(matchesFilter(msg('ENVELOPE'), 0, set), true);
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.backends._legacy:_Backend"
[project] [project]
name = "simtrace-analyser" name = "simtrace-analyser"
version = "2.7.0" version = "2.7.1"
description = "SIMtrace Analyser — APDU trace analyser for GSMTAP/PCAP captures (bundles the simtrace2-pysniff utility)" description = "SIMtrace Analyser — APDU trace analyser for GSMTAP/PCAP captures (bundles the simtrace2-pysniff utility)"
readme = {file = "README.md", content-type = "text/markdown"} readme = {file = "README.md", content-type = "text/markdown"}
license = {text = "GPL-2.0-or-later"} license = {text = "GPL-2.0-or-later"}
+1 -1
View File
@@ -1,3 +1,3 @@
"""Single source of truth for the SIMtrace Analyser version.""" """Single source of truth for the SIMtrace Analyser version."""
__version__ = '2.7.0' __version__ = '2.7.1'
+1 -1
View File
@@ -224,7 +224,7 @@ class TestImportEndpoint(unittest.TestCase):
class TestVersion(unittest.TestCase): class TestVersion(unittest.TestCase):
def test_package_version(self): def test_package_version(self):
from simtrace2_pysniff import __version__ from simtrace2_pysniff import __version__
self.assertEqual(__version__, '2.7.0') self.assertEqual(__version__, '2.7.1')
def test_status_includes_version(self): def test_status_includes_version(self):
import os import os