ui: rename the SCP81 script templates to Explore ISD / Delete AID (v3.1.3)
'Explore' and 'Delete' were ambiguous next to the other SCP81 actions. - template selector: Explore -> Explore ISD, Delete -> Delete AID (EN/RU); - a new Explore script is named 'Explore ISD'; the Delete template keeps its count-based name (e.g. 'Delete 2 AIDs'); - new scriptKindLabel() maps the stored kinds (unchanged: explore/delete/install/empty, so existing localStorage scripts keep working) to those labels and is now used for the scripts table kind column, which used to print the raw lowercase kind untranslated; - docs: help EN/RU, README/RUS, docs/api.md examples, AGENTS; - sw.js simple-v238.
This commit is contained in:
@@ -624,9 +624,9 @@ The **Scripts** pill manages named APDU lists stored in `localStorage` (`simple_
|
|||||||
| Template | What it builds |
|
| Template | What it builds |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Empty** | an empty list |
|
| **Empty** | an empty list |
|
||||||
| **Explore** | the reference administration sequence (`GET DATA FF21`, GET STATUS ISD/ELF/application listings, `GET DATA 0085`); long listings auto-continue through `SW 6310/CAFE` pages |
|
| **Explore ISD** | the reference administration sequence (`GET DATA FF21`, GET STATUS ISD/ELF/application listings, `GET DATA 0085`); long listings auto-continue through `SW 6310/CAFE` pages |
|
||||||
| **Install from .cap** | INSTALL [for load] → LOAD ×N → INSTALL [for install] from a `.cap` (optional SD AID, install/STK parameters, make selectable) via `POST /api/scp81/gen-install`; the file is only used to generate the APDUs — it is not stored, not even its name |
|
| **Install from .cap** | INSTALL [for load] → LOAD ×N → INSTALL [for install] from a `.cap` (optional SD AID, install/STK parameters, make selectable) via `POST /api/scp81/gen-install`; the file is only used to generate the APDUs — it is not stored, not even its name |
|
||||||
| **Delete** | DELETE APDUs from an AID list (one per line) with P2 = object only / object and related objects |
|
| **Delete AID** | DELETE APDUs from an AID list (one per line) with P2 = object only / object and related objects |
|
||||||
|
|
||||||
The table lists each script with kind, APDU count and creation time; **Edit** opens the name + APDU editor and **Delete** removes it. Over a session the server serves one C-APDU per card POST and tracks execution: the card reports status in its next POST (`X-Admin-Script-Status`), a session that dies resends only the unexecuted APDUs (`X-Admin-Resume` continues, a fresh dialog restarts), and a completed script is closed with `204 No Content`. The Remote APDU → **RAM/GP** builder can feed a command chain straight into the run with **Queue in SCP81**.
|
The table lists each script with kind, APDU count and creation time; **Edit** opens the name + APDU editor and **Delete** removes it. Over a session the server serves one C-APDU per card POST and tracks execution: the card reports status in its next POST (`X-Admin-Script-Status`), a session that dies resends only the unexecuted APDUs (`X-Admin-Resume` continues, a fresh dialog restarts), and a completed script is closed with `204 No Content`. The Remote APDU → **RAM/GP** builder can feed a command chain straight into the run with **Queue in SCP81**.
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -595,9 +595,9 @@ Delivery PoR (SPI2 `01`) проще — карта возвращает PoR на
|
|||||||
| Шаблон | Что строит |
|
| Шаблон | Что строит |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Empty** | пустой список |
|
| **Empty** | пустой список |
|
||||||
| **Explore** | эталонная административная последовательность (`GET DATA FF21`, листинги GET STATUS ISD/ELF/приложений, `GET DATA 0085`); длинные листинги автоматически продолжаются страницами `SW 6310/CAFE` |
|
| **Explore ISD** | эталонная административная последовательность (`GET DATA FF21`, листинги GET STATUS ISD/ELF/приложений, `GET DATA 0085`); длинные листинги автоматически продолжаются страницами `SW 6310/CAFE` |
|
||||||
| **Install from .cap** | INSTALL [for load] → LOAD ×N → INSTALL [for install] из `.cap` (опционально SD AID, параметры install/STK, make selectable) через `POST /api/scp81/gen-install`; файл используется только для генерации APDU — он не сохраняется, как и его имя |
|
| **Install from .cap** | INSTALL [for load] → LOAD ×N → INSTALL [for install] из `.cap` (опционально SD AID, параметры install/STK, make selectable) через `POST /api/scp81/gen-install`; файл используется только для генерации APDU — он не сохраняется, как и его имя |
|
||||||
| **Delete** | APDU DELETE из списка AID (по одному в строке) с P2 = object only / object and related objects |
|
| **Delete AID** | APDU DELETE из списка AID (по одному в строке) с P2 = object only / object and related objects |
|
||||||
|
|
||||||
Таблица показывает имя, тип, число APDU и время создания каждого скрипта; **Edit** открывает редактор имени и списка APDU, **Delete** удаляет скрипт. В ходе сессии сервер отдаёт по одному C-APDU на каждый POST карты и отслеживает выполнение: карта сообщает статус в следующем POST (`X-Admin-Script-Status`), оборвавшаяся сессия досылает только невыполненные APDU (`X-Admin-Resume` продолжает, новый диалог начинает заново), а завершённый скрипт закрывается ответом `204 No Content`. Конструктор RAM/GP вкладки Remote APDU может отправить цепочку команд прямо в прогон кнопкой **«В очередь SCP81»**.
|
Таблица показывает имя, тип, число APDU и время создания каждого скрипта; **Edit** открывает редактор имени и списка APDU, **Delete** удаляет скрипт. В ходе сессии сервер отдаёт по одному C-APDU на каждый POST карты и отслеживает выполнение: карта сообщает статус в следующем POST (`X-Admin-Script-Status`), оборвавшаяся сессия досылает только невыполненные APDU (`X-Admin-Resume` продолжает, новый диалог начинает заново), а завершённый скрипт закрывается ответом `204 No Content`. Конструктор RAM/GP вкладки Remote APDU может отправить цепочку команд прямо в прогон кнопкой **«В очередь SCP81»**.
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -788,7 +788,7 @@ Keys are never stored or logged.
|
|||||||
{"action": "start", "mode": "tls", "host": "127.0.0.1", "port": 8443,
|
{"action": "start", "mode": "tls", "host": "127.0.0.1", "port": 8443,
|
||||||
"psk_map": [{"identity": "89012345678901234567",
|
"psk_map": [{"identity": "89012345678901234567",
|
||||||
"psk_hex": "00112233445566778899aabbccddeeff"}],
|
"psk_hex": "00112233445566778899aabbccddeeff"}],
|
||||||
"script": ["80CAFF2100", "80F28002024F0000"], "script_kind": "Explore"}
|
"script": ["80CAFF2100", "80F28002024F0000"], "script_kind": "Explore ISD"}
|
||||||
```
|
```
|
||||||
|
|
||||||
`script` is the APDU list served to the card (an explicit list, or `none`);
|
`script` is the APDU list served to the card (an explicit list, or `none`);
|
||||||
@@ -873,7 +873,7 @@ Returns the configured command script and the execution state:
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{"script": ["80CAFF2100", "80F28002024F0000"], "next": 2, "total": 2,
|
{"script": ["80CAFF2100", "80F28002024F0000"], "next": 2, "total": 2,
|
||||||
"done": [0, 1], "kind": "Explore",
|
"done": [0, 1], "kind": "Explore ISD",
|
||||||
"pending": {"index": 17, "pos": null, "page": true, "apdu": "80F28003024F0000"},
|
"pending": {"index": 17, "pos": null, "page": true, "apdu": "80F28003024F0000"},
|
||||||
"pages": 11, "pages_queued": 0, "complete": false,
|
"pages": 11, "pages_queued": 0, "complete": false,
|
||||||
"results": [{"index": 1, "pos": 0, "page": false, "sw": "9000",
|
"results": [{"index": 1, "pos": 0, "page": false, "sw": "9000",
|
||||||
|
|||||||
@@ -338,9 +338,9 @@
|
|||||||
<p class="text-sm mb-2">Именованные списки APDU хранятся локально (<code class="font-mono text-sm">simple_scripts</code>) и передаются серверу при старте слушателя. Каждый список — последовательность hex C-APDU (по одной в строке; допускаются комментарии <code class="font-mono text-sm">#</code>/<code class="font-mono text-sm">;</code>). Кнопка <strong>Новый</strong> создаёт список из шаблона:</p>
|
<p class="text-sm mb-2">Именованные списки APDU хранятся локально (<code class="font-mono text-sm">simple_scripts</code>) и передаются серверу при старте слушателя. Каждый список — последовательность hex C-APDU (по одной в строке; допускаются комментарии <code class="font-mono text-sm">#</code>/<code class="font-mono text-sm">;</code>). Кнопка <strong>Новый</strong> создаёт список из шаблона:</p>
|
||||||
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
||||||
<li><strong>Empty</strong> — начать с пустого списка.</li>
|
<li><strong>Empty</strong> — начать с пустого списка.</li>
|
||||||
<li><strong>Explore</strong> — эталонная административная последовательность (<code class="font-mono text-sm">GET DATA FF21</code>, листинги GET STATUS ISD/ELF/приложений, <code class="font-mono text-sm">GET DATA 0085</code>); длинные листинги автоматически продолжаются страницами <code class="font-mono text-sm">SW 6310/CAFE</code>.</li>
|
<li><strong>Explore ISD</strong> — эталонная административная последовательность (<code class="font-mono text-sm">GET DATA FF21</code>, листинги GET STATUS ISD/ELF/приложений, <code class="font-mono text-sm">GET DATA 0085</code>); длинные листинги автоматически продолжаются страницами <code class="font-mono text-sm">SW 6310/CAFE</code>.</li>
|
||||||
<li><strong>Install from .cap</strong> — выберите <code class="font-mono text-sm">.cap</code>, при необходимости SD AID, параметры install/STK и <em>Make selectable</em>; кнопка <strong>Сгенерировать</strong> строит INSTALL [for load] → LOAD ×N → INSTALL [for install]. Файл используется только для генерации APDU — он не сохраняется, как и его имя.</li>
|
<li><strong>Install from .cap</strong> — выберите <code class="font-mono text-sm">.cap</code>, при необходимости SD AID, параметры install/STK и <em>Make selectable</em>; кнопка <strong>Сгенерировать</strong> строит INSTALL [for load] → LOAD ×N → INSTALL [for install]. Файл используется только для генерации APDU — он не сохраняется, как и его имя.</li>
|
||||||
<li><strong>Delete</strong> — список AID (по одному в строке) и P2 (<em>object only</em> / <em>object and related objects</em>) → APDU DELETE.</li>
|
<li><strong>Delete AID</strong> — список AID (по одному в строке) и P2 (<em>object only</em> / <em>object and related objects</em>) → APDU DELETE.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="text-sm mb-3">Таблица показывает имя, тип, число APDU и время создания каждого скрипта, а также кнопки <strong>Редактировать</strong> и <strong>Удалить</strong>; в редакторе есть поле имени и текстовая область APDU. В ходе сессии сервер отдаёт по одному C-APDU на каждый POST карты и отслеживает выполнение: карта сообщает статус в следующем POST (<code class="font-mono text-sm">X-Admin-Script-Status</code>), оборвавшаяся сессия досылает только невыполненные APDU (<code class="font-mono text-sm">X-Admin-Resume</code> продолжает, новый диалог начинает заново), а завершённый скрипт закрывается ответом <code class="font-mono text-sm">204 No Content</code>. Конструктор RAM/GP вкладки Remote APDU может отправить цепочку команд прямо в прогон кнопкой <strong>«В очередь SCP81»</strong>.</p>
|
<p class="text-sm mb-3">Таблица показывает имя, тип, число APDU и время создания каждого скрипта, а также кнопки <strong>Редактировать</strong> и <strong>Удалить</strong>; в редакторе есть поле имени и текстовая область APDU. В ходе сессии сервер отдаёт по одному C-APDU на каждый POST карты и отслеживает выполнение: карта сообщает статус в следующем POST (<code class="font-mono text-sm">X-Admin-Script-Status</code>), оборвавшаяся сессия досылает только невыполненные APDU (<code class="font-mono text-sm">X-Admin-Resume</code> продолжает, новый диалог начинает заново), а завершённый скрипт закрывается ответом <code class="font-mono text-sm">204 No Content</code>. Конструктор RAM/GP вкладки Remote APDU может отправить цепочку команд прямо в прогон кнопкой <strong>«В очередь SCP81»</strong>.</p>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
+2
-2
@@ -338,9 +338,9 @@
|
|||||||
<p class="text-sm mb-2">Named APDU lists stored locally (<code class="font-mono text-sm">simple_scripts</code>) and sent to the server when a listener starts. Each list is a sequence of hex C-APDUs (one per line; <code class="font-mono text-sm">#</code>/<code class="font-mono text-sm">;</code> comments allowed). <strong>New</strong> creates one from a template:</p>
|
<p class="text-sm mb-2">Named APDU lists stored locally (<code class="font-mono text-sm">simple_scripts</code>) and sent to the server when a listener starts. Each list is a sequence of hex C-APDUs (one per line; <code class="font-mono text-sm">#</code>/<code class="font-mono text-sm">;</code> comments allowed). <strong>New</strong> creates one from a template:</p>
|
||||||
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
||||||
<li><strong>Empty</strong> — start from scratch.</li>
|
<li><strong>Empty</strong> — start from scratch.</li>
|
||||||
<li><strong>Explore</strong> — the reference administration sequence (<code class="font-mono text-sm">GET DATA FF21</code>, GET STATUS ISD/ELF/application listings, <code class="font-mono text-sm">GET DATA 0085</code>); long listings auto-continue through the <code class="font-mono text-sm">SW 6310/CAFE</code> pages.</li>
|
<li><strong>Explore ISD</strong> — the reference administration sequence (<code class="font-mono text-sm">GET DATA FF21</code>, GET STATUS ISD/ELF/application listings, <code class="font-mono text-sm">GET DATA 0085</code>); long listings auto-continue through the <code class="font-mono text-sm">SW 6310/CAFE</code> pages.</li>
|
||||||
<li><strong>Install from .cap</strong> — pick a <code class="font-mono text-sm">.cap</code> plus optional SD AID, install/STK parameters and <em>make selectable</em>; <strong>Generate</strong> builds INSTALL [for load] → LOAD ×N → INSTALL [for install]. The file is only used to generate the APDUs — it is not stored, not even its name.</li>
|
<li><strong>Install from .cap</strong> — pick a <code class="font-mono text-sm">.cap</code> plus optional SD AID, install/STK parameters and <em>make selectable</em>; <strong>Generate</strong> builds INSTALL [for load] → LOAD ×N → INSTALL [for install]. The file is only used to generate the APDUs — it is not stored, not even its name.</li>
|
||||||
<li><strong>Delete</strong> — AID list (one per line) and P2 (<em>object only</em> / <em>object and related objects</em>) → DELETE APDUs.</li>
|
<li><strong>Delete AID</strong> — AID list (one per line) and P2 (<em>object only</em> / <em>object and related objects</em>) → DELETE APDUs.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="text-sm mb-3">The table lists each script with its kind, APDU count and creation time, plus <strong>Edit</strong> and <strong>Delete</strong>; the editor has a name field and the APDU textarea. Over a session the server serves one C-APDU per card POST and tracks execution: the card reports status in its next POST (<code class="font-mono text-sm">X-Admin-Script-Status</code>), a session that dies resends only the unexecuted APDUs (<code class="font-mono text-sm">X-Admin-Resume</code> continues, a fresh dialog restarts), and a completed script is closed with <code class="font-mono text-sm">204 No Content</code>. The Remote APDU tab's RAM/GP builder can feed a command chain straight into the run with <strong>Queue in SCP81</strong>.</p>
|
<p class="text-sm mb-3">The table lists each script with its kind, APDU count and creation time, plus <strong>Edit</strong> and <strong>Delete</strong>; the editor has a name field and the APDU textarea. Over a session the server serves one C-APDU per card POST and tracks execution: the card reports status in its next POST (<code class="font-mono text-sm">X-Admin-Script-Status</code>), a session that dies resends only the unexecuted APDUs (<code class="font-mono text-sm">X-Admin-Resume</code> continues, a fresh dialog restarts), and a completed script is closed with <code class="font-mono text-sm">204 No Content</code>. The Remote APDU tab's RAM/GP builder can feed a command chain straight into the run with <strong>Queue in SCP81</strong>.</p>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
+17
-6
@@ -1180,9 +1180,9 @@
|
|||||||
<label class="block mb-1 text-xs font-medium text-gray-600 dark:text-slate-400" data-l10n="New script from">New script from</label>
|
<label class="block mb-1 text-xs font-medium text-gray-600 dark:text-slate-400" data-l10n="New script from">New script from</label>
|
||||||
<select id="scripts-template" onchange="scriptsTemplateChanged()" class="border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800">
|
<select id="scripts-template" onchange="scriptsTemplateChanged()" class="border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800">
|
||||||
<option value="empty" data-l10n="Empty">Empty</option>
|
<option value="empty" data-l10n="Empty">Empty</option>
|
||||||
<option value="explore" data-l10n="Explore">Explore</option>
|
<option value="explore" data-l10n="Explore ISD">Explore ISD</option>
|
||||||
<option value="install" data-l10n="Install from .cap">Install from .cap</option>
|
<option value="install" data-l10n="Install from .cap">Install from .cap</option>
|
||||||
<option value="delete" data-l10n="Delete">Delete</option>
|
<option value="delete" data-l10n="Delete AID">Delete AID</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button id="scripts-new-btn" onclick="scriptsNew()" class="px-3 py-1.5 text-sm rounded bg-blue-600 text-white hover:bg-blue-700" data-l10n="New">New</button>
|
<button id="scripts-new-btn" onclick="scriptsNew()" class="px-3 py-1.5 text-sm rounded bg-blue-600 text-white hover:bg-blue-700" data-l10n="New">New</button>
|
||||||
@@ -1436,7 +1436,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.1.2';
|
const SIMPLE_VERSION = '3.1.3';
|
||||||
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
|
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
|
||||||
|
|
||||||
// ===== Tab switching =====
|
// ===== Tab switching =====
|
||||||
@@ -9472,7 +9472,7 @@ function scriptsNew() {
|
|||||||
const tpl = document.getElementById('scripts-template').value;
|
const tpl = document.getElementById('scripts-template').value;
|
||||||
scriptsMsg('');
|
scriptsMsg('');
|
||||||
if (tpl === 'empty') { scriptsEdit(null, 'empty', '', []); return; }
|
if (tpl === 'empty') { scriptsEdit(null, 'empty', '', []); return; }
|
||||||
if (tpl === 'explore') { scriptsEdit(null, 'explore', 'Explore', SCP81_EXPLORE_APDUS.slice()); return; }
|
if (tpl === 'explore') { scriptsEdit(null, 'explore', 'Explore ISD', SCP81_EXPLORE_APDUS.slice()); return; }
|
||||||
// Install/delete: fill the parameter form above, then press Generate.
|
// Install/delete: fill the parameter form above, then press Generate.
|
||||||
scriptsTemplateChanged();
|
scriptsTemplateChanged();
|
||||||
}
|
}
|
||||||
@@ -9547,6 +9547,16 @@ function scriptsDelete(id) {
|
|||||||
scriptsPersist();
|
scriptsPersist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Script template kind -> display label. The stored kind stays
|
||||||
|
// 'explore'/'delete'/'install'/'empty' (existing localStorage scripts).
|
||||||
|
function scriptKindLabel(kind) {
|
||||||
|
const k = String(kind || '').toLowerCase();
|
||||||
|
if (k === 'explore') return t('Explore ISD');
|
||||||
|
if (k === 'delete') return t('Delete AID');
|
||||||
|
if (k === 'install') return t('Install from .cap');
|
||||||
|
return t('Empty');
|
||||||
|
}
|
||||||
|
|
||||||
function scriptsRender() {
|
function scriptsRender() {
|
||||||
const tbody = document.getElementById('scripts-tbody');
|
const tbody = document.getElementById('scripts-tbody');
|
||||||
if (!tbody) return;
|
if (!tbody) return;
|
||||||
@@ -9558,7 +9568,7 @@ function scriptsRender() {
|
|||||||
for (const s of scripts) {
|
for (const s of scripts) {
|
||||||
html += '<tr class="border-b border-gray-100 dark:border-slate-700">';
|
html += '<tr class="border-b border-gray-100 dark:border-slate-700">';
|
||||||
html += '<td class="py-1 px-2 font-medium">' + esc(s.name) + '</td>';
|
html += '<td class="py-1 px-2 font-medium">' + esc(s.name) + '</td>';
|
||||||
html += '<td class="py-1 px-2 text-xs text-gray-500 dark:text-slate-400">' + esc(t(s.kind || 'empty')) + '</td>';
|
html += '<td class="py-1 px-2 text-xs text-gray-500 dark:text-slate-400">' + esc(scriptKindLabel(s.kind)) + '</td>';
|
||||||
html += '<td class="py-1 px-2 font-mono text-xs">' + ((s.apdus || []).length) + '</td>';
|
html += '<td class="py-1 px-2 font-mono text-xs">' + ((s.apdus || []).length) + '</td>';
|
||||||
html += '<td class="py-1 px-2 text-xs">' + esc((s.created || '').slice(0, 10)) + '</td>';
|
html += '<td class="py-1 px-2 text-xs">' + esc((s.created || '').slice(0, 10)) + '</td>';
|
||||||
html += '<td class="py-1 px-2 whitespace-nowrap">' +
|
html += '<td class="py-1 px-2 whitespace-nowrap">' +
|
||||||
@@ -13909,7 +13919,8 @@ const LANG_RU = {
|
|||||||
'Listener': 'Слушатель',
|
'Listener': 'Слушатель',
|
||||||
'Scripts': 'Скрипты',
|
'Scripts': 'Скрипты',
|
||||||
'Empty': 'Пустой',
|
'Empty': 'Пустой',
|
||||||
'Explore': 'Обзор',
|
'Explore ISD': 'Обзор ISD',
|
||||||
|
'Delete AID': 'Удалить AID',
|
||||||
'New': 'Новый',
|
'New': 'Новый',
|
||||||
'New script from': 'Новый скрипт из',
|
'New script from': 'Новый скрипт из',
|
||||||
'Generate': 'Сгенерировать',
|
'Generate': 'Сгенерировать',
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
const CACHE = 'simple-v237';
|
const CACHE = 'simple-v238';
|
||||||
const URLS = [
|
const URLS = [
|
||||||
'index.html',
|
'index.html',
|
||||||
'help.html',
|
'help.html',
|
||||||
|
|||||||
@@ -31,11 +31,20 @@ eval(extractFunc(html, 'scp81LogLine'));
|
|||||||
eval(extractFunc(html, 'scp81LogEntryHtml'));
|
eval(extractFunc(html, 'scp81LogEntryHtml'));
|
||||||
eval(extractFunc(html, 'scp81GroupResults'));
|
eval(extractFunc(html, 'scp81GroupResults'));
|
||||||
eval(extractFunc(html, 'scp81ScriptStateText'));
|
eval(extractFunc(html, 'scp81ScriptStateText'));
|
||||||
|
eval(extractFunc(html, 'scriptKindLabel'));
|
||||||
global.esc = (s) => String(s == null ? '' : s)
|
global.esc = (s) => String(s == null ? '' : s)
|
||||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||||
|
|
||||||
test('explore template is the reference administration sequence', () => {
|
test('scriptKindLabel maps the stored kinds to the template labels', () => {
|
||||||
const m = /const SCP81_EXPLORE_APDUS = \[(.*?)\];/s.exec(html);
|
assert.strictEqual(scriptKindLabel('explore'), 'Explore ISD');
|
||||||
|
assert.strictEqual(scriptKindLabel('Explore'), 'Explore ISD');
|
||||||
|
assert.strictEqual(scriptKindLabel('delete'), 'Delete AID');
|
||||||
|
assert.strictEqual(scriptKindLabel('install'), 'Install from .cap');
|
||||||
|
assert.strictEqual(scriptKindLabel('empty'), 'Empty');
|
||||||
|
assert.strictEqual(scriptKindLabel(undefined), 'Empty');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('explore template is the reference administration sequence', () => { const m = /const SCP81_EXPLORE_APDUS = \[(.*?)\];/s.exec(html);
|
||||||
assert.ok(m, 'SCP81_EXPLORE_APDUS not found');
|
assert.ok(m, 'SCP81_EXPLORE_APDUS not found');
|
||||||
const apdus = [...m[1].matchAll(/'([0-9A-F]+)'/g)].map(x => x[1]);
|
const apdus = [...m[1].matchAll(/'([0-9A-F]+)'/g)].map(x => x[1]);
|
||||||
assert.deepStrictEqual(apdus, ['80CAFF2100', '80F28002024F0000', '80CA008500',
|
assert.deepStrictEqual(apdus, ['80CAFF2100', '80F28002024F0000', '80CA008500',
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "pysim-simple-server"
|
name = "pysim-simple-server"
|
||||||
version = "3.1.2"
|
version = "3.1.3"
|
||||||
description = "HTTP REST server wrapping pysim for the SIMple PWA"
|
description = "HTTP REST server wrapping pysim for the SIMple PWA"
|
||||||
requires-python = ">=3.8"
|
requires-python = ">=3.8"
|
||||||
# pysim is a git-only dependency installed explicitly by setup.bat/setup.sh.
|
# pysim is a git-only dependency installed explicitly by setup.bat/setup.sh.
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ from osmocom.tlv import BER_TLV_IE
|
|||||||
from osmocom.utils import rpad
|
from osmocom.utils import rpad
|
||||||
|
|
||||||
|
|
||||||
VERSION = '3.1.2'
|
VERSION = '3.1.3'
|
||||||
|
|
||||||
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