Drop the invented "SMS-related" / "CB-related" filter categories: those files are service-declared and are already reached through their per-service options (per-spec service names). Bump VERSION/pyproject/ PWA header to 3.40.1 and the SW cache to simple-v486.
This commit is contained in:
1 parent
98926833f7
commit
1f8fa54c49
6 files changed
+44
-44
No files matched your search
@@ -9,6 +9,17 @@ every change carries a descriptive commit message.
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [3.40.1] — 2026-10-26
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **File filter: drop the "SMS-related" / "CB-related" categories.** Those
|
||||||
|
files are service-declared and already reachable through their per-service
|
||||||
|
filter options, which carry the per-spec service names ("Short Message
|
||||||
|
Storage (SMS)", "SMS Parameters (SMSP)", "Short Message Status Reports
|
||||||
|
(SMSR)", "Cell Broadcast Message Identifier (CBMI)", "Cell Broadcast
|
||||||
|
Message Identifier Ranges (CBMIR)").
|
||||||
|
|
||||||
## [3.40.0] — 2026-10-26
|
## [3.40.0] — 2026-10-26
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
+3
-11
@@ -1989,7 +1989,7 @@
|
|||||||
// ===== Version =====
|
// ===== Version =====
|
||||||
// Single source of truth for the PWA version: shown in the header and used
|
// Single source of truth for the PWA version: shown in the header and used
|
||||||
// by the server version check in pysimConnect().
|
// by the server version check in pysimConnect().
|
||||||
const SIMPLE_VERSION = '3.40.0';
|
const SIMPLE_VERSION = '3.40.1';
|
||||||
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
|
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
|
||||||
|
|
||||||
// ===== view history (the browser Back/Forward buttons) =====
|
// ===== view history (the browser Back/Forward buttons) =====
|
||||||
@@ -16094,8 +16094,8 @@ function pysimFsSetSort(mode) {
|
|||||||
// can belong to several criteria (EF.SPN is a provider name and the file of
|
// can belong to several criteria (EF.SPN is a provider name and the file of
|
||||||
// the "Service Provider Name" service). `all` is the exclusive default.
|
// the "Service Provider Name" service). `all` is the exclusive default.
|
||||||
// The categories are shown under three headings (`group`): the subscriber
|
// The categories are shown under three headings (`group`): the subscriber
|
||||||
// data, the network-selection data, and services (the SMS files plus one
|
// data, the network-selection data, and services (one option per file-backed
|
||||||
// option per file-backed feature of the service cross-reference).
|
// feature of the service cross-reference).
|
||||||
const FS_FILTER_ALL = 'all';
|
const FS_FILTER_ALL = 'all';
|
||||||
// "Custom files" is not a name-based criterion: it matches the injected
|
// "Custom files" is not a name-based criterion: it matches the injected
|
||||||
// custom-file nodes by their `custom` flag (user-chosen names).
|
// custom-file nodes by their `custom` flag (user-chosen names).
|
||||||
@@ -16111,12 +16111,6 @@ const FS_FILTER_GROUPS = [
|
|||||||
{ id: 'wlan', label: 'WLAN / I-WLAN', group: 'PLMN', files: [
|
{ id: 'wlan', label: 'WLAN / I-WLAN', group: 'PLMN', files: [
|
||||||
'EF.UPLMNWLAN', 'EF.OPLMNWLAN', 'EF.WRI', 'EF.HWSIDL', 'EF.WEHPLMNPI', 'EF.WHPI',
|
'EF.UPLMNWLAN', 'EF.OPLMNWLAN', 'EF.WRI', 'EF.HWSIDL', 'EF.WEHPLMNPI', 'EF.WHPI',
|
||||||
'EF.WLRPLMN', 'EF.HPLMNDAI'] },
|
'EF.WLRPLMN', 'EF.HPLMNDAI'] },
|
||||||
// EF.PSISMSC is a standard name pySim does not model, so it has no tree
|
|
||||||
// node to match - it stays listed for completeness.
|
|
||||||
{ id: 'sms', label: 'SMS-related', group: 'Services', files: [
|
|
||||||
'EF.SMS', 'EF.SMSS', 'EF.SMSP', 'EF.SMSR', 'EF.PSISMSC'] },
|
|
||||||
{ id: 'cb', label: 'CB-related', group: 'Services', files: [
|
|
||||||
'EF.CBMI', 'EF.CBMID', 'EF.CBMIR'] },
|
|
||||||
];
|
];
|
||||||
const FS_FILTER_GROUP_ORDER = ['Identifiers', 'PLMN', 'Services'];
|
const FS_FILTER_GROUP_ORDER = ['Identifiers', 'PLMN', 'Services'];
|
||||||
|
|
||||||
@@ -28111,8 +28105,6 @@ const LANG_RU = {
|
|||||||
'PLMN selection': 'Выбор PLMN',
|
'PLMN selection': 'Выбор PLMN',
|
||||||
'Provider names': 'Имена операторов',
|
'Provider names': 'Имена операторов',
|
||||||
'WLAN / I-WLAN': 'WLAN / I-WLAN',
|
'WLAN / I-WLAN': 'WLAN / I-WLAN',
|
||||||
'SMS-related': 'Связанное с SMS',
|
|
||||||
'CB-related': 'Связанное с CB',
|
|
||||||
'Custom files': 'Пользовательские файлы',
|
'Custom files': 'Пользовательские файлы',
|
||||||
'Selected: {n}': 'Выбрано: {n}',
|
'Selected: {n}': 'Выбрано: {n}',
|
||||||
'Expand all': 'Развернуть все',
|
'Expand all': 'Развернуть все',
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
const CACHE = 'simple-v485';
|
const CACHE = 'simple-v486';
|
||||||
const URLS = [
|
const URLS = [
|
||||||
'index.html',
|
'index.html',
|
||||||
'help.html',
|
'help.html',
|
||||||
|
|||||||
@@ -173,9 +173,9 @@ test('an outside click or Escape closes the menu', () => {
|
|||||||
assert.match(key[1], /pysimFsFilterToggle\(false\)/);
|
assert.match(key[1], /pysimFsFilterToggle\(false\)/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('the six category groups name their files', () => {
|
test('the four category groups name their files', () => {
|
||||||
assert.deepStrictEqual(FS_FILTER_GROUPS.map(g => g.id),
|
assert.deepStrictEqual(FS_FILTER_GROUPS.map(g => g.id),
|
||||||
['identifiers', 'plmn-selection', 'provider-names', 'wlan', 'sms', 'cb']);
|
['identifiers', 'plmn-selection', 'provider-names', 'wlan']);
|
||||||
const files = id => new Set(FS_FILTER_GROUPS.find(g => g.id === id).files);
|
const files = id => new Set(FS_FILTER_GROUPS.find(g => g.id === id).files);
|
||||||
assert.deepStrictEqual([...files('identifiers')],
|
assert.deepStrictEqual([...files('identifiers')],
|
||||||
['EF.ICCID', 'EF.IMSI', 'EF.MSISDN', 'EF.IMPI', 'EF.IMPU', 'EF.SUPI_NAI', 'EF.GID1', 'EF.GID2']);
|
['EF.ICCID', 'EF.IMSI', 'EF.MSISDN', 'EF.IMPI', 'EF.IMPU', 'EF.SUPI_NAI', 'EF.GID1', 'EF.GID2']);
|
||||||
@@ -187,8 +187,6 @@ test('the six category groups name their files', () => {
|
|||||||
assert.deepStrictEqual([...files('wlan')],
|
assert.deepStrictEqual([...files('wlan')],
|
||||||
['EF.UPLMNWLAN', 'EF.OPLMNWLAN', 'EF.WRI', 'EF.HWSIDL', 'EF.WEHPLMNPI', 'EF.WHPI',
|
['EF.UPLMNWLAN', 'EF.OPLMNWLAN', 'EF.WRI', 'EF.HWSIDL', 'EF.WEHPLMNPI', 'EF.WHPI',
|
||||||
'EF.WLRPLMN', 'EF.HPLMNDAI']);
|
'EF.WLRPLMN', 'EF.HPLMNDAI']);
|
||||||
assert.deepStrictEqual([...files('sms')], ['EF.SMS', 'EF.SMSS', 'EF.SMSP', 'EF.SMSR', 'EF.PSISMSC']);
|
|
||||||
assert.deepStrictEqual([...files('cb')], ['EF.CBMI', 'EF.CBMID', 'EF.CBMIR']);
|
|
||||||
assert.strictEqual(FS_FILTER_ALL, 'all');
|
assert.strictEqual(FS_FILTER_ALL, 'all');
|
||||||
assert.strictEqual(FS_FILTER_CUSTOM, 'custom');
|
assert.strictEqual(FS_FILTER_CUSTOM, 'custom');
|
||||||
});
|
});
|
||||||
@@ -212,12 +210,12 @@ test('the inverted index keys the uppercased names and merges memberships', () =
|
|||||||
assert.ok(ids('EF.PLMNwAcT').includes('plmn-selection'));
|
assert.ok(ids('EF.PLMNwAcT').includes('plmn-selection'));
|
||||||
assert.ok(ids('EF.SPN').includes('provider-names'));
|
assert.ok(ids('EF.SPN').includes('provider-names'));
|
||||||
assert.ok(ids('EF.SPN').includes('svc:Service Provider Name (SPN)'));
|
assert.ok(ids('EF.SPN').includes('svc:Service Provider Name (SPN)'));
|
||||||
assert.ok(ids('EF.SMS').includes('sms'));
|
// SMS/CB files are covered by their per-service options, not a category
|
||||||
assert.ok(ids('EF.SMS').includes('svc:Short Message Storage (SMS)'));
|
assert.ok(ids('EF.SMS').includes('svc:Short Message Storage (SMS)'));
|
||||||
assert.ok(ids('EF.CBMI').includes('cb'));
|
assert.ok(ids('EF.CBMI').includes('svc:Cell Broadcast Message Identifier (CBMI)'));
|
||||||
// EF.PSISMSC is only listed by the SMS category - pySim models no such
|
// EF.PSISMSC is neither a category nor a file-backed service, so nothing
|
||||||
// file, so it never matches a tree node (no service lists it either)
|
// maps it (pySim models no such file, and no service lists it either)
|
||||||
assert.deepStrictEqual([...idx.get('EF.PSISMSC')], ['sms']);
|
assert.ok(!idx.has('EF.PSISMSC'));
|
||||||
assert.ok(!fileBackedFeatures().some(n => (SERVICES_FS_MAP[n] || []).includes('EF.PSISMSC')));
|
assert.ok(!fileBackedFeatures().some(n => (SERVICES_FS_MAP[n] || []).includes('EF.PSISMSC')));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -232,12 +230,12 @@ test('a file matches the selected categories, case-insensitively', () => {
|
|||||||
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.SPN' }), true);
|
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.SPN' }), true);
|
||||||
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.PNN' }), false);
|
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.PNN' }), false);
|
||||||
});
|
});
|
||||||
withFilter(['identifiers', 'sms'], () => {
|
withFilter(['identifiers', 'svc:Short Message Status Reports (SMSR)'], () => {
|
||||||
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.IMSI' }), true);
|
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.IMSI' }), true);
|
||||||
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.SMSR' }), true);
|
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.SMSR' }), true);
|
||||||
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.SPN' }), false);
|
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.SPN' }), false);
|
||||||
});
|
});
|
||||||
withFilter(['sms'], () => {
|
withFilter(['svc:Short Message Storage (SMS)'], () => {
|
||||||
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.ECC' }), false);
|
assert.strictEqual(pysimFsFilterMatch({ name: 'EF.ECC' }), false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -320,8 +318,8 @@ test('a directory shows only on the path of a file the filter selects', () => {
|
|||||||
assert.strictEqual(pysimFsFilterShow(t.usim), true); // EF.IMSI/EF.MSISDN copies
|
assert.strictEqual(pysimFsFilterShow(t.usim), true); // EF.IMSI/EF.MSISDN copies
|
||||||
assert.strictEqual(pysimFsFilterShow(t.wlan), false);
|
assert.strictEqual(pysimFsFilterShow(t.wlan), false);
|
||||||
});
|
});
|
||||||
withFilter(['cb'], () => {
|
withFilter(['svc:Cell Broadcast Message Identifier (CBMI)'], () => {
|
||||||
assert.strictEqual(pysimFsFilterShow(t.gsm), true); // EF.CBMI/CBMID/CBMIR
|
assert.strictEqual(pysimFsFilterShow(t.gsm), true); // EF.CBMI
|
||||||
assert.strictEqual(pysimFsFilterShow(t.telecom), false);
|
assert.strictEqual(pysimFsFilterShow(t.telecom), false);
|
||||||
assert.strictEqual(pysimFsFilterShow(t.wlan), false);
|
assert.strictEqual(pysimFsFilterShow(t.wlan), false);
|
||||||
});
|
});
|
||||||
@@ -377,13 +375,11 @@ test('the standard list gives a name every tree it lives in', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('the selection resolves to the paths of its files', () => {
|
test('the selection resolves to the paths of its files', () => {
|
||||||
withFilter(['cb'], () => {
|
withFilter(['svc:Cell Broadcast Message Identifier (CBMI)'], () => {
|
||||||
const paths = pysimFsFilterMatchingPaths();
|
const paths = pysimFsFilterMatchingPaths();
|
||||||
assert.ok(paths instanceof Set, 'expected a Set');
|
assert.ok(paths instanceof Set, 'expected a Set');
|
||||||
assert.deepStrictEqual(Array.from(paths).sort(), [
|
assert.deepStrictEqual(Array.from(paths).sort(), [
|
||||||
'ADF.USIM-NON-IMSI/6F45', 'ADF.USIM-NON-IMSI/6F48', 'ADF.USIM-NON-IMSI/6F50',
|
'ADF.USIM-NON-IMSI/6F45', 'ADF.USIM/6F45', 'MF/7F20/6F45',
|
||||||
'ADF.USIM/6F45', 'ADF.USIM/6F48', 'ADF.USIM/6F50',
|
|
||||||
'MF/7F20/6F45', 'MF/7F20/6F48', 'MF/7F20/6F50',
|
|
||||||
]);
|
]);
|
||||||
// cached for the same selection
|
// cached for the same selection
|
||||||
assert.strictEqual(pysimFsFilterMatchingPaths(), paths);
|
assert.strictEqual(pysimFsFilterMatchingPaths(), paths);
|
||||||
@@ -429,7 +425,8 @@ test('the menu lists all, custom, the three headings and the services', () => {
|
|||||||
// the categories sit under their headings
|
// the categories sit under their headings
|
||||||
assert.ok(out.indexOf('data-filter="provider-names"') < out.indexOf('>PLMN</div>'));
|
assert.ok(out.indexOf('data-filter="provider-names"') < out.indexOf('>PLMN</div>'));
|
||||||
assert.ok(out.indexOf('data-filter="plmn-selection"') > out.indexOf('>PLMN</div>'));
|
assert.ok(out.indexOf('data-filter="plmn-selection"') > out.indexOf('>PLMN</div>'));
|
||||||
assert.ok(out.indexOf('data-filter="sms"') > out.indexOf('>Services</div>'));
|
// the per-service options sit under the Services heading
|
||||||
|
assert.ok(out.indexOf('data-filter="svc:') > out.indexOf('>Services</div>'));
|
||||||
const boxes = renderedBoxes();
|
const boxes = renderedBoxes();
|
||||||
assert.strictEqual(boxes.length, 2 + FS_FILTER_GROUPS.length + fsFilterServiceOptions().length);
|
assert.strictEqual(boxes.length, 2 + FS_FILTER_GROUPS.length + fsFilterServiceOptions().length);
|
||||||
assert.strictEqual(boxes[0].id, 'all');
|
assert.strictEqual(boxes[0].id, 'all');
|
||||||
@@ -513,11 +510,11 @@ test('the button summary names the single entry or counts the selection', () =>
|
|||||||
assert.strictEqual(summary(['all']), 'All');
|
assert.strictEqual(summary(['all']), 'All');
|
||||||
// an empty selection also means everything
|
// an empty selection also means everything
|
||||||
assert.strictEqual(summary([]), 'All');
|
assert.strictEqual(summary([]), 'All');
|
||||||
assert.strictEqual(summary(['all', 'sms']), 'All');
|
assert.strictEqual(summary(['all', 'plmn-selection']), 'All');
|
||||||
assert.strictEqual(summary(['custom']), 'Custom files');
|
assert.strictEqual(summary(['custom']), 'Custom files');
|
||||||
assert.strictEqual(summary(['plmn-selection']), 'PLMN selection');
|
assert.strictEqual(summary(['plmn-selection']), 'PLMN selection');
|
||||||
assert.strictEqual(summary(['svc:Service Provider Name (SPN)']), 'Service Provider Name (SPN)');
|
assert.strictEqual(summary(['svc:Service Provider Name (SPN)']), 'Service Provider Name (SPN)');
|
||||||
assert.strictEqual(summary(['sms', 'cb']), 'Selected: 2');
|
assert.strictEqual(summary(['plmn-selection', 'wlan']), 'Selected: 2');
|
||||||
// an unknown id falls back to itself
|
// an unknown id falls back to itself
|
||||||
assert.strictEqual(summary(['providers']), 'providers');
|
assert.strictEqual(summary(['providers']), 'providers');
|
||||||
});
|
});
|
||||||
@@ -550,18 +547,18 @@ test('the checkbox rows keep "all" exclusive and persist the selection', () => {
|
|||||||
assert.strictEqual(_store.simple_fs_filter, '["all"]');
|
assert.strictEqual(_store.simple_fs_filter, '["all"]');
|
||||||
assert.strictEqual(_treeRenders, 1);
|
assert.strictEqual(_treeRenders, 1);
|
||||||
// choosing a category drops "all"
|
// choosing a category drops "all"
|
||||||
pysimFsFilterSetEntry('sms', true);
|
pysimFsFilterSetEntry('provider-names', true);
|
||||||
assert.deepStrictEqual([...pysimFsFilter], ['sms']);
|
assert.deepStrictEqual([...pysimFsFilter], ['provider-names']);
|
||||||
assert.strictEqual(_store.simple_fs_filter, '["sms"]');
|
assert.strictEqual(_store.simple_fs_filter, '["provider-names"]');
|
||||||
assert.strictEqual(_treeRenders, 3); // render + the auto-expand's render
|
assert.strictEqual(_treeRenders, 3); // render + the auto-expand's render
|
||||||
assert.strictEqual(box('sms').checked, true);
|
assert.strictEqual(box('provider-names').checked, true);
|
||||||
assert.strictEqual(box('all').checked, false);
|
assert.strictEqual(box('all').checked, false);
|
||||||
assert.strictEqual(dom.btn.textContent, 'SMS-related');
|
assert.strictEqual(dom.btn.textContent, 'Provider names');
|
||||||
// several categories stay selected
|
// several categories stay selected
|
||||||
pysimFsFilterSetEntry('identifiers', true);
|
pysimFsFilterSetEntry('identifiers', true);
|
||||||
assert.deepStrictEqual([...pysimFsFilter], ['sms', 'identifiers']);
|
assert.deepStrictEqual([...pysimFsFilter], ['provider-names', 'identifiers']);
|
||||||
// unchecking one keeps the other
|
// unchecking one keeps the other
|
||||||
pysimFsFilterSetEntry('sms', false);
|
pysimFsFilterSetEntry('provider-names', false);
|
||||||
assert.deepStrictEqual([...pysimFsFilter], ['identifiers']);
|
assert.deepStrictEqual([...pysimFsFilter], ['identifiers']);
|
||||||
// unchecking the last one restores the default
|
// unchecking the last one restores the default
|
||||||
pysimFsFilterSetEntry('identifiers', false);
|
pysimFsFilterSetEntry('identifiers', false);
|
||||||
@@ -569,7 +566,7 @@ test('the checkbox rows keep "all" exclusive and persist the selection', () => {
|
|||||||
assert.strictEqual(_store.simple_fs_filter, '["all"]');
|
assert.strictEqual(_store.simple_fs_filter, '["all"]');
|
||||||
assert.strictEqual(box('all').checked, true);
|
assert.strictEqual(box('all').checked, true);
|
||||||
// "all" is exclusive even when another entry is selected
|
// "all" is exclusive even when another entry is selected
|
||||||
pysimFsFilter = new Set(['sms']);
|
pysimFsFilter = new Set(['provider-names']);
|
||||||
pysimFsFilterSetEntry('all', true);
|
pysimFsFilterSetEntry('all', true);
|
||||||
assert.deepStrictEqual([...pysimFsFilter], ['all']);
|
assert.deepStrictEqual([...pysimFsFilter], ['all']);
|
||||||
});
|
});
|
||||||
@@ -582,7 +579,7 @@ test('the saved selection is restored, defaulting to "all"', () => {
|
|||||||
pysimFsFilterRestore();
|
pysimFsFilterRestore();
|
||||||
assert.deepStrictEqual([...pysimFsFilter], ['providers', 'svc:Service Provider Name (SPN)']);
|
assert.deepStrictEqual([...pysimFsFilter], ['providers', 'svc:Service Provider Name (SPN)']);
|
||||||
// `all` is exclusive; an empty or broken save falls back to it
|
// `all` is exclusive; an empty or broken save falls back to it
|
||||||
_store.simple_fs_filter = JSON.stringify(['all', 'sms']);
|
_store.simple_fs_filter = JSON.stringify(['all', 'plmn-selection']);
|
||||||
pysimFsFilterRestore();
|
pysimFsFilterRestore();
|
||||||
assert.deepStrictEqual([...pysimFsFilter], ['all']);
|
assert.deepStrictEqual([...pysimFsFilter], ['all']);
|
||||||
_store.simple_fs_filter = '[]';
|
_store.simple_fs_filter = '[]';
|
||||||
@@ -636,7 +633,7 @@ test('the dropdown is re-rendered on language switch', () => {
|
|||||||
test('the filter labels have Russian entries', () => {
|
test('the filter labels have Russian entries', () => {
|
||||||
const dict = html.match(/const LANG_RU = \{([\s\S]*?)\n\};/)[1];
|
const dict = html.match(/const LANG_RU = \{([\s\S]*?)\n\};/)[1];
|
||||||
for (const key of ['All', 'Custom files', 'Identifiers', 'PLMN', 'Services', 'PLMN selection',
|
for (const key of ['All', 'Custom files', 'Identifiers', 'PLMN', 'Services', 'PLMN selection',
|
||||||
'Provider names', 'WLAN / I-WLAN', 'SMS-related', 'CB-related', 'Selected: {n}']) {
|
'Provider names', 'WLAN / I-WLAN', 'Selected: {n}']) {
|
||||||
assert.ok(dict.includes("'" + key + "':"), 'missing Russian entry: ' + key);
|
assert.ok(dict.includes("'" + key + "':"), 'missing Russian entry: ' + key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "pysim-simple-server"
|
name = "pysim-simple-server"
|
||||||
version = "3.40.0"
|
version = "3.40.1"
|
||||||
description = "HTTP REST server wrapping pysim for the SIMple PWA"
|
description = "HTTP REST server wrapping pysim for the SIMple PWA"
|
||||||
license = { text = "GPL-2.0-or-later" }
|
license = { text = "GPL-2.0-or-later" }
|
||||||
requires-python = ">=3.9"
|
requires-python = ">=3.9"
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ from osmocom.tlv import BER_TLV_IE
|
|||||||
from osmocom.utils import rpad
|
from osmocom.utils import rpad
|
||||||
|
|
||||||
|
|
||||||
VERSION = '3.40.0'
|
VERSION = '3.40.1'
|
||||||
|
|
||||||
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
|
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user