Veuillez placer une carte sur le lecteur
Veuillez placer une carte sur le lecteur
Veuillez placer une carte sur le lecteur
Copy, paste, move (including drag-and-drop) and delete in the library tree now follow role-based rights, the Shared Directory Write Access option, and destination-folder ownership (cid / gid).
cid and gid).cid / gid restriction. (copy).The About -> Version menu shows the git tag. Click the version number to open the release notes.
Date: 20 September 2026
This release adds protocol v2 between the desktop/Android agent and the web server. The web client does not speak v2 directly: it keeps using the existing PHP helpers (utils/agent_status.php, utils/cmd_reader.php, dump load). The server translates those calls into the same MySQL queues the agent already used, and pushes work to the agent over SSE.
v2 is opt-in on the agent. Legacy long-poll (utils/reader_gw.php) remains the default when transport_v2 is absent from server.txt.
| Role | Process | Talks v2 HTTP? |
|---|---|---|
| Agent | Java desktop or Android app | Yes api/v2/agent/*.php |
| Web server | Apache + PHP + MySQL | Yes implements v2; still serves the web client on the legacy PHP URLs |
| Web client | Browser (or Android WebView) | No polls status and posts APDUs through the existing utils/ and php/ endpoints |
The web client therefore works the same whether the agent is on v2 or on long-poll. Presence, APDU results and dumps still land in tbl_cli_status / tbl_cli_msg / dumps/load.php.
Typical round trip:
POST hello.php server creates a session, sets lastConnection, returns sessionId + cid.GET stream.php (SSE) and keeps reconnecting.GET agent_status.php every 2.5 s connected if lastConnection is less than 5 s old.GET cmd_reader.php server inserts tbl_cli_msg (sta = 0) and waits for sta = 2.sta = 1, sends SSE event: command, closes.POST reply.php sta = 2; the web client unblocks.POST heartbeat.php on a card/SAM change (and every 5 s).POST bye.php presence drops immediately.On the agent, add the keyword transport_v2 on its own line in the installation server.txt (non-comment). Desktop and Android both read that flag at startup.
version,1,
server,http://localhost,
root_dir,intertool_proj/intertool,
transport_v2
Without that keyword the agent keeps calling utils/reader_gw.php (legacy long-poll).
The server hello payload also reports transport (sse-post by default, or legacy if agent_transport_mode is set to legacy in site config). That field is informational; the agent chooses the stack from server.txt.
All v2 agent endpoints are under:
{server}/{root_dir}/api/v2/agent/
Example with the localhost overlay: http://localhost/intertool_proj/intertool/api/v2/agent/hello.php.
JSON endpoints accept Content-Type: application/json and return application/json; charset=utf-8. The stream is text/event-stream.
Envelope field v is 1 for this protocol revision (independent of the application git tag).
POST hello.php registerBody (required): v, sam, agentVersion
sam is the SAM serial as uppercase hex (or the manual PIN used as a pseudo-SAM). agentVersion is the packed protocol version string from the agent (releases.json current, compared as a float to agentMinVersion).
| HTTP | ok | Meaning |
|---|---|---|
| 200 | true | Session created |
| 400 | false | Bad JSON / missing fields / v 1 / SAM not hex |
| 403 | false | SAM_UNKNOWN SAM not mapped to a CID |
| 426 | false | AGENT_VERSION_TOO_OLD |
| 500 | false | Could not insert the session row |
Success body: sessionId, cid, aidRestrict, serverTime (epoch seconds), transport, minAgentVersion.
Side effects:
tbl_agent_sessions_v2 (connected = 1).agent_updt_sam + tbl_cli_status.lastConnection = now.tbl_cli_msg rows for that CID (empty the command queue).The agent treats HTTP 200 + ok: true as connected. It does not wait for the first SSE event before showing the LED.
GET stream.php?sessionId=…&timeoutSec=… wait for a commandLong-lived GET. timeoutSec is clamped to 555, default 25.
Unknown or disconnected session 404 text unknown session. Missing sessionId 400.
While the connection is open the server:
:).tbl_cli_status.lastConnection about once per second (so the web client 5 s presence window stays green).event: heartbeat.tbl_cli_msg row for the session CID with sta = 0, sets sta = 1 (collected), emits event: command, then closes the stream.event: noop and closes.connection_aborted), the session is marked disconnected (same as bye).The agent reconnects immediately after noop/heartbeat-only/command. Heartbeat SSE events are ignored by the agent loop (presence is a separate POST, see 4.4). After three consecutive stream HTTP errors the agent stops the proxy.
POST reply.php command resultBody (required): v, sessionId, seq, type, payload
type is RES_CMD_OK (legacy msg 4, sta = 2) or RES_CMD_ERROR (legacy msg -1, sta = -1).
payload.legacyRes is the string the web client already understands, typically {responseHex}{sw},{durationMs} (for example 9000,12). If legacyRes is omitted, the server builds it from responseHex, sw (default 6F00) and durationMs.
| HTTP | status | Meaning |
|---|---|---|
| 200 | accepted | Row updated (sta was 0 or 1) |
| 200 | duplicate | No matching row left to update |
| 404 | unknown_session | Session missing or connected = 0 |
Also touches lastConnection.
The web clients comm_sendApdu only waits for sta = 2. An error reply (sta = -1) is not treated as a completed APDU there; the browser call times out (9998,0) after 20 s.
POST heartbeat.php card / SAM presenceBody (required): v, sessionId, type (HEARTBEAT), payload
payload fields used:
| Field | Use |
|---|---|
cardStatus | Bit mask written to tbl_cli_status.cardStatus |
atrHex | Card ATR hex tbl_cli_status.atr |
agentVersion | Optional; updates tbl_cli_status.agentVersion |
cardStatus bits (agent):
| Bit | Value | Meaning |
|---|---|---|
| 0 | 1 | Card present on the PC/SC reader |
| 1 | 2 | SAM present |
| 2 | 4 | SAM locked |
The agent sends a heartbeat at least every 5 s, and immediately when card/SAM/reader presence changes. Success body includes nextHeartbeatSec: 10 (advisory).
This is what the web client shows as SAM / card state: utils/agent_status.php reads tbl_cli_status via agent_infoSAM.
POST bye.php clean disconnectBody (required): v, sessionId
Marks the session connected = 0, sets lastConnection 60 s in the past (so agent_ComStatus reports disconnected on the next poll), and resets card/SAM display fields (agent_reset_status).
The agent also aborts the in-flight stream.php GET so the PHP worker does not keep touching lastConnection. Quit without bye left the web UI green for ~20 s (remaining stream timeout).
{
"v": 1,
"sessionId": "…",
"seq": 12345,
"type": "CMD_SEND_APDU",
"ts": 1770000000,
"payload": {
"legacyMsg": 2,
"legacyArg": "0:00A40400…"
},
"meta": { "source": "server" }
}
SSE framing:
event: command
id: 12345
data: {…json…}
type | legacyMsg | Origin |
|---|---|---|
NOOP | 0 | Stream timeout, or idle |
CMD_CONFIG | 1 | Rare / test |
CMD_SEND_APDU | 2 | Web client APDU (device:apdu in legacyArg) |
CMD_ECHO | 5 | Echo |
INIT_COMM | -3 | Legacy handshake leftover (agent no-op on v2) |
HELLO_ACK | -4 | Legacy you are leftover |
HEARTBEAT | Stream keepalive event (not a tbl_cli_msg row) |
The browser never calls api/v2/agent/. It keeps:
| Browser call | Server | Effect |
|---|---|---|
GET utils/agent_status.php?cid= every 2.5 s | agent_ComStatus | Connected if lastConnection is younger than 5 s; plus SAM fields |
GET utils/cmd_reader.php?cid=&device=&apdu= | comm_sendApdu | Insert tbl_cli_msg (msg = 2, sta = 0, arg = device:apdu), poll until sta = 2 (20 s) |
| Console / dump / card flows | same comm_sendApdu + dumps/load.php | APDUs and dump JSON |
Disconnected agent: comm_sendApdu returns 9999,0 without queueing. Timeout waiting for a reply: 9998,0.
Dump upload from the agent is not v2 JSON. After a dump command the agent still POSTs JSON to dumps/load.php (legacy).
tbl_agent_sessions_v2Created on first hello if missing. One row per sessionId (32 hex chars). connected is 1 until bye or aborted stream.
tbl_cli_msg (shared with legacy)sta | Name | Who sets it |
|---|---|---|
| 0 | Posted | Web server when the browser queues an APDU |
| 1 | Collected | stream.php when the command is sent on SSE |
| 2 | Responded | reply.php on RES_CMD_OK |
| -1 | Error | reply.php on RES_CMD_ERROR |
tbl_cli_status (shared with the web client)lastConnection is the presence signal. Stream + hello + reply + heartbeat refresh it. Bye / abort set it 60 s back so the 5 s window fails immediately.
When transport_v2 is off, the agent loops on:
GET {server}/{root_dir}/utils/reader_gw.php?cid=&ts=&seq=&msg=&res=
That PHP both collects the next tbl_cli_msg and writes the previous result in the query string. v2 splits that into stream + reply, but the web client and the tables stay the same.
| Agent action | Stream GET | tbl_agent_sessions_v2 | Web LED |
|---|---|---|---|
| Quit / window close | aborted | connected = 0 via bye | Off on next agent_status ( 2.5 s) |
| Stream idle noop | closed by server, agent reconnects | still 1 | Stays on (lastConnection refreshed on the next GET) |
| Process kill (no bye) | PHP notices abort and marks disconnected | 0 | Off |
| Lost network, process still running | stream errors, then agent stops after 3 failures | may stay 1 until 5 s presence timeout | Off after ~5 s |
| Script | What it covers |
|---|---|
tests/protocol_v2_e2e.php | Hello schema, SAM unknown, version gate, stream events, reply accepted/duplicate, heartbeat, bye, presence |
tests/protocol_v2_t2_live.php | Live agent + card (hardware) |
Date: 20 September 2026
When write preprocessing is on, Intertool does not copy the dumps Environment authenticator (EnvAuthenticator, envAuth) onto the card as-is. The seal is bound to the card CSN. This note describes how po_preproc_data() rewrites that field in the dump record before the update APDU is built.
Preprocessing runs from update_PO_from_DB() in php/lib_db.php when the write command is diff_update_PO_from_DB (writePreprocEnabled = true). The command diff_update_PO_from_DB_no_preproc skips this patch and writes the dump bits unchanged.
Write PO and Clone PO now default writePreprocEnabled to true, so envAuth rewriting is the default path. SELECT_PREPROC only shows or hides the checkbox; it does not choose the command.
| Item | Value |
|---|---|
| AID | A0000004040125090101 (and the 16-byte padded form) |
| File | SFI 07, record 01 (EnvHolder) |
| Field | EnvAuthenticator 16 bits |
| Dump payload | $p_data (hex record about to be written), modified in place |
| Live card | $rt_dump (reader-tree image of the same AID/SFI/record) |
| Code | php/lib_po_update_preproc.php po_preproc_data() |
| SAM calc | EnvAuthenticator(..., calcMode=true) in php/extension_intercode/ed_calculation_250901.php |
Other AIDs, SFIs and records are left unchanged.
s_hex2bin() expands each hex nibble to four ASCII bits (0/1). Offsets in the preprocessor are bit indexes, not bytes.
The hardcoded window substr(..., 59, 16) assumes the usual Intercode Environment bitmap without EnvPayMethod (bitmap bit 3 clear):
| Bits | Field |
|---|---|
| 05 | EnvApplicationVersionNumber |
| 612 | EnvBitmap |
| 1336 | EnvNetworkId |
| 3744 | EnvApplicationIssuerId |
| 4558 | EnvApplicationValidityEndDate |
| 5974 | EnvAuthenticator (the seal) |
| 75+ | Remainder of the record (holder and other data) not rewritten by this step |
The preprocessor splices only bits 5974. Network, issuer, validity date and holder data still come from the dump.
EnvAuthenticator is a SAM-computed seal over this portable object. Inputs include the card CSN (from FCI) and the application KVC (from FCP). A value taken from another card is invalid on this one.
Write-card preprocessing therefore treats the dump seal as a request (keep a seal / clear a seal), not as the bytes to program.
Both the dump record and the live card record are read at bits 5974. A field of all zeros is no seal.
| Dump envAuth | Card envAuth | Seal written to the card | Meaning |
|---|---|---|---|
0 | any | 0 (dump left unchanged) | Clear the seal (0 out the card) |
| non-zero | non-zero | Live card seal | Card already signed: keep its signature; apply the rest of the dump Environment |
| non-zero | 0 | SAM-calculated seal for this CSN | Blank / unsigned card: compute a new seal |
| non-zero | 0, SAM fails | Dump envAuth bits | Fallback if the SAM cannot calculate |
No patch. The dump already contains envAuth 0000, so the write programs zeros and clears the card seal. Used when the operator wants the card unsigned.
Bits 5974 of $p_data are replaced with the cards current 16 bits. The dumps envAuth is discarded.
This is the usual clone/update onto a card that is already personalized: Environment data (network, dates, holder, ) can change; the existing CSN-bound signature stays.
The card has never been signed (or was cleared). The server calls:
EnvAuthenticator(0, card FCI, card FCP, null, true)
calcMode = true asks the SAM to compute a 16-bit seal for this CSN and KVC (legacy or modern method from the FCP KVC). On success, that hex value is expanded to 16 bits and spliced into $p_data at bits 5974.
If the SAM call fails (success != true: unknown KVC, key missing, comms error), the dumps envAuth bits are kept so the write can still proceed.
Confirm Write PO / Clone PO sets write_cmd from MenuModel.writePreprocEnabled:
writePreprocEnabled | write_cmd | envAuth preprocessing |
|---|---|---|
true (default) | diff_update_PO_from_DB | Runs po_preproc_data() |
false | diff_update_PO_from_DB_no_preproc | Dump envAuth bits are written as stored |
Opening Write PO or Clone PO sets both the model and the checkbox to checked. Uncheck the preproc box to write the dump seal without rewriting.
lib_dump.php maps those commands to update_PO_from_DB(..., true) and update_PO_from_DB(..., false).
| File | Role |
|---|---|
php/lib_po_update_preproc.php | Decision and bit splice |
php/lib_db.php | Calls po_preproc_data() per record when $preproc is true |
dumps/lib_dump.php | diff_update_PO_from_DB / _no_preproc |
php/extension_intercode/ed_calculation_250901.php | SAM / DB calculation of the seal |
js/menu/MenuController.js | Chooses write_cmd; defaults preproc on |
js/menu/MenuModel.js | writePreprocEnabled default true |
views/modals/write_po.php | Preproc checkbox (visibility from SELECT_PREPROC) |
when a user's group changes, and regroup is selected, the owned folder and dump gid are updated. The user's group is updated in the database, and the owned folder and dump gid are updated in the file system.
It copies the dump into the Import tree.
TL Password support removed.
INT-33 https://gcnits.atlassian.net/browse/INT-33
Limit group rename to the shared root folder.
INT-48 https://gcnits.atlassian.net/browse/INT-48
The three User privileges options are exclusive now.
Show alert, confirm and prompt in in-app dialogs so they work in the Android WebView.
INT-42 INT-43 https://gcnits.atlassian.net/browse/INT-42 https://gcnits.atlassian.net/browse/INT-43
Disable Write to card and Clone when the reader SAM is locked or absent. Menu, drag-and-drop, and Reader Clone stay blocked until the SAM is present and unlocked.
When the global parameter dumpAutoload is 1, a card insert loads the dump into the reader tree, selects that dump, and shows Card Summary. If the user AID filter is not %, the application whose name contains that AID is selected. 0 leaves the tree unselected.
autoRefreshCardContent mode 2 loads the dump on insert when the reader tree is empty, and keeps the dump when the card is removed.
SAM counters refresh on agent connection only when UpdateSAMonAgentConnection is enabled. A missing or zero value skips those reads.
The login dialog opens when the main page is served without an active session.
Password self-service opens from the login dialog. The new password is checked as it is typed, and the user is signed in after a successful change.
The desktop layout stays side by side. PO and App tabs stay visible while their panel content scrolls. File system and raw tabs are hidden when expert view is off. The panel splitter is wider, and dump table headers stay pinned to the top of the PO content panels.
A compact layout for small screens and the agent WebView lets a reader dump be saved, written, and moved without drag-and-drop. A card insert opens the dump, a waiting write can start, and webviewDndEnable is honored. In simplified view the description column is hidden and redundant dump owner information is removed.
The compact bar shows edit icons, and library and reader commands follow the selected node.
Rehabilitate and invalidate wait for a card. The web indicator stays on card present after the dump reloads.
On a wide screen the library context menu sits above the panel. Compact and WebView layouts hide that menu.
Card control opens from the compact bar, and its PDF is handed to the Android agent. Library and Reader close that view. Revert, redo, and save stay available while Library or Reader is open.
The library dump filter opens in a dialog. Apply and Clear close the dialog, and the Filter item stays yellow while a filter is active.
The card control bar and panel fill the window. The PDF report can be emailed to the signed-in user.
autoRefreshCardContent is split into desktopAutoRefreshCardContent and androidAutoRefreshCardContent.
A user's decimal CID is accepted as a virtual SAM, so a shared phone can connect without a registered hardware SAM.
The agent download path serves the Android APK named for the site.
Super users can edit grouped elementary-data value lists, import and export them, and save a site overlay. Shared translation files stay unchanged.
A reader option gates the card control view. Without that option, the menu item is disabled, the compact-view button is hidden, and the page is refused.
Expert view is suspended on a small screen or in the agent WebView. The saved option is restored on a large screen.
A read-only status API reports the working-tree revision, redacted configuration hashes, and usage counts for a site. A bearer token authenticates it. secrets.php is never returned.
A super user can arm one git pull for 15 minutes from the admin console. The server accepts a single signed command and answers 404 when the window is closed. The status token cannot arm the site or pull.
Every super user sees the full System Parameters list. The company id no longer hides system parameters.
Sync database from files copies the merged common and site global_parameters.json into tbl_global_parameters, and inserts names that exist only in the files.
Export database to site file replaces the site global_parameters.json with every database row. The common file is not changed.
Card Summary and Container Parameters are formatted in the browser. Startup data can be edited, including the AID and application type bits. DF parameters can be edited for status, KVC, and KIF.
The full AID is shown with the application text. Decimal and hex serial numbers share a line. System issuer shares a line with chip type, and application type shares a line with application subtype.
Saving user options in the admin console leaves the expert view bit unchanged.
After the agent disconnects, the next status poll shows it as disconnected. An open v2 stream no longer keeps the indicator green until that request times out.
The card emulation option can export and apply a dump.