ui: group the TCP request with the channel/link triggers; identification packet as a same-message follow-up
The Push commands pill now has three sub-pills: Trigger (Push SMS), Store (SD admin params) and Channel / link trigger, which builds all three TS 102 226 §9 establishment requests - 01 BIP channel opening (OPEN CHANNEL), 02 CAT_TP link, 03 TCP connection - with one shared destination-port field and per-request field visibility. The TCP parameters are the OPEN CHANNEL TCP set (BIP, or a direct IP connection per TS 102 483 where supported), so 03 belongs with the other channel/link requests. The identification packet (04) is not a trigger: it presupposes an already open TCP channel and only makes sense as a follow-up in the same message, so it is no longer a standalone request. The TCP request carries an "Also send the identification packet (04) in the same message" checkbox (optional data, ICCID when empty): the preview then shows both commands (a command string sent in one secured packet) and → Expanded Script appends one 22 Command TLV per command. pushSectionApdus() returns the APDU list; 04 stays available in the RAM/GP chain's PUSH row for script sequences. Help 2.7 EN/RU, READMEs and AGENTS describe the three sub-pills and the BIP vs direct-IP nuance; sw cache -> simple-v249; version stays 3.5.0. html.test.js also asserts that the document is complete (ends with </html>, every <script> closed, the inline script parses and defines cApduSwitchSubtab): a truncated index.html made the browser fail to parse the inline script, so every onclick handler reported "function is not defined" while the Node tests still passed.
This commit is contained in:
@@ -359,7 +359,7 @@ Pastes raw APDU hex and renders a collapsible tree. It auto-detects the containe
|
||||
|
||||
### Push commands
|
||||
|
||||
Groups the commands that make the card dial out. Four sub-pills switch between the forms - Trigger (Push SMS), Store (SD admin params), BIP / CAT_TP trigger and TCP trigger - and only the selected one is shown (the two GP forms share their fields). They are delivered differently - the administration trigger is a TLV message for the Security Domain, a §9 PUSH is a C-APDU (`80 EC 01 P2`) for an application that supports BIP/CAT_TP.
|
||||
Groups the commands that make the card dial out. Three sub-pills switch between the forms - Trigger (Push SMS), Store (SD admin params) and Channel / link trigger - and only the selected one is shown (the two GP forms share their fields). They are delivered differently - the administration trigger is a TLV message for the Security Domain, a §9 PUSH is a C-APDU (`80 EC 01 P2`) for an application that supports BIP/CAT_TP.
|
||||
|
||||
#### Administration session (HTTP OTA)
|
||||
|
||||
@@ -379,10 +379,12 @@ The **Command Scripting template** checkbox wraps the whole `81` triggering comm
|
||||
|
||||
#### TS 102 226 §9 PUSH
|
||||
|
||||
Two guided sections build the §9 requests with the same encoder as the RAM/GP chain's **PUSH** row and offer **Pack into Secured packet** (TAR stays manual - the request goes to the target application) and **→ Expanded Script** (wraps the APDU in the `22` Command TLV):
|
||||
The **Channel / link trigger** sub-pill builds the §9 requests with the same encoder as the RAM/GP chain's **PUSH** row and offers **Pack into Secured packet** (TAR stays manual - the request goes to the target application) and **→ Expanded Script** (each APDU becomes a `22` Command TLV):
|
||||
|
||||
- **BIP / CAT_TP** — `01` BIP channel opening (OPEN CHANNEL COMPREHENSION-TLVs optional) or `02` CAT_TP link (destination port in transport level `3C` with protocol type 00, optional buffer size `39` / identification data `36`);
|
||||
- **TCP** — `03` TCP connection (bearer `35`, transport level `3C` with protocol type 02, destination address `3E` - `21` IPv4 / `57` IPv6 / `F0` FQDN, NAA/APN `47`) or `04` identification packet (sent over an already open channel; the ICCID is used when absent).
|
||||
- **BIP channel opening** (`01`) - OPEN CHANNEL COMPREHENSION-TLVs optional; the application issues the proactive OPEN CHANNEL itself;
|
||||
- **CAT_TP link** (`02`) - destination port in transport level `3C` with protocol type 00 (mandatory), optional buffer size `39` / identification data `36`;
|
||||
- **TCP connection** (`03`) - bearer `35`, transport level `3C` with protocol type 02, destination address `3E` (`21` IPv4 / `57` IPv6 / `F0` FQDN), NAA/APN `47`; the parameters are the OPEN CHANNEL TCP set (BIP, or a direct IP connection per TS 102 483 where supported);
|
||||
- **Identification packet** (`04`) is not a trigger - it needs an already open TCP channel, so the TCP request has an *Also send the identification packet (04)* checkbox that appends it in the same message; `04` also stays in the chain's PUSH row for scripts.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+6
-4
@@ -333,7 +333,7 @@ CLA = `80` (GlobalPlatform v2.3.1). Удалённое управление со
|
||||
|
||||
### Пуш/триггер
|
||||
|
||||
Объединяет команды, заставляющие карту выйти в сеть. Четыре подвкладки переключают формы — Trigger (Push SMS), Store (SD admin params), BIP / CAT_TP trigger и TCP trigger — показывается только выбранная (обе формы GP используют один набор полей). Доставляются они по-разному — триггер администрирования это TLV-сообщение для Security Domain, а PUSH §9 это C-APDU (`80 EC 01 P2`) для приложения с поддержкой BIP/CAT_TP.
|
||||
Объединяет команды, заставляющие карту выйти в сеть. Три подвкладки переключают формы — Trigger (Push SMS), Store (SD admin params) и «Триггер канала/линка» — показывается только выбранная (обе формы GP используют один набор полей). Доставляются они по-разному — триггер администрирования это TLV-сообщение для Security Domain, а PUSH §9 это C-APDU (`80 EC 01 P2`) для приложения с поддержкой BIP/CAT_TP.
|
||||
|
||||
#### Сессия администрирования (HTTP OTA)
|
||||
|
||||
@@ -354,10 +354,12 @@ CLA = `80` (GlobalPlatform v2.3.1). Удалённое управление со
|
||||
|
||||
#### PUSH по TS 102 226 §9
|
||||
|
||||
Два управляемых раздела собирают запросы §9 тем же кодировщиком, что и строка **PUSH** в цепочке RAM/GP, и предлагают **«Упаковать в Secured packet»** (TAR остаётся ручным — запрос адресован целевому приложению) и **→ Расширенный скрипт** (оборачивает APDU в Command TLV `22`):
|
||||
Подвкладка **«Триггер канала/линка»** собирает запросы §9 тем же кодировщиком, что и строка **PUSH** в цепочке RAM/GP, и предлагает **«Упаковать в Secured packet»** (TAR остаётся ручным — запрос адресован целевому приложению) и **→ Расширенный скрипт** (каждый APDU становится Command TLV `22`):
|
||||
|
||||
- **BIP / CAT_TP** — `01` открытие BIP-канала (COMPREHENSION-TLV OPEN CHANNEL необязательны) или `02` CAT_TP (порт назначения в transport level `3C` с типом 00, необязательные buffer size `39` / данные идентификации `36`);
|
||||
- **TCP** — `03` TCP-соединение (bearer `35`, transport level `3C` с типом 02, адрес назначения `3E` — `21` IPv4 / `57` IPv6 / `F0` FQDN, NAA/APN `47`) или `04` пакет идентификации (по уже открытому каналу, при отсутствии данных используется ICCID).
|
||||
- **Открытие BIP-канала** (`01`) — COMPREHENSION-TLV OPEN CHANNEL необязательны; проактивную команду OPEN CHANNEL выдаёт само приложение;
|
||||
- **CAT_TP** (`02`) — порт назначения в transport level `3C` с типом 00 (обязателен), необязательные buffer size `39` / данные идентификации `36`;
|
||||
- **TCP-соединение** (`03`) — bearer `35`, transport level `3C` с типом 02, адрес назначения `3E` (`21` IPv4 / `57` IPv6 / `F0` FQDN), NAA/APN `47`; это параметры OPEN CHANNEL для TCP (BIP или прямое IP-соединение по TS 102 483, где поддерживается);
|
||||
- **Пакет идентификации** (`04`) — не триггер: ему нужен уже открытый TCP-канал, поэтому у TCP-запроса есть флажок «Также отправить пакет идентификации (04)», добавляющий его в то же сообщение; `04` также остаётся в строке PUSH цепочки для сценариев.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
<p class="text-sm mb-3">Вставка raw APDU hex и отображение сворачиваемого дерева. Автоматически определяет контейнер: <strong>Expanded Script</strong> (начало <code class="font-mono text-sm">AA</code> или <code class="font-mono text-sm">AE80</code>, декодируется по ETSI TS 102 226 §5.2.1) или <strong>Compact C-APDU chain</strong> (последовательность C-APDU ISO 7816). Каждый узел показывает метку, hex и краткое описание; родительские узлы раскрываются в подэлементы.</p>
|
||||
|
||||
<h3 id="push-commands" class="text-lg font-medium mb-2">2.7 Пуш/триггер</h3>
|
||||
<p class="text-sm mb-3">Объединяет команды, заставляющие карту выйти в сеть. Четыре подвкладки переключают формы — <strong>Trigger (Push SMS)</strong>, <strong>Store (SD admin params)</strong>, <strong>BIP / CAT_TP trigger</strong> и <strong>TCP trigger</strong> — показывается только выбранная форма; обе формы GP используют один набор полей (режим меняет только обёртку payload’а, а заголовок формы указывает режим). Они из разных спецификаций и доставляются по-разному: триггер администрирования это TLV-сообщение для Security Domain (HTTP OTA), а PUSH §9 это C-APDU (<code class="font-mono text-sm">80 EC 01 P2</code>) для приложения с поддержкой BIP и/или CAT_TP.</p>
|
||||
<p class="text-sm mb-3">Объединяет команды, заставляющие карту выйти в сеть. Три подвкладки переключают формы — <strong>Trigger (Push SMS)</strong>, <strong>Store (SD admin params)</strong> и <strong>«Триггер канала/линка»</strong> — показывается только выбранная форма; обе формы GP используют один набор полей (режим меняет только обёртку payload’а, а заголовок формы указывает режим). Они из разных спецификаций и доставляются по-разному: триггер администрирования это TLV-сообщение для Security Domain (HTTP OTA), а PUSH §9 это C-APDU (<code class="font-mono text-sm">80 EC 01 P2</code>) для приложения с поддержкой BIP и/или CAT_TP.</p>
|
||||
|
||||
<h4 id="http-ota" class="font-medium mb-1">Сессия администрирования (HTTP OTA)</h4>
|
||||
<p class="text-sm mb-3">Сборка payload’ов Remote Application Management over HTTP по GlobalPlatform <strong>GPC v2.2 Amendment B v1.1</strong> (§4.7). Два режима:</p>
|
||||
@@ -253,11 +253,12 @@
|
||||
<p class="text-sm mb-2"><strong>Упаковать в Secured packet</strong> отправляет готовый payload на вкладку SCP80 для заполнения SPI/счётчика — там укажите TAR, который слушает SD (обычно TAR OTASD).</p>
|
||||
|
||||
<h4 id="push-ts102226" class="font-medium mb-1 mt-3">PUSH по TS 102 226 §9</h4>
|
||||
<p class="text-sm mb-2">Два раздела собирают запросы §9 тем же кодировщиком, что и строка <strong>PUSH</strong> в цепочке RAM/GP, показывают предпросмотр C-APDU и предлагают <strong>«Упаковать в Secured packet»</strong> (TAR остаётся ручным: запрос адресован целевому приложению, а не Security Domain) и <strong>→ Расширенный скрипт</strong> (оборачивает APDU в Command TLV <code class="font-mono text-sm">22</code> и добавляет его в конструктор Expanded Script).</p>
|
||||
<p class="text-sm mb-2">Подвкладка <strong>«Триггер канала/линка»</strong> собирает запросы §9 тем же кодировщиком, что и строка <strong>PUSH</strong> в цепочке RAM/GP, показывает предпросмотр C-APDU, и предлагает <strong>«Упаковать в Secured packet»</strong> (TAR остаётся ручным: запрос адресован целевому приложению, а не Security Domain) и <strong>→ Расширенный скрипт</strong> (оборачивает каждый APDU в Command TLV <code class="font-mono text-sm">22</code> и добавляет их в конструктор Expanded Script).</p>
|
||||
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
||||
<li><strong>BIP / CAT_TP</strong> — запрос <code class="font-mono text-sm">01</code> открытие BIP-канала (необязательные COMPREHENSION-TLV OPEN CHANNEL; при пустом значении действуют умолчания приложения) или <code class="font-mono text-sm">02</code> установление соединения CAT_TP (порт назначения в transport level <code class="font-mono text-sm">3C</code> с типом протокола 00, необязательные buffer size <code class="font-mono text-sm">39</code> / данные идентификации <code class="font-mono text-sm">36</code>).</li>
|
||||
<li><strong>TCP</strong> — запрос <code class="font-mono text-sm">03</code> TCP-соединение (bearer <code class="font-mono text-sm">35</code>, transport level <code class="font-mono text-sm">3C</code> с типом протокола 02 = TCP-клиент, удалённое соединение, адрес назначения <code class="font-mono text-sm">3E</code> с типом <code class="font-mono text-sm">21</code> IPv4 / <code class="font-mono text-sm">57</code> IPv6 / <code class="font-mono text-sm">F0</code> FQDN, NAA/APN <code class="font-mono text-sm">47</code>) или <code class="font-mono text-sm">04</code> пакет идентификации (необязательные данные, при отсутствии используется ICCID — отправляется по уже открытому TCP-каналу, не триггер).</li>
|
||||
<li>В управляемых разделах обязательные параметры проверяются: для <code class="font-mono text-sm">02</code> нужен порт назначения, для <code class="font-mono text-sm">03</code> — порт и адрес назначения. Строка PUSH в цепочке RAM/GP остаётся нестрогой для свободного составления скриптов.</li>
|
||||
<li><strong>Открытие BIP-канала</strong> (<code class="font-mono text-sm">01</code>) — необязательные COMPREHENSION-TLV OPEN CHANNEL; при пустом значении действуют умолчания приложения. Проактивную команду OPEN CHANNEL выдаёт само приложение (§9.1.1).</li>
|
||||
<li><strong>Установление соединения CAT_TP</strong> (<code class="font-mono text-sm">02</code>) — порт назначения в transport level <code class="font-mono text-sm">3C</code> с типом протокола 00 (обязателен), необязательные buffer size <code class="font-mono text-sm">39</code> / данные идентификации <code class="font-mono text-sm">36</code>.</li>
|
||||
<li><strong>TCP-соединение</strong> (<code class="font-mono text-sm">03</code>) — bearer <code class="font-mono text-sm">35</code>, transport level <code class="font-mono text-sm">3C</code> с типом протокола 02 = TCP-клиент, удалённое соединение, адрес назначения <code class="font-mono text-sm">3E</code> (<code class="font-mono text-sm">21</code> IPv4 / <code class="font-mono text-sm">57</code> IPv6 / <code class="font-mono text-sm">F0</code> FQDN), NAA/APN <code class="font-mono text-sm">47</code>; порт и адрес обязательны. Это параметры OPEN CHANNEL для TCP: соединение устанавливается через BIP или, если карта и терминал это поддерживают, через прямое IP-соединение (TS 102 483).</li>
|
||||
<li><strong>Пакет идентификации</strong> (<code class="font-mono text-sm">04</code>) не является триггером: он предполагает уже открытый TCP-канал и имеет смысл только как продолжение в том же сообщении, поэтому у TCP-запроса есть флажок <em>«Также отправить пакет идентификации (04)»</em>, добавляющий его (данные необязательны; при пустом значении используется ICCID). <code class="font-mono text-sm">04</code> также остаётся доступным в строке PUSH цепочки RAM/GP для сценариев.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
+6
-5
@@ -230,7 +230,7 @@
|
||||
<p class="text-sm mb-3">Pastes raw APDU hex and renders a collapsible tree. It auto-detects the container: an <strong>Expanded Script</strong> (leading <code class="font-mono text-sm">AA</code> or <code class="font-mono text-sm">AE80</code>, decoded per ETSI TS 102 226 §5.2.1) or a <strong>Compact C-APDU chain</strong> (a sequence of ISO 7816 C-APDUs). Each node shows its label, hex and a short description; parent nodes expand to reveal their sub-elements. The <strong>C-APDU Parser</strong> and <strong>R-APDU parser</strong> are the two sub-pills of the <strong>Parser</strong> pill.</p>
|
||||
|
||||
<h3 id="push-commands" class="text-lg font-medium mb-2">2.7 Push commands</h3>
|
||||
<p class="text-sm mb-3">Groups the commands that make the card dial out. Four sub-pills switch between the forms — <strong>Trigger (Push SMS)</strong>, <strong>Store (SD admin params)</strong>, <strong>BIP / CAT_TP trigger</strong> and <strong>TCP trigger</strong> — and only the selected form is shown; the two GP forms share one set of fields (the mode only changes how the payload is wrapped, and the form heading says which one). They come from different specs and are delivered differently: the administration trigger is a TLV message for the Security Domain (HTTP OTA), a §9 PUSH is a C-APDU (<code class="font-mono text-sm">80 EC 01 P2</code>) for an application that supports BIP and/or CAT_TP.</p>
|
||||
<p class="text-sm mb-3">Groups the commands that make the card dial out. Three sub-pills switch between the forms — <strong>Trigger (Push SMS)</strong>, <strong>Store (SD admin params)</strong> and <strong>Channel / link trigger</strong> — and only the selected form is shown; the two GP forms share one set of fields (the mode only changes how the payload is wrapped, and the form heading says which one). They come from different specs and are delivered differently: the administration trigger is a TLV message for the Security Domain (HTTP OTA), a §9 PUSH is a C-APDU (<code class="font-mono text-sm">80 EC 01 P2</code>) for an application that supports BIP and/or CAT_TP.</p>
|
||||
|
||||
<h4 id="http-ota" class="font-medium mb-1">Administration session (HTTP OTA)</h4>
|
||||
<p class="text-sm mb-3">Builds the Remote Application Management over HTTP payloads defined in GlobalPlatform <strong>GPC v2.2 Amendment B v1.1</strong> (§4.7). Two modes:</p>
|
||||
@@ -252,11 +252,12 @@
|
||||
<p class="text-sm mb-2"><strong>Pack into Secured packet</strong> sends the built payload to the SCP80 tab for SPI/counter filling — insert the TAR the SD listens on (typically the OTASD TAR) there.</p>
|
||||
|
||||
<h4 id="push-ts102226" class="font-medium mb-1 mt-3">TS 102 226 §9 PUSH</h4>
|
||||
<p class="text-sm mb-2">Two guided sections build the §9 requests with the same encoder as the RAM/GP chain's <strong>PUSH</strong> row, preview the C-APDU, and offer <strong>Pack into Secured packet</strong> (the TAR stays manual: the request is addressed to the target application, not the Security Domain) and <strong>→ Expanded Script</strong> (wraps the APDU in the <code class="font-mono text-sm">22</code> Command TLV and appends it to the Expanded Script builder).</p>
|
||||
<p class="text-sm mb-2">The <strong>Channel / link trigger</strong> sub-pill builds the §9 requests with the same encoder as the RAM/GP chain's <strong>PUSH</strong> row, previews the C-APDU(s), and offers <strong>Pack into Secured packet</strong> (the TAR stays manual: the request is addressed to the target application, not the Security Domain) and <strong>→ Expanded Script</strong> (wraps each APDU in the <code class="font-mono text-sm">22</code> Command TLV and appends them to the Expanded Script builder).</p>
|
||||
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
||||
<li><strong>BIP / CAT_TP</strong> — request <code class="font-mono text-sm">01</code> BIP channel opening (optional OPEN CHANNEL COMPREHENSION-TLVs; the application defaults apply when empty) or <code class="font-mono text-sm">02</code> CAT_TP link establishment (destination port in transport level <code class="font-mono text-sm">3C</code> with protocol type 00, optional buffer size <code class="font-mono text-sm">39</code> / identification data <code class="font-mono text-sm">36</code>).</li>
|
||||
<li><strong>TCP</strong> — request <code class="font-mono text-sm">03</code> TCP connection (bearer <code class="font-mono text-sm">35</code>, transport level <code class="font-mono text-sm">3C</code> with protocol type 02 = TCP client remote, destination address <code class="font-mono text-sm">3E</code> with type <code class="font-mono text-sm">21</code> IPv4 / <code class="font-mono text-sm">57</code> IPv6 / <code class="font-mono text-sm">F0</code> FQDN, NAA/APN <code class="font-mono text-sm">47</code>) or <code class="font-mono text-sm">04</code> identification packet (optional data, ICCID when absent — sent over an already open TCP channel, not a trigger).</li>
|
||||
<li>Mandatory parameters are enforced in the guided sections: <code class="font-mono text-sm">02</code> needs the destination port, <code class="font-mono text-sm">03</code> the port and the destination address. The RAM/GP chain row keeps the lenient behaviour for free-form scripting.</li>
|
||||
<li><strong>BIP channel opening</strong> (<code class="font-mono text-sm">01</code>) — optional OPEN CHANNEL COMPREHENSION-TLVs; the application defaults apply when empty. The application issues the proactive OPEN CHANNEL itself (§9.1.1).</li>
|
||||
<li><strong>CAT_TP link establishment</strong> (<code class="font-mono text-sm">02</code>) — destination port in transport level <code class="font-mono text-sm">3C</code> with protocol type 00 (mandatory), optional buffer size <code class="font-mono text-sm">39</code> / identification data <code class="font-mono text-sm">36</code>.</li>
|
||||
<li><strong>TCP connection</strong> (<code class="font-mono text-sm">03</code>) — bearer <code class="font-mono text-sm">35</code>, transport level <code class="font-mono text-sm">3C</code> with protocol type 02 = TCP client remote, destination address <code class="font-mono text-sm">3E</code> (<code class="font-mono text-sm">21</code> IPv4 / <code class="font-mono text-sm">57</code> IPv6 / <code class="font-mono text-sm">F0</code> FQDN), NAA/APN <code class="font-mono text-sm">47</code>; port and address are mandatory. These are the OPEN CHANNEL TCP parameters: the application establishes the connection over BIP or, where the card and terminal support it, over a direct IP connection (TS 102 483).</li>
|
||||
<li><strong>Identification packet</strong> (<code class="font-mono text-sm">04</code>) is not a trigger: it presupposes an already open TCP channel and only makes sense as a follow-up in the same message, so the TCP request carries an <em>Also send the identification packet (04)</em> checkbox that appends it (optional data; the ICCID is used when empty). <code class="font-mono text-sm">04</code> also stays available in the RAM/GP chain's PUSH row for script sequences.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
+99
-101
@@ -175,8 +175,7 @@
|
||||
<div class="flex flex-wrap gap-2 mb-3">
|
||||
<button id="hota-form-btn-trigger" onclick="hotaSetForm('trigger')" class="px-4 py-1.5 text-sm rounded-full bg-blue-600 text-white" data-l10n="Trigger (Push SMS)">Trigger (Push SMS)</button>
|
||||
<button id="hota-form-btn-store" onclick="hotaSetForm('store')" class="px-4 py-1.5 text-sm rounded-full bg-gray-200 dark:bg-slate-700 text-gray-700 dark:text-slate-300 hover:bg-gray-300 dark:hover:bg-slate-600" data-l10n="Store (SD admin params)">Store (SD admin params)</button>
|
||||
<button id="hota-form-btn-bip" onclick="hotaSetForm('bip')" class="px-4 py-1.5 text-sm rounded-full bg-gray-200 dark:bg-slate-700 text-gray-700 dark:text-slate-300 hover:bg-gray-300 dark:hover:bg-slate-600" data-l10n="BIP / CAT_TP trigger">BIP / CAT_TP trigger</button>
|
||||
<button id="hota-form-btn-tcp" onclick="hotaSetForm('tcp')" class="px-4 py-1.5 text-sm rounded-full bg-gray-200 dark:bg-slate-700 text-gray-700 dark:text-slate-300 hover:bg-gray-300 dark:hover:bg-slate-600" data-l10n="TCP trigger">TCP trigger</button>
|
||||
<button id="hota-form-btn-link" onclick="hotaSetForm('link')" class="px-4 py-1.5 text-sm rounded-full bg-gray-200 dark:bg-slate-700 text-gray-700 dark:text-slate-300 hover:bg-gray-300 dark:hover:bg-slate-600" data-l10n="Channel / link trigger">Channel / link trigger</button>
|
||||
</div>
|
||||
|
||||
<div id="hota-form-gp">
|
||||
@@ -291,73 +290,57 @@
|
||||
<button onclick="packToSp('hota-preview')" id="hota-pack-btn" disabled class="mb-3 px-5 py-2.5 bg-emerald-600 text-white text-sm font-medium rounded hover:bg-emerald-700 disabled:opacity-40 disabled:cursor-not-allowed" data-l10n="Pack into Secured packet">Pack into Secured packet</button>
|
||||
</div>
|
||||
|
||||
<div id="push-form-bip" class="hidden">
|
||||
<h3 class="text-base font-medium mb-2" data-l10n="BIP / CAT_TP trigger (TS 102 226 §9)">BIP / CAT_TP trigger (TS 102 226 §9)</h3>
|
||||
<div id="push-form-link" class="hidden">
|
||||
<h3 class="text-base font-medium mb-2" data-l10n="Channel / link establishment (TS 102 226 §9)">Channel / link establishment (TS 102 226 §9)</h3>
|
||||
<p class="text-xs text-gray-500 dark:text-slate-400 mb-2" data-l10n="Not the administration session — a C-APDU for an app that supports BIP/CAT_TP">Not the administration session — a C-APDU for an app that supports BIP/CAT_TP</p>
|
||||
<div class="border border-gray-300 dark:border-slate-600 rounded p-3 bg-gray-50 dark:bg-slate-800 mb-3">
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Request">Request</label>
|
||||
<select id="push-bip-request" onchange="pushUpdate('bip')" class="w-full border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800 font-mono">
|
||||
<select id="push-link-request" onchange="pushUpdate('link')" class="w-full border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800 font-mono">
|
||||
<option value="01" data-l10n="BIP channel opening (OPEN CHANNEL)">BIP channel opening (OPEN CHANNEL)</option>
|
||||
<option value="02" data-l10n="CAT_TP link establishment">CAT_TP link establishment</option>
|
||||
</select>
|
||||
</div>
|
||||
<div data-push-bip="01">
|
||||
<label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="OPEN CHANNEL COMPREHENSION-TLVs (hex, optional)">OPEN CHANNEL COMPREHENSION-TLVs (hex, optional)</label>
|
||||
<textarea id="push-bip-data" rows="2" oninput="pushUpdate('bip')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800 mb-2" placeholder="82102081..."></textarea>
|
||||
</div>
|
||||
<div data-push-bip="02" class="grid grid-cols-3 gap-2 mb-2">
|
||||
<div><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Destination port (hex)">Destination port (hex)</label>
|
||||
<input id="push-bip-port" oninput="pushUpdate('bip')" maxlength="4" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800" placeholder="1F90"></div>
|
||||
<div><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Max SDU (hex, optional)">Max SDU (hex, optional)</label>
|
||||
<input id="push-bip-sdu" oninput="pushUpdate('bip')" maxlength="4" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800"></div>
|
||||
<div><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Identification data (hex, optional)">Identification data (hex, optional)</label>
|
||||
<input id="push-bip-ident" oninput="pushUpdate('bip')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800"></div>
|
||||
</div>
|
||||
<div data-push-bip="02">
|
||||
<label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Extra TLVs (hex, optional)">Extra TLVs (hex, optional)</label>
|
||||
<input id="push-bip-extra" oninput="pushUpdate('bip')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800">
|
||||
</div>
|
||||
</div>
|
||||
<textarea id="push-bip-preview" rows="2" readonly class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 bg-gray-100 dark:bg-slate-800 mb-2" placeholder="C-APDU (TS 102 226 §9)"></textarea>
|
||||
<button onclick="packToSp('push-bip-preview')" id="push-bip-pack-btn" disabled class="mb-3 px-5 py-2.5 bg-emerald-600 text-white text-sm font-medium rounded hover:bg-emerald-700 disabled:opacity-40 disabled:cursor-not-allowed" data-l10n="Pack into Secured packet">Pack into Secured packet</button>
|
||||
<button onclick="pushToExpanded('push-bip-preview')" id="push-bip-exp-btn" disabled class="mb-3 px-5 py-2.5 bg-violet-600 text-white text-sm font-medium rounded hover:bg-violet-700 disabled:opacity-40 disabled:cursor-not-allowed" data-l10n="→ Expanded Script">→ Expanded Script</button>
|
||||
</div>
|
||||
|
||||
<div id="push-form-tcp" class="hidden">
|
||||
<h3 class="text-base font-medium mb-2" data-l10n="TCP trigger (TS 102 226 §9)">TCP trigger (TS 102 226 §9)</h3>
|
||||
<p class="text-xs text-gray-500 dark:text-slate-400 mb-2" data-l10n="Not the administration session — a C-APDU for an app that supports BIP/CAT_TP">Not the administration session — a C-APDU for an app that supports BIP/CAT_TP</p>
|
||||
<div class="border border-gray-300 dark:border-slate-600 rounded p-3 bg-gray-50 dark:bg-slate-800 mb-3">
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Request">Request</label>
|
||||
<select id="push-tcp-request" onchange="pushUpdate('tcp')" class="w-full border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800 font-mono">
|
||||
<option value="03" data-l10n="TCP connection">TCP connection</option>
|
||||
<option value="04" data-l10n="Identification packet">Identification packet</option>
|
||||
</select>
|
||||
</div>
|
||||
<div data-push-tcp="03" class="grid grid-cols-2 gap-2 mb-2">
|
||||
<div><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Bearer description (hex, empty = 350103)">Bearer description (hex, empty = 350103)</label>
|
||||
<input id="push-tcp-bearer" oninput="pushUpdate('tcp')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800" placeholder="350103"></div>
|
||||
<div data-push-link="01">
|
||||
<label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="OPEN CHANNEL COMPREHENSION-TLVs (hex, optional)">OPEN CHANNEL COMPREHENSION-TLVs (hex, optional)</label>
|
||||
<textarea id="push-link-data" rows="2" oninput="pushUpdate('link')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800 mb-2" placeholder="82102081..."></textarea>
|
||||
</div>
|
||||
<div data-push-link="02" class="grid grid-cols-2 gap-2 mb-2">
|
||||
<div><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Max SDU (hex, optional)">Max SDU (hex, optional)</label>
|
||||
<input id="push-link-sdu" oninput="pushUpdate('link')" maxlength="4" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800"></div>
|
||||
<div><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Identification data (hex, optional)">Identification data (hex, optional)</label>
|
||||
<input id="push-link-ident" oninput="pushUpdate('link')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800"></div>
|
||||
</div>
|
||||
<div data-push-link="02,03" class="grid grid-cols-2 gap-2 mb-2">
|
||||
<div><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Destination port (hex)">Destination port (hex)</label>
|
||||
<input id="push-tcp-port" oninput="pushUpdate('tcp')" maxlength="4" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800" placeholder="0050"></div>
|
||||
<div><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Destination address value (hex: 21 IPv4 / 57 IPv6 / F0 FQDN)">Destination address value (hex: 21 IPv4 / 57 IPv6 / F0 FQDN)</label>
|
||||
<input id="push-tcp-addr" oninput="pushUpdate('tcp')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800" placeholder="210A000001"></div>
|
||||
<div><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="NAA / APN (text)">NAA / APN (text)</label>
|
||||
<input id="push-tcp-apn" oninput="pushUpdate('tcp')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800" placeholder="internet"></div>
|
||||
<input id="push-link-port" oninput="pushUpdate('link')" maxlength="4" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800" placeholder="1F90"></div>
|
||||
<div data-push-link="03"><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Bearer description (hex, empty = 350103)">Bearer description (hex, empty = 350103)</label>
|
||||
<input id="push-link-bearer" oninput="pushUpdate('link')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800" placeholder="350103"></div>
|
||||
<div data-push-link="03"><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Destination address value (hex: 21 IPv4 / 57 IPv6 / F0 FQDN)">Destination address value (hex: 21 IPv4 / 57 IPv6 / F0 FQDN)</label>
|
||||
<input id="push-link-addr" oninput="pushUpdate('link')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800" placeholder="210A000001"></div>
|
||||
<div data-push-link="03"><label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="NAA / APN (text)">NAA / APN (text)</label>
|
||||
<input id="push-link-apn" oninput="pushUpdate('link')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800" placeholder="internet"></div>
|
||||
</div>
|
||||
<div data-push-tcp="04" class="mb-2">
|
||||
<label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Identification data (hex, optional; ICCID when empty)">Identification data (hex, optional; ICCID when empty)</label>
|
||||
<input id="push-tcp-ident" oninput="pushUpdate('tcp')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800">
|
||||
<div class="text-xs text-gray-500 dark:text-slate-400 mt-1" data-l10n="The identification packet is sent over an already open TCP channel (not a trigger).">The identification packet is sent over an already open TCP channel (not a trigger).</div>
|
||||
</div>
|
||||
<div data-push-tcp="03">
|
||||
<div data-push-link="02,03" class="mb-2">
|
||||
<label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Extra TLVs (hex, optional)">Extra TLVs (hex, optional)</label>
|
||||
<input id="push-tcp-extra" oninput="pushUpdate('tcp')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800">
|
||||
<input id="push-link-extra" oninput="pushUpdate('link')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800">
|
||||
</div>
|
||||
<div data-push-link="03">
|
||||
<label class="flex items-center gap-2 text-sm font-medium text-gray-700 dark:text-slate-300 mb-2">
|
||||
<input type="checkbox" id="push-link-idp" onchange="pushUpdate('link')" class="rounded">
|
||||
<span data-l10n="Also send the identification packet (04) in the same message">Also send the identification packet (04) in the same message</span>
|
||||
</label>
|
||||
<div id="push-link-idp-block" class="hidden">
|
||||
<label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Identification data (hex, optional; ICCID when empty)">Identification data (hex, optional; ICCID when empty)</label>
|
||||
<input id="push-link-idp-ident" oninput="pushUpdate('link')" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800">
|
||||
<div class="text-xs text-gray-500 dark:text-slate-400 mt-1" data-l10n="The identification packet follows the TCP request in the same message (ICCID when empty).">The identification packet follows the TCP request in the same message (ICCID when empty).</div>
|
||||
</div>
|
||||
</div>
|
||||
<textarea id="push-tcp-preview" rows="2" readonly class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 bg-gray-100 dark:bg-slate-800 mb-2" placeholder="C-APDU (TS 102 226 §9)"></textarea>
|
||||
<button onclick="packToSp('push-tcp-preview')" id="push-tcp-pack-btn" disabled class="mb-3 px-5 py-2.5 bg-emerald-600 text-white text-sm font-medium rounded hover:bg-emerald-700 disabled:opacity-40 disabled:cursor-not-allowed" data-l10n="Pack into Secured packet">Pack into Secured packet</button>
|
||||
<button onclick="pushToExpanded('push-tcp-preview')" id="push-tcp-exp-btn" disabled class="mb-3 px-5 py-2.5 bg-violet-600 text-white text-sm font-medium rounded hover:bg-violet-700 disabled:opacity-40 disabled:cursor-not-allowed" data-l10n="→ Expanded Script">→ Expanded Script</button>
|
||||
</div>
|
||||
<textarea id="push-link-preview" rows="2" readonly class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 bg-gray-100 dark:bg-slate-800 mb-2" placeholder="C-APDU (TS 102 226 §9)"></textarea>
|
||||
<button onclick="packToSp('push-link-preview')" id="push-link-pack-btn" disabled class="mb-3 px-5 py-2.5 bg-emerald-600 text-white text-sm font-medium rounded hover:bg-emerald-700 disabled:opacity-40 disabled:cursor-not-allowed" data-l10n="Pack into Secured packet">Pack into Secured packet</button>
|
||||
<button onclick="pushToExpanded('push-link-preview')" id="push-link-exp-btn" disabled class="mb-3 px-5 py-2.5 bg-violet-600 text-white text-sm font-medium rounded hover:bg-violet-700 disabled:opacity-40 disabled:cursor-not-allowed" data-l10n="→ Expanded Script">→ Expanded Script</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2063,19 +2046,19 @@ function hotaSetMode(mode) {
|
||||
}
|
||||
|
||||
// The Push commands pill shows one form at a time: Trigger and Store share the
|
||||
// GP administration form (different payload mode), BIP/CAT_TP and TCP have
|
||||
// their own TS 102 226 §9 form.
|
||||
// GP administration form (different payload mode), Channel / link trigger has
|
||||
// its own TS 102 226 §9 form.
|
||||
function hotaSetForm(form) {
|
||||
_hotaForm = form;
|
||||
['trigger', 'store', 'bip', 'tcp'].forEach(f => {
|
||||
['trigger', 'store', 'link'].forEach(f => {
|
||||
const btn = document.getElementById('hota-form-btn-' + f);
|
||||
if (!btn) return;
|
||||
btn.className = 'px-4 py-1.5 text-sm rounded-full ' + (f === form
|
||||
? 'bg-blue-600 text-white'
|
||||
: 'bg-gray-200 dark:bg-slate-700 text-gray-700 dark:text-slate-300 hover:bg-gray-300 dark:hover:bg-slate-600');
|
||||
});
|
||||
const visible = form === 'bip' ? 'push-form-bip' : (form === 'tcp' ? 'push-form-tcp' : 'hota-form-gp');
|
||||
['hota-form-gp', 'push-form-bip', 'push-form-tcp'].forEach(id => {
|
||||
const visible = form === 'link' ? 'push-form-link' : 'hota-form-gp';
|
||||
['hota-form-gp', 'push-form-link'].forEach(id => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.classList.toggle('hidden', id !== visible);
|
||||
});
|
||||
@@ -2172,46 +2155,56 @@ function hotaPreviewEdited() {
|
||||
}
|
||||
|
||||
// ===== Push command sections (TS 102 226 9) =====
|
||||
// The BIP/CAT_TP and TCP sections feed the same encoder as the RAM/GP chain's
|
||||
// PUSH command (chainPushData, vector-tested in ts102226.test.js) and preview
|
||||
// the resulting C-APDU. A §9 PUSH is addressed to the application's TAR, so
|
||||
// The channel/link section feeds the same encoder as the RAM/GP chain's PUSH
|
||||
// command (chainPushData, vector-tested in ts102226.test.js) and previews the
|
||||
// resulting C-APDU(s). A §9 PUSH is addressed to the application's TAR, so
|
||||
// packing does not auto-select a TAR (unlike the RFM/RAM chain previews).
|
||||
const _pushApdus = {};
|
||||
|
||||
function pushReadFields(section) {
|
||||
const v = id => { const el = document.getElementById(id); return el ? el.value : ''; };
|
||||
if (section === 'bip') {
|
||||
const idp = document.getElementById('push-' + section + '-idp');
|
||||
return {
|
||||
request: v('push-bip-request') || '01',
|
||||
pushData: v('push-bip-data'),
|
||||
pushPort: v('push-bip-port'),
|
||||
pushSdu: v('push-bip-sdu'),
|
||||
pushIdent: v('push-bip-ident'),
|
||||
pushExtra: v('push-bip-extra'),
|
||||
};
|
||||
}
|
||||
return {
|
||||
request: v('push-tcp-request') || '03',
|
||||
pushBearer: v('push-tcp-bearer'),
|
||||
pushPort: v('push-tcp-port'),
|
||||
pushAddr: v('push-tcp-addr'),
|
||||
pushApn: v('push-tcp-apn'),
|
||||
pushIdent: v('push-tcp-ident'),
|
||||
pushExtra: v('push-tcp-extra'),
|
||||
request: v('push-' + section + '-request') || '01',
|
||||
withIdp: !!(idp && idp.checked),
|
||||
pushData: v('push-' + section + '-data'),
|
||||
pushPort: v('push-' + section + '-port'),
|
||||
pushSdu: v('push-' + section + '-sdu'),
|
||||
pushIdent: v('push-' + section + '-ident'),
|
||||
pushBearer: v('push-' + section + '-bearer'),
|
||||
pushAddr: v('push-' + section + '-addr'),
|
||||
pushApn: v('push-' + section + '-apn'),
|
||||
pushExtra: v('push-' + section + '-extra'),
|
||||
idpIdent: v('push-' + section + '-idp-ident'),
|
||||
};
|
||||
}
|
||||
|
||||
// C-APDU for a §9 push from the section's field values; empty when a mandatory
|
||||
// C-APDUs for a §9 push from the form's field values; empty when a mandatory
|
||||
// parameter is missing (TS 102 226 9.2.2/9.2.3: CAT_TP and TCP need the
|
||||
// destination port, TCP also the destination address). P2=01/04 may carry no
|
||||
// data (the application defaults / ICCID are used). The RAM/GP chain row
|
||||
// stays lenient so scripts can be composed freely.
|
||||
function pushSectionApdu(section, f) {
|
||||
const request = f.request || (section === 'bip' ? '01' : '03');
|
||||
//
|
||||
// The identification packet (9.1.5) presupposes an open TCP channel and is
|
||||
// only meaningful as a follow-up in the same message, so it is appended right
|
||||
// after the TCP request when requested.
|
||||
function pushSectionApdus(section, f) {
|
||||
const request = f.request || '01';
|
||||
const hx = s => (s || '').replace(/[^0-9a-fA-F]/g, '').toUpperCase();
|
||||
if (request === '02' && hx(f.pushPort).length !== 4) return '';
|
||||
if (request === '03' && (hx(f.pushPort).length !== 4 || !hx(f.pushAddr))) return '';
|
||||
if (request === '02' && hx(f.pushPort).length !== 4) return [];
|
||||
if (request === '03' && (hx(f.pushPort).length !== 4 || !hx(f.pushAddr))) return [];
|
||||
const p2 = parseInt(request, 16);
|
||||
const data = chainPushData(Object.assign({}, f, { pushType: request }));
|
||||
if (!data) return buildApdu(0x80, 0xEC, 0x01, parseInt(request, 16), null, null);
|
||||
return buildApdu(0x80, 0xEC, 0x01, parseInt(request, 16), data.length / 2, data);
|
||||
const apdus = [data
|
||||
? buildApdu(0x80, 0xEC, 0x01, p2, data.length / 2, data)
|
||||
: buildApdu(0x80, 0xEC, 0x01, p2, null, null)];
|
||||
if (request === '03' && f.withIdp) {
|
||||
const idp = chainPushData({ pushType: '04', pushIdent: f.idpIdent });
|
||||
apdus.push(idp
|
||||
? buildApdu(0x80, 0xEC, 0x01, 0x04, idp.length / 2, idp)
|
||||
: buildApdu(0x80, 0xEC, 0x01, 0x04, null, null));
|
||||
}
|
||||
return apdus;
|
||||
}
|
||||
|
||||
function pushToggleFields(section) {
|
||||
@@ -2225,26 +2218,33 @@ function pushToggleFields(section) {
|
||||
|
||||
function pushUpdate(section) {
|
||||
pushToggleFields(section);
|
||||
const apdu = pushSectionApdu(section, pushReadFields(section));
|
||||
const f = pushReadFields(section);
|
||||
const apdus = pushSectionApdus(section, f);
|
||||
_pushApdus[section] = apdus;
|
||||
const preview = document.getElementById('push-' + section + '-preview');
|
||||
if (preview) preview.value = apdu;
|
||||
if (preview) preview.value = apdus.join('');
|
||||
['pack', 'exp'].forEach(kind => {
|
||||
const btn = document.getElementById('push-' + section + '-' + kind + '-btn');
|
||||
if (btn) btn.disabled = !apdu;
|
||||
if (btn) btn.disabled = !apdus.length;
|
||||
});
|
||||
const idpBlock = document.getElementById('push-' + section + '-idp-block');
|
||||
if (idpBlock) idpBlock.classList.toggle('hidden', !(f.request === '03' && f.withIdp));
|
||||
}
|
||||
|
||||
// Import the §9 C-APDU into the Expanded Script builder as a 22 command TLV.
|
||||
// Import the §9 C-APDU(s) into the Expanded Script builder as 22 command TLVs
|
||||
// (a sequence - e.g. TCP request plus identification packet - becomes one row
|
||||
// per command, all inside the same script).
|
||||
function pushToExpanded(sourceId) {
|
||||
const hex = (document.getElementById(sourceId) || {}).value || '';
|
||||
if (!hex) return;
|
||||
const section = (sourceId || '').replace(/^push-/, '').replace(/-preview$/, '');
|
||||
const apdus = _pushApdus[section] || [];
|
||||
if (!apdus.length) return;
|
||||
cApduSwitchSubtab('ber');
|
||||
berAppendApdu(hex);
|
||||
apdus.forEach(berAppendApdu);
|
||||
genBerTlv();
|
||||
}
|
||||
|
||||
function pushInit() {
|
||||
['bip', 'tcp'].forEach(pushUpdate);
|
||||
pushUpdate('link');
|
||||
hotaSetForm('trigger');
|
||||
}
|
||||
pushInit();
|
||||
@@ -14953,16 +14953,15 @@ const LANG_RU = {
|
||||
'Push commands': 'Пуш/триггер',
|
||||
'HTTP OTA Administrative session trigger (Push SMS)': 'HTTP OTA — триггер административной сессии (Push SMS)',
|
||||
'HTTP OTA Administrative session store data (SD admin params)': 'HTTP OTA — запись данных административной сессии (параметры SD)',
|
||||
'BIP / CAT_TP trigger': 'Триггер BIP / CAT_TP',
|
||||
'TCP trigger': 'Триггер TCP',
|
||||
'BIP / CAT_TP trigger (TS 102 226 §9)': 'Триггер BIP / CAT_TP (TS 102 226 §9)',
|
||||
'TCP trigger (TS 102 226 §9)': 'Триггер TCP (TS 102 226 §9)',
|
||||
'Not the administration session — a C-APDU for an app that supports BIP/CAT_TP': 'C-APDU для приложения с поддержкой BIP/CAT_TP (не admin session!)',
|
||||
'Request': 'Запрос',
|
||||
'BIP channel opening (OPEN CHANNEL)': 'Открытие BIP-канала (OPEN CHANNEL)',
|
||||
'Channel / link trigger': 'Триггер канала/линка',
|
||||
'Channel / link establishment (TS 102 226 §9)': 'Установление канала/линка (TS 102 226 §9)',
|
||||
'Also send the identification packet (04) in the same message': 'Также отправить пакет идентификации (04) в том же сообщении',
|
||||
'The identification packet follows the TCP request in the same message (ICCID when empty).': 'Пакет идентификации отправляется следом за TCP-запросом в том же сообщении (при пустом значении — ICCID).',
|
||||
'CAT_TP link establishment': 'Установление соединения CAT_TP',
|
||||
'TCP connection': 'TCP-соединение',
|
||||
'Identification packet': 'Пакет идентификации',
|
||||
'OPEN CHANNEL COMPREHENSION-TLVs (hex, optional)': 'COMPREHENSION-TLV OPEN CHANNEL (hex, необязательно)',
|
||||
'Destination port (hex)': 'Порт назначения (hex)',
|
||||
'Max SDU (hex, optional)': 'Макс. SDU (hex, необязательно)',
|
||||
@@ -14972,7 +14971,6 @@ const LANG_RU = {
|
||||
'Bearer description (hex, empty = 350103)': 'Описание bearer (hex, пусто = 350103)',
|
||||
'Destination address value (hex: 21 IPv4 / 57 IPv6 / F0 FQDN)': 'Значение адреса назначения (hex: 21 IPv4 / 57 IPv6 / F0 FQDN)',
|
||||
'NAA / APN (text)': 'NAA / APN (текст)',
|
||||
'The identification packet is sent over an already open TCP channel (not a trigger).': 'Пакет идентификации отправляется по уже открытому TCP-каналу (не триггер).',
|
||||
'C-APDU (TS 102 226 §9)': 'C-APDU (TS 102 226 §9)',
|
||||
'Store (SD admin params)': 'Store (параметры SD)',
|
||||
'SD params tag': 'Tag параметров SD',
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const CACHE = 'simple-v248';
|
||||
const CACHE = 'simple-v249';
|
||||
const URLS = [
|
||||
'index.html',
|
||||
'help.html',
|
||||
|
||||
@@ -134,6 +134,22 @@ test('the C-APDU and R-APDU parsers are sub-pills of the Parser pill', () => {
|
||||
assert.match(html, /id="parser-btn-response" onclick="parserSwitchSubtab\('response'\)"/);
|
||||
});
|
||||
|
||||
test('the document and its inline script are complete', () => {
|
||||
// A truncated index.html (missing </script></body></html>) makes the whole
|
||||
// inline script fail to parse in the browser: every onclick handler then
|
||||
// reports "function is not defined" while the Node tests still pass,
|
||||
// because they extract functions from the text without ever running the
|
||||
// document's script.
|
||||
assert.ok(html.trimEnd().endsWith('</html>'), 'index.html must end with </html>');
|
||||
assert.strictEqual((html.match(/<script\b/g) || []).length,
|
||||
(html.match(/<\/script>/g) || []).length, 'every <script> must be closed');
|
||||
const inline = html.match(/<script>([\s\S]*)<\/script>\s*<\/body>/);
|
||||
assert.ok(inline, 'inline script not found');
|
||||
assert.ok(inline[1].length > 100000, 'inline script looks truncated');
|
||||
new Function(inline[1]); // throws on a syntax error
|
||||
assert.ok(inline[1].includes('function cApduSwitchSubtab'), 'key function missing');
|
||||
});
|
||||
|
||||
test('profiler and phone simulator are top-level tab contents', () => {
|
||||
assert.ok(html.includes('id="tab-profiler" class="tab-content hidden"'));
|
||||
assert.ok(html.includes('id="tab-phone" class="tab-content hidden"'));
|
||||
|
||||
@@ -31,7 +31,7 @@ function extractFunc(src, name) {
|
||||
const FNS = ['berLenStr', 'buildApdu', 'buildSelect', 'escHtml', 'esc', 'chainInit',
|
||||
'chainKind', 'chainIsEmbedded', 'chainCommands', 'chainBuildRowHex',
|
||||
'chainSimBuildRowHex', 'chainRamBuildRowHex', 'chainPushData', '_hotaAsciiHex',
|
||||
'chainApduList', 'chainBuildFcp', 'pushSectionApdu'];
|
||||
'chainApduList', 'chainBuildFcp', 'pushSectionApdus'];
|
||||
let code = '';
|
||||
for (const f of FNS) code += extractFunc(html, f) + '\n';
|
||||
for (const c of ['CHAIN_CMDS_SIM', 'CHAIN_CMDS_USIM', 'CHAIN_CMDS_RAM']) {
|
||||
@@ -227,22 +227,30 @@ test('CREATE FILE FCP template skeleton (TS 102 222 table 4)', () => {
|
||||
assert.strictEqual(r4.fields.fcp, '620883026F0780020010');
|
||||
});
|
||||
|
||||
test('pushSectionApdu builds the guided §9 push commands (Remote APDU pill)', () => {
|
||||
test('pushSectionApdus builds the guided §9 channel/link requests', () => {
|
||||
// BIP channel opening: OPEN CHANNEL TLVs are optional.
|
||||
assert.strictEqual(pushSectionApdu('bip', { request: '01', pushData: '350103' }), '80EC010103350103');
|
||||
assert.strictEqual(pushSectionApdu('bip', { request: '01', pushData: '' }), '80EC0101');
|
||||
assert.deepStrictEqual(pushSectionApdus('link', { request: '01', pushData: '350103' }), ['80EC010103350103']);
|
||||
assert.deepStrictEqual(pushSectionApdus('link', { request: '01', pushData: '' }), ['80EC0101']);
|
||||
// CAT_TP: the destination port is mandatory (9.2.2).
|
||||
assert.strictEqual(pushSectionApdu('bip', { request: '02', pushPort: '1F90' }), '80EC0102053C03001F90');
|
||||
assert.strictEqual(pushSectionApdu('bip', { request: '02', pushPort: '' }), '');
|
||||
assert.deepStrictEqual(pushSectionApdus('link', { request: '02', pushPort: '1F90' }), ['80EC0102053C03001F90']);
|
||||
assert.deepStrictEqual(pushSectionApdus('link', { request: '02', pushPort: '' }), []);
|
||||
// TCP: port and destination address are mandatory (9.2.3).
|
||||
assert.strictEqual(
|
||||
pushSectionApdu('tcp', { request: '03', pushPort: '0050', pushAddr: '210A000001', pushApn: 'internet' }),
|
||||
'80EC010319' + '3501033C030200503E05210A0000014708696E7465726E6574');
|
||||
assert.strictEqual(pushSectionApdu('tcp', { request: '03', pushPort: '0050' }), '');
|
||||
assert.strictEqual(pushSectionApdu('tcp', { request: '03', pushAddr: '210A000001' }), '');
|
||||
// Identification packet: optional data, ICCID is used when absent (9.2.4).
|
||||
assert.strictEqual(pushSectionApdu('tcp', { request: '04', pushIdent: '0102' }), '80EC01040436020102');
|
||||
assert.strictEqual(pushSectionApdu('tcp', { request: '04', pushIdent: '' }), '80EC0104');
|
||||
const tcp = '80EC010319' + '3501033C030200503E05210A0000014708696E7465726E6574';
|
||||
assert.deepStrictEqual(
|
||||
pushSectionApdus('link', { request: '03', pushPort: '0050', pushAddr: '210A000001', pushApn: 'internet' }),
|
||||
[tcp]);
|
||||
assert.deepStrictEqual(pushSectionApdus('link', { request: '03', pushPort: '0050' }), []);
|
||||
assert.deepStrictEqual(pushSectionApdus('link', { request: '03', pushAddr: '210A000001' }), []);
|
||||
// The identification packet (9.1.5) rides in the same message right after
|
||||
// the TCP request; its data is optional (ICCID when absent).
|
||||
assert.deepStrictEqual(
|
||||
pushSectionApdus('link', { request: '03', pushPort: '0050', pushAddr: '210A000001', pushApn: 'internet', withIdp: true }),
|
||||
[tcp, '80EC0104']);
|
||||
assert.deepStrictEqual(
|
||||
pushSectionApdus('link', { request: '03', pushPort: '0050', pushAddr: '210A000001', pushApn: 'internet', withIdp: true, idpIdent: '0102' }),
|
||||
[tcp, '80EC01040436020102']);
|
||||
// The follow-up only applies to the TCP request.
|
||||
assert.deepStrictEqual(pushSectionApdus('link', { request: '01', pushData: '', withIdp: true }), ['80EC0101']);
|
||||
});
|
||||
|
||||
test('chainApduList drops GET RESPONSE and splits multi-APDU rows', () => {
|
||||
|
||||
Reference in New Issue
Block a user