From fa830975285ac51fcba6e46d2aa4826a25d2edc1 Mon Sep 17 00:00:00 2001 From: "954801926@qq.com" Date: Sun, 6 Sep 2026 20:16:23 +0800 Subject: [PATCH] chore: gitignore esbuild test bundles and release dir --- .gitignore | 6 + tests/.hl-split-smoke.cjs | 236 --- tests/.zmodem-e2e.cjs | 3371 ------------------------------------- 3 files changed, 6 insertions(+), 3607 deletions(-) delete mode 100644 tests/.hl-split-smoke.cjs delete mode 100644 tests/.zmodem-e2e.cjs diff --git a/.gitignore b/.gitignore index 399ad26..37a53ab 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,9 @@ research/ *.tsbuildinfo .sftp-test-*.bin .sftp-dl-* + +tests/.commands-store.cjs +tests/.session-e2e.cjs +tests/.hl-split-smoke.cjs +tests/.zmodem-e2e.cjs +release/ diff --git a/tests/.hl-split-smoke.cjs b/tests/.hl-split-smoke.cjs deleted file mode 100644 index e4ed885..0000000 --- a/tests/.hl-split-smoke.cjs +++ /dev/null @@ -1,236 +0,0 @@ -// src/renderer/src/terminal/highlightEngine.ts -var ESCAPE_RE = /(\x1b\[[0-9;:?]*[A-Za-z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[()][0-9A-B]|\x1b[=>])/g; -var MAX_PER_RULE = 300; -var MAX_CHUNK = 512 * 1024; -function hexToRgb(hex) { - let h = (hex || "").trim().replace(/^#/, ""); - if (h.length === 3) h = h.replace(/./g, (c) => c + c); - if (!/^[0-9a-fA-F]{6}$/.test(h)) return { r: 255, g: 255, b: 255 }; - const n = parseInt(h, 16); - return { r: n >> 16 & 255, g: n >> 8 & 255, b: n & 255 }; -} -function tokenize(input) { - const out = []; - let acc = ""; - let i = 0; - let m; - while ((m = ESCAPE_RE.exec(input)) !== null) { - if (m.index > i) acc += input.slice(i, m.index); - if (acc.length > 0) { - out.push({ kind: "text", value: acc }); - acc = ""; - } - out.push({ kind: "seq", value: m[0] }); - i = m.index + m[0].length; - } - if (i < input.length) acc += input.slice(i); - if (acc.length > 0) out.push({ kind: "text", value: acc }); - return out; -} -function compileRules(rules2) { - const out = []; - for (const rule of rules2) { - if (!rule || rule.enabled === false) continue; - const pattern = rule.pattern; - if (typeof pattern !== "string" || pattern.length === 0) continue; - let regex; - try { - regex = new RegExp(pattern, "g"); - } catch { - continue; - } - const fg = typeof rule.color?.fg === "string" ? rule.color.fg : ""; - if (!/^#[0-9a-fA-F]{3}$|^#[0-9a-fA-F]{6}$/.test(fg)) continue; - const bg = typeof rule.color?.bg === "string" ? rule.color.bg : void 0; - out.push({ id: rule.id, regex, fg, bg, priority: rule.priority }); - } - out.sort((a, b) => a.priority - b.priority); - return out; -} -function wrap(text, fgHex, bgHex) { - const f = hexToRgb(fgHex); - let s = `\x1B[38;2;${f.r};${f.g};${f.b}`; - if (bgHex) { - const b = hexToRgb(bgHex); - s += `;48;2;${b.r};${b.g};${b.b}`; - } - return `${s}m${text}\x1B[0m`; -} -function overlaps(claimed, s, e) { - for (const c of claimed) { - if (s < c.end && e > c.start) return true; - } - return false; -} -function applyRun(text, rules2, budgets) { - if (text.length === 0) return ""; - const claimed = []; - for (let ri = 0; ri < rules2.length; ri++) { - const rule = rules2[ri]; - if (budgets[ri] <= 0) continue; - rule.regex.lastIndex = 0; - let m; - let made = 0; - while ((m = rule.regex.exec(text)) !== null) { - const start = m.index; - const end = start + m[0].length; - if (end <= start) { - rule.regex.lastIndex++; - continue; - } - if (!overlaps(claimed, start, end)) { - claimed.push({ start, end, fg: rule.fg, bg: rule.bg }); - made++; - budgets[ri]--; - if (budgets[ri] <= 0) break; - } - if (rule.regex.lastIndex === start) rule.regex.lastIndex++; - } - } - if (claimed.length === 0) return text; - claimed.sort((a, b) => a.start - b.start); - let out = ""; - let pos = 0; - for (const c of claimed) { - if (c.start > pos) out += text.slice(pos, c.start); - out += wrap(text.slice(c.start, c.end), c.fg, c.bg); - pos = c.end; - } - if (pos < text.length) out += text.slice(pos); - return out; -} -function applyHighlights(chunk, rules2) { - if (!chunk || rules2.length === 0) return chunk; - if (chunk.length > MAX_CHUNK) return chunk; - let budgets = rules2.map(() => MAX_PER_RULE); - let usedBudget = false; - let out = ""; - for (const token of tokenize(chunk)) { - if (token.kind === "seq") { - out += token.value; - continue; - } - if (token.value.includes("\x1B")) { - out += token.value; - continue; - } - const before = budgets.reduce((a, b) => a + b, 0); - out += applyRun(token.value, rules2, budgets); - const after = budgets.reduce((a, b) => a + b, 0); - if (after < before) usedBudget = true; - } - return usedBudget ? out : chunk; -} -function isIncompleteEscape(seg) { - if (seg === "\x1B") return true; - if (/^\x1b\[[0-9;:?]*$/.test(seg)) return true; - if (seg.startsWith("\x1B]") && !seg.includes("\x07") && !seg.includes("\x1B\\")) return true; - return false; -} -function lastEscapeEnd(input) { - let end = -1; - let m; - ESCAPE_RE.lastIndex = 0; - while ((m = ESCAPE_RE.exec(input)) !== null) end = m.index + m[0].length; - return end; -} -function findIncompleteIndex(input) { - const idx = input.lastIndexOf("\x1B"); - if (idx < 0) return -1; - return isIncompleteEscape(input.slice(idx)) ? idx : -1; -} -var MAX_CARRY = 1024; -var HighlightStream = class { - rules; - buffer = ""; - constructor(rules2) { - this.rules = rules2; - } - /** Swap the active rules without touching any buffered content. */ - setRules(rules2) { - this.rules = rules2; - } - /** True while content is held back (a pending flush will release it). */ - hasPending() { - return this.buffer.length > 0; - } - /** Join held bytes with `chunk`, return content safe to hand to xterm. */ - push(chunk) { - this.buffer += chunk; - const incompleteAt = findIncompleteIndex(this.buffer); - if (incompleteAt >= 0) { - const head2 = this.buffer.slice(0, incompleteAt); - const tail = this.buffer.slice(incompleteAt); - if (tail.length > MAX_CARRY) { - this.buffer = ""; - return applyHighlights(head2, this.rules) + tail; - } - this.buffer = tail; - return applyHighlights(head2, this.rules); - } - const lastEnd = lastEscapeEnd(this.buffer); - if (lastEnd < 0) { - if (this.buffer.length > MAX_CHUNK) { - const raw = this.buffer; - this.buffer = ""; - return applyHighlights(raw, this.rules); - } - return ""; - } - const head = this.buffer.slice(0, lastEnd); - this.buffer = this.buffer.slice(lastEnd); - return applyHighlights(head, this.rules); - } - /** Flush any held content (session end) — highlighted as a final run. */ - flush() { - const b = this.buffer; - this.buffer = ""; - return applyHighlights(b, this.rules); - } -}; - -// tests/hl-split-smoke.mjs -var rules = compileRules([ - { id: "okstate", pattern: "\\b(SUCCESS|PASS|OK|DONE)\\b", enabled: true, priority: 5, color: { fg: "#3fb950" } }, - { id: "badstate", pattern: "\\b(ERROR|FAILED)\\b", enabled: true, priority: 6, color: { fg: "#f85149" } }, - { id: "numbers", pattern: "\\b\\d+(?:\\.\\d+)?(?:%)?\\b", enabled: true, priority: 25, color: { fg: "#f2cc60" } }, - { id: "url", pattern: "https?://[^\\s]+", enabled: true, priority: 30, color: { fg: "#58a6ff" } } -]); -var banner = "\x1B]0;kimi \u2014 session\x07\x1B[38;2;79;168;255m\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E\x1B[0m\r\n\x1B[38;2;136;136;136mWelcome to Kimi Code!\x1B[0m \x1B[38;2;79;168;255m\u2502\x1B[0m send /help\r\n\x1B[38;2;224;224;224mModel: MiniMax-M3 0.41.038 ERROR 99% https://example.com/x\x1B[0m\r\n"; -var reference = applyHighlights(banner, rules); -var failed = 0; -var splitAt = (s, i) => [s.slice(0, i), s.slice(i)]; -for (let i = 1; i < banner.length - 1; i++) { - const [a, b] = splitAt(banner, i); - const stream = new HighlightStream(rules); - const out = stream.push(a) + stream.push(b) + stream.flush(); - if (out !== reference) { - failed++; - if (failed <= 3) { - console.log(`MISMATCH at split ${i}:`); - console.log(" got: " + JSON.stringify(out.slice(0, 120))); - console.log(" expected: " + JSON.stringify(reference.slice(0, 120))); - } - } -} -{ - const i = Math.floor(banner.length / 3); - const j = Math.floor(banner.length * 2 / 3); - const stream = new HighlightStream(rules); - const out = stream.push(banner.slice(0, i)) + stream.push(banner.slice(i, j)) + stream.push(banner.slice(j)) + stream.flush(); - if (out !== reference) failed++; -} -{ - const stream = new HighlightStream(rules); - let out = ""; - for (const ch of banner) out += stream.push(ch); - out += stream.flush(); - if (out !== reference) failed++; -} -if (failed === 0) { - console.log("SPLIT-SMOKE PASS: all split points byte-identical to single-chunk reference"); - process.exit(0); -} else { - console.log(`SPLIT-SMOKE FAIL: ${failed} mismatches`); - process.exit(1); -} diff --git a/tests/.zmodem-e2e.cjs b/tests/.zmodem-e2e.cjs deleted file mode 100644 index 52fc547..0000000 --- a/tests/.zmodem-e2e.cjs +++ /dev/null @@ -1,3371 +0,0 @@ -var __create = Object.create; -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __getProtoOf = Object.getPrototypeOf; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __commonJS = (cb, mod) => function __require() { - return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; -}; -var __export = (target, all) => { - for (var name2 in all) - __defProp(target, name2, { get: all[name2], enumerable: true }); -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( - // If the importer is in node compatibility mode or this is not an ESM - // file that has been converted to a CommonJS file using a Babel- - // compatible transform (i.e. "__esModule" has not been set), then set - // "default" to the CommonJS "module.exports" for node compatibility. - isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, - mod -)); -var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); - -// node_modules/zmodem.js/src/zmlib.js -var require_zmlib = __commonJS({ - "node_modules/zmodem.js/src/zmlib.js"(exports2, module2) { - "use strict"; - var Zmodem2 = module2.exports; - var ZDLE = 24; - var XON = 17; - var XOFF = 19; - var XON_HIGH = 128 | XON; - var XOFF_HIGH = 128 | XOFF; - var CAN = 24; - Zmodem2.ZMLIB = { - /** - * @property {number} The ZDLE constant, which ZMODEM uses for escaping - */ - ZDLE, - /** - * @property {number} XON - ASCII XON - */ - XON, - /** - * @property {number} XOFF - ASCII XOFF - */ - XOFF, - /** - * @property {number[]} ABORT_SEQUENCE - ZMODEM’s abort sequence - */ - ABORT_SEQUENCE: [CAN, CAN, CAN, CAN, CAN], - /** - * Remove octet values from the given array that ZMODEM always ignores. - * This will mutate the given array. - * - * @param {number[]} octets - The octet values to transform. - * Each array member should be an 8-bit unsigned integer (0-255). - * This object is mutated in the function. - * - * @returns {number[]} The passed-in array. This is the same object that is - * passed in. - */ - strip_ignored_bytes: function strip_ignored_bytes(octets) { - for (var o = octets.length - 1; o >= 0; o--) { - switch (octets[o]) { - case XON: - case XON_HIGH: - case XOFF: - case XOFF_HIGH: - octets.splice(o, 1); - continue; - } - } - return octets; - }, - /** - * Like Array.prototype.indexOf, but searches for a subarray - * rather than just a particular value. - * - * @param {Array} haystack - The array to search, i.e., the bigger. - * - * @param {Array} needle - The array whose values to find, - * i.e., the smaller. - * - * @returns {number} The position in “haystack” where “needle” - * first appears—or, -1 if “needle” doesn’t appear anywhere - * in “haystack”. - */ - find_subarray: function find_subarray(haystack, needle) { - var h = 0, n; - var start = Date.now(); - HAYSTACK: - while (h !== -1) { - h = haystack.indexOf(needle[0], h); - if (h === -1) break HAYSTACK; - for (n = 1; n < needle.length; n++) { - if (haystack[h + n] !== needle[n]) { - h++; - continue HAYSTACK; - } - } - return h; - } - return -1; - } - }; - } -}); - -// node_modules/zmodem.js/src/encode.js -var require_encode = __commonJS({ - "node_modules/zmodem.js/src/encode.js"(exports2, module2) { - "use strict"; - var Zmodem2 = module2.exports; - var HEX_DIGITS = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102]; - var HEX_OCTET_VALUE = {}; - for (hd = 0; hd < HEX_DIGITS.length; hd++) { - HEX_OCTET_VALUE[HEX_DIGITS[hd]] = hd; - } - var hd; - Zmodem2.ENCODELIB = { - /** - * Return an array with the given number as 2 big-endian bytes. - * - * @param {number} number - The number to encode. - * - * @returns {number[]} The octet values. - */ - pack_u16_be: function pack_u16_be(number) { - if (number > 65535) throw "Number cannot exceed 16 bits: " + number; - return [number >> 8, number & 255]; - }, - /** - * Return an array with the given number as 4 little-endian bytes. - * - * @param {number} number - The number to encode. - * - * @returns {number[]} The octet values. - */ - pack_u32_le: function pack_u32_le(number) { - var high_bytes = number / 65536; - return [ - number & 255, - (number & 65535) >> 8, - high_bytes & 255, - high_bytes >> 8 - ]; - }, - /** - * The inverse of pack_u16_be() - i.e., take in 2 octet values - * and parse them as an unsigned, 2-byte big-endian number. - * - * @param {number[]} octets - The octet values (2 of them). - * - * @returns {number} The decoded number. - */ - unpack_u16_be: function unpack_u16_be(bytes_arr) { - return (bytes_arr[0] << 8) + bytes_arr[1]; - }, - /** - * The inverse of pack_u32_le() - i.e., take in a 4-byte sequence - * and parse it as an unsigned, 4-byte little-endian number. - * - * @param {number[]} octets - The octet values (4 of them). - * - * @returns {number} The decoded number. - */ - unpack_u32_le: function unpack_u32_le(octets) { - return octets[0] + (octets[1] << 8) + (octets[2] << 16) + octets[3] * 16777216; - }, - /** - * Encode a series of octet values to be the octet values that - * correspond to the ASCII hex characters for each octet. The - * returned array is suitable for use as binary data. - * - * For example: - * - * Original Hex Returned - * 254 fe 102, 101 - * 12 0c 48, 99 - * 129 81 56, 49 - * - * @param {number[]} octets - The original octet values. - * - * @returns {number[]} The octet values that correspond to an ASCII - * representation of the given octets. - */ - octets_to_hex: function octets_to_hex(octets) { - var hex = []; - for (var o = 0; o < octets.length; o++) { - hex.push( - HEX_DIGITS[octets[o] >> 4], - HEX_DIGITS[octets[o] & 15] - ); - } - return hex; - }, - /** - * The inverse of octets_to_hex(): takes an array - * of hex octet pairs and returns their octet values. - * - * @param {number[]} hex_octets - The hex octet values. - * - * @returns {number[]} The parsed octet values. - */ - parse_hex_octets: function parse_hex_octets(hex_octets) { - var octets = new Array(hex_octets.length / 2); - for (var i = 0; i < octets.length; i++) { - octets[i] = (HEX_OCTET_VALUE[hex_octets[2 * i]] << 4) + HEX_OCTET_VALUE[hex_octets[1 + 2 * i]]; - } - return octets; - } - }; - } -}); - -// node_modules/zmodem.js/src/text.js -var require_text = __commonJS({ - "node_modules/zmodem.js/src/text.js"(exports2, module2) { - var _my_TextEncoder = class { - encode(text) { - text = unescape(encodeURIComponent(text)); - var bytes = new Array(text.length); - for (var b = 0; b < text.length; b++) { - bytes[b] = text.charCodeAt(b); - } - return new Uint8Array(bytes); - } - }; - var _my_TextDecoder = class { - decode(bytes) { - return decodeURIComponent(escape(String.fromCharCode.apply(String, bytes))); - } - }; - var Zmodem2 = module2.exports; - Zmodem2.Text = { - Encoder: typeof TextEncoder !== "undefined" ? TextEncoder : _my_TextEncoder, - Decoder: typeof TextDecoder !== "undefined" ? TextDecoder : _my_TextDecoder - }; - } -}); - -// node_modules/zmodem.js/src/zdle.js -var require_zdle = __commonJS({ - "node_modules/zmodem.js/src/zdle.js"(exports2, module2) { - "use strict"; - var Zmodem2 = module2.exports; - Object.assign( - Zmodem2, - require_zmlib() - ); - var encode_cur; - var encode_todo; - var ZDLE = Zmodem2.ZMLIB.ZDLE; - Zmodem2.ZDLE = class ZmodemZDLE { - /** - * Create a ZDLE encoder. - * - * @param {object} [config] - The initial configuration. - * @param {object} config.escape_ctrl_chars - Whether the ZDLE encoder - * should escape control characters. - */ - constructor(config) { - this._config = {}; - if (config) { - this.set_escape_ctrl_chars(!!config.escape_ctrl_chars); - } - } - /** - * Enable or disable control-character escaping. - * You should probably enable this for sender sessions. - * - * @param {boolean} value - Whether to enable (true) or disable (false). - */ - set_escape_ctrl_chars(value) { - if (typeof value !== "boolean") throw "need boolean!"; - if (value !== this._config.escape_ctrl_chars) { - this._config.escape_ctrl_chars = value; - this._setup_zdle_table(); - } - } - /** - * Whether or not control-character escaping is enabled. - * - * @return {boolean} Whether the escaping is on (true) or off (false). - */ - escapes_ctrl_chars() { - return !!this._config.escape_ctrl_chars; - } - //I don’t know of any Zmodem implementations that use ZESC8 - //(“escape_8th_bit”)?? - /* - ZMODEM software escapes ZDLE, 020, 0220, 021, 0221, 023, and 0223. If - preceded by 0100 or 0300 (@), 015 and 0215 are also escaped to protect the - Telenet command escape CR-@-CR. - */ - /** - * Encode an array of octet values and return it. - * This will mutate the given array. - * - * @param {number[]} octets - The octet values to transform. - * Each array member should be an 8-bit unsigned integer (0-255). - * This object is mutated in the function. - * - * @returns {number[]} The passed-in array, transformed. This is the - * same object that is passed in. - */ - encode(octets) { - if (!this._zdle_table) throw "No ZDLE encode table configured!"; - var zdle_table = this._zdle_table; - var last_code = this._lastcode; - var arrbuf = new ArrayBuffer(2 * octets.length); - var arrbuf_uint8 = new Uint8Array(arrbuf); - var escctl_yn = this._config.escape_ctrl_chars; - var arrbuf_i = 0; - for (encode_cur = 0; encode_cur < octets.length; encode_cur++) { - encode_todo = zdle_table[octets[encode_cur]]; - if (!encode_todo) { - console.trace(); - console.error("bad encode() call:", JSON.stringify(octets)); - this._lastcode = last_code; - throw "Invalid octet: " + octets[encode_cur]; - } - last_code = octets[encode_cur]; - if (encode_todo === 1) { - } else if (escctl_yn || encode_todo === 2 || (last_code & 127) === 64) { - arrbuf_uint8[arrbuf_i] = ZDLE; - arrbuf_i++; - last_code ^= 64; - } - arrbuf_uint8[arrbuf_i] = last_code; - arrbuf_i++; - } - this._lastcode = last_code; - octets.splice(0); - octets.push.apply(octets, new Uint8Array(arrbuf, 0, arrbuf_i)); - return octets; - } - /** - * Decode an array of octet values and return it. - * This will mutate the given array. - * - * @param {number[]} octets - The octet values to transform. - * Each array member should be an 8-bit unsigned integer (0-255). - * This object is mutated in the function. - * - * @returns {number[]} The passed-in array. - * This is the same object that is passed in. - */ - static decode(octets) { - for (var o = octets.length - 1; o >= 0; o--) { - if (octets[o] === ZDLE) { - octets.splice(o, 2, octets[o + 1] - 64); - } - } - return octets; - } - /** - * Remove, ZDLE-decode, and return bytes from the passed-in array. - * If the requested number of ZDLE-encoded bytes isn’t available, - * then the passed-in array is unmodified (and the return is undefined). - * - * @param {number[]} octets - The octet values to transform. - * Each array member should be an 8-bit unsigned integer (0-255). - * This object is mutated in the function. - * - * @param {number} offset - The number of (undecoded) bytes to skip - * at the beginning of the “octets” array. - * - * @param {number} count - The number of bytes (octet values) to return. - * - * @returns {number[]|undefined} An array with the requested number of - * decoded octet values, or undefined if that number of decoded - * octets isn’t available (given the passed-in offset). - */ - static splice(octets, offset, count) { - var so_far = 0; - if (!offset) offset = 0; - for (var i = offset; i < octets.length && so_far < count; i++) { - so_far++; - if (octets[i] === ZDLE) i++; - } - if (so_far === count) { - if (octets.length === i - 1) return; - octets.splice(0, offset); - return ZmodemZDLE.decode(octets.splice(0, i - offset)); - } - return; - } - _setup_zdle_table() { - var zsendline_tab = new Array(256); - for (var i = 0; i < zsendline_tab.length; i++) { - if (i & 96) { - zsendline_tab[i] = 1; - } else { - switch (i) { - case ZDLE: - //NB: no (ZDLE | 0x80) - case Zmodem2.ZMLIB.XOFF: - case Zmodem2.ZMLIB.XON: - case Zmodem2.ZMLIB.XOFF | 128: - case Zmodem2.ZMLIB.XON | 128: - zsendline_tab[i] = 2; - break; - case 16: - // 020 - case 144: - zsendline_tab[i] = this._config.turbo_escape ? 1 : 2; - break; - case 13: - // 015 - case 141: - zsendline_tab[i] = this._config.escape_ctrl_chars ? 2 : !this._config.turbo_escape ? 3 : 1; - break; - default: - zsendline_tab[i] = this._config.escape_ctrl_chars ? 2 : 1; - } - } - } - this._zdle_table = zsendline_tab; - } - }; - } -}); - -// node_modules/crc-32/crc32.js -var require_crc32 = __commonJS({ - "node_modules/crc-32/crc32.js"(exports2) { - var CRC32; - (function(factory) { - if (typeof DO_NOT_EXPORT_CRC === "undefined") { - if ("object" === typeof exports2) { - factory(exports2); - } else if ("function" === typeof define && define.amd) { - define(function() { - var module3 = {}; - factory(module3); - return module3; - }); - } else { - factory(CRC32 = {}); - } - } else { - factory(CRC32 = {}); - } - })(function(CRC322) { - CRC322.version = "1.2.2"; - function signed_crc_table() { - var c = 0, table = new Array(256); - for (var n = 0; n != 256; ++n) { - c = n; - c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1; - c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1; - c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1; - c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1; - c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1; - c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1; - c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1; - c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1; - table[n] = c; - } - return typeof Int32Array !== "undefined" ? new Int32Array(table) : table; - } - var T0 = signed_crc_table(); - function slice_by_16_tables(T) { - var c = 0, v = 0, n = 0, table = typeof Int32Array !== "undefined" ? new Int32Array(4096) : new Array(4096); - for (n = 0; n != 256; ++n) table[n] = T[n]; - for (n = 0; n != 256; ++n) { - v = T[n]; - for (c = 256 + n; c < 4096; c += 256) v = table[c] = v >>> 8 ^ T[v & 255]; - } - var out = []; - for (n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== "undefined" ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256); - return out; - } - var TT = slice_by_16_tables(T0); - var T1 = TT[0], T2 = TT[1], T3 = TT[2], T4 = TT[3], T5 = TT[4]; - var T6 = TT[5], T7 = TT[6], T8 = TT[7], T9 = TT[8], Ta = TT[9]; - var Tb = TT[10], Tc = TT[11], Td = TT[12], Te = TT[13], Tf = TT[14]; - function crc32_bstr(bstr, seed) { - var C = seed ^ -1; - for (var i = 0, L = bstr.length; i < L; ) C = C >>> 8 ^ T0[(C ^ bstr.charCodeAt(i++)) & 255]; - return ~C; - } - function crc32_buf(B, seed) { - var C = seed ^ -1, L = B.length - 15, i = 0; - for (; i < L; ) C = Tf[B[i++] ^ C & 255] ^ Te[B[i++] ^ C >> 8 & 255] ^ Td[B[i++] ^ C >> 16 & 255] ^ Tc[B[i++] ^ C >>> 24] ^ Tb[B[i++]] ^ Ta[B[i++]] ^ T9[B[i++]] ^ T8[B[i++]] ^ T7[B[i++]] ^ T6[B[i++]] ^ T5[B[i++]] ^ T4[B[i++]] ^ T3[B[i++]] ^ T2[B[i++]] ^ T1[B[i++]] ^ T0[B[i++]]; - L += 15; - while (i < L) C = C >>> 8 ^ T0[(C ^ B[i++]) & 255]; - return ~C; - } - function crc32_str(str, seed) { - var C = seed ^ -1; - for (var i = 0, L = str.length, c = 0, d = 0; i < L; ) { - c = str.charCodeAt(i++); - if (c < 128) { - C = C >>> 8 ^ T0[(C ^ c) & 255]; - } else if (c < 2048) { - C = C >>> 8 ^ T0[(C ^ (192 | c >> 6 & 31)) & 255]; - C = C >>> 8 ^ T0[(C ^ (128 | c & 63)) & 255]; - } else if (c >= 55296 && c < 57344) { - c = (c & 1023) + 64; - d = str.charCodeAt(i++) & 1023; - C = C >>> 8 ^ T0[(C ^ (240 | c >> 8 & 7)) & 255]; - C = C >>> 8 ^ T0[(C ^ (128 | c >> 2 & 63)) & 255]; - C = C >>> 8 ^ T0[(C ^ (128 | d >> 6 & 15 | (c & 3) << 4)) & 255]; - C = C >>> 8 ^ T0[(C ^ (128 | d & 63)) & 255]; - } else { - C = C >>> 8 ^ T0[(C ^ (224 | c >> 12 & 15)) & 255]; - C = C >>> 8 ^ T0[(C ^ (128 | c >> 6 & 63)) & 255]; - C = C >>> 8 ^ T0[(C ^ (128 | c & 63)) & 255]; - } - } - return ~C; - } - CRC322.table = T0; - CRC322.bstr = crc32_bstr; - CRC322.buf = crc32_buf; - CRC322.str = crc32_str; - }); - } -}); - -// node_modules/zmodem.js/src/zerror.js -var require_zerror = __commonJS({ - "node_modules/zmodem.js/src/zerror.js"(exports2, module2) { - "use strict"; - var Zmodem2 = module2.exports; - function _crc_message(got, expected) { - this.got = got.slice(0); - this.expected = expected.slice(0); - return "CRC check failed! (got: " + got.join() + "; expected: " + expected.join() + ")"; - } - function _pass(val) { - return val; - } - var TYPE_MESSAGE = { - aborted: "Session aborted", - peer_aborted: "Peer aborted session", - already_aborted: "Session already aborted", - crc: _crc_message, - validation: _pass - }; - function _generate_message(type) { - const msg = TYPE_MESSAGE[type]; - switch (typeof msg) { - case "string": - return msg; - case "function": - var args_after_type = [].slice.call(arguments).slice(1); - return msg.apply(this, args_after_type); - } - return null; - } - Zmodem2.Error = class ZmodemError extends Error { - constructor(msg_or_type) { - super(); - var generated = _generate_message.apply(this, arguments); - if (generated) { - this.type = msg_or_type; - this.message = generated; - } else { - this.message = msg_or_type; - } - } - }; - } -}); - -// node_modules/zmodem.js/src/zcrc.js -var require_zcrc = __commonJS({ - "node_modules/zmodem.js/src/zcrc.js"(exports2, module2) { - "use strict"; - var CRC32_MOD = require_crc32(); - var Zmodem2 = module2.exports; - Object.assign( - Zmodem2, - require_zerror(), - require_encode() - ); - var _crctab; - var crc_width = 16; - var crc_polynomial = 4129; - var crc_castmask = 65535; - var crc_msbmask = 1 << crc_width - 1; - function _compute_crctab() { - _crctab = new Array(256); - var divident_shift = crc_width - 8; - for (var divident = 0; divident < 256; divident++) { - var currByte = divident << divident_shift & crc_castmask; - for (var bit = 0; bit < 8; bit++) { - if ((currByte & crc_msbmask) !== 0) { - currByte <<= 1; - currByte ^= crc_polynomial; - } else { - currByte <<= 1; - } - } - _crctab[divident] = currByte & crc_castmask; - } - } - function _updcrc(cp, crc) { - if (!_crctab) _compute_crctab(); - return _crctab[crc >> 8 & 255] ^ (255 & crc) << 8 ^ cp; - } - function __verify(expect, got) { - var err; - if (expect.join() !== got.join()) { - throw new Zmodem2.Error("crc", got, expect); - } - } - Zmodem2.CRC = { - //https://www.lammertbies.nl/comm/info/crc-calculation.html - //CRC-CCITT (XModem) - /** - * Deduce a given set of octet values’ CRC16, as per the CRC16 - * variant that ZMODEM uses (CRC-CCITT/XModem). - * - * @param {Array} octets - The array of octet values. - * Each array member should be an 8-bit unsigned integer (0-255). - * - * @returns {Array} crc - The CRC, expressed as an array of octet values. - */ - crc16: function crc16(octet_nums) { - var crc = octet_nums[0]; - for (var b = 1; b < octet_nums.length; b++) { - crc = _updcrc(octet_nums[b], crc); - } - crc = _updcrc(0, _updcrc(0, crc)); - return Zmodem2.ENCODELIB.pack_u16_be(crc); - }, - /** - * Deduce a given set of octet values’ CRC32. - * - * @param {Array} octets - The array of octet values. - * Each array member should be an 8-bit unsigned integer (0-255). - * - * @returns {Array} crc - The CRC, expressed as an array of octet values. - */ - crc32: function crc32(octet_nums) { - return Zmodem2.ENCODELIB.pack_u32_le( - CRC32_MOD.buf(octet_nums) >>> 0 - //bit-shift to get unsigned - ); - }, - /** - * Verify a given set of octet values’ CRC16. - * An exception is thrown on failure. - * - * @param {Array} bytes_arr - The array of octet values. - * Each array member should be an 8-bit unsigned integer (0-255). - * - * @param {Array} crc - The CRC to check against, expressed as - * an array of octet values. - */ - verify16: function verify16(bytes_arr, got) { - return __verify(this.crc16(bytes_arr), got); - }, - /** - * Verify a given set of octet values’ CRC32. - * An exception is thrown on failure. - * - * @param {Array} bytes_arr - The array of octet values. - * Each array member should be an 8-bit unsigned integer (0-255). - * - * @param {Array} crc - The CRC to check against, expressed as - * an array of octet values. - */ - verify32: function verify32(bytes_arr, crc) { - try { - __verify(this.crc32(bytes_arr), crc); - } catch (err) { - err.input = bytes_arr.slice(0); - throw err; - } - } - }; - } -}); - -// node_modules/zmodem.js/src/zheader.js -var require_zheader = __commonJS({ - "node_modules/zmodem.js/src/zheader.js"(exports2, module2) { - "use strict"; - var Zmodem2 = module2.exports; - Object.assign( - Zmodem2, - require_encode(), - require_zdle(), - require_zmlib(), - require_zcrc(), - require_zerror() - ); - var ZPAD = "*".charCodeAt(0); - var ZBIN = "A".charCodeAt(0); - var ZHEX = "B".charCodeAt(0); - var ZBIN32 = "C".charCodeAt(0); - var HEX_HEADER_CRLF = [13, 10]; - var HEX_HEADER_CRLF_XON = HEX_HEADER_CRLF.slice(0).concat([Zmodem2.ZMLIB.XON]); - var HEX_HEADER_PREFIX = [ZPAD, ZPAD, Zmodem2.ZMLIB.ZDLE, ZHEX]; - var BINARY16_HEADER_PREFIX = [ZPAD, Zmodem2.ZMLIB.ZDLE, ZBIN]; - var BINARY32_HEADER_PREFIX = [ZPAD, Zmodem2.ZMLIB.ZDLE, ZBIN32]; - Zmodem2.Header = class ZmodemHeader { - //lrzsz’s “sz” command sends a random (?) CR/0x0d byte - //after ZEOF. Let’s accommodate 0x0a, 0x0d, 0x8a, and 0x8d. - // - //Also, when you skip a file, sz outputs a message about it. - // - //It appears that we’re supposed to ignore anything until - //[ ZPAD, ZDLE ] when we’re looking for a header. - /** - * Weed out the leading bytes that aren’t valid to start a ZMODEM header. - * - * @param {number[]} ibuffer - The octet values to parse. - * Each array member should be an 8-bit unsigned integer (0-255). - * This object is mutated in the function. - * - * @returns {number[]} The octet values that were removed from the start - * of “ibuffer”. Order is preserved. - */ - static trim_leading_garbage(ibuffer) { - var garbage = []; - var discard_all, parser, next_ZPAD_at_least = 0; - TRIM_LOOP: - while (ibuffer.length && !parser) { - var first_ZPAD = ibuffer.indexOf(ZPAD); - if (first_ZPAD === -1) { - discard_all = true; - break TRIM_LOOP; - } else { - garbage.push.apply(garbage, ibuffer.splice(0, first_ZPAD)); - if (ibuffer.length < 2) { - break TRIM_LOOP; - } else if (ibuffer[1] === ZPAD) { - if (ibuffer.length < HEX_HEADER_PREFIX.length) { - if (ibuffer.join() === HEX_HEADER_PREFIX.slice(0, ibuffer.length).join()) { - break TRIM_LOOP; - } - } else if (ibuffer[2] === HEX_HEADER_PREFIX[2] && ibuffer[3] === HEX_HEADER_PREFIX[3]) { - parser = _parse_hex; - } - } else if (ibuffer[1] === Zmodem2.ZMLIB.ZDLE) { - if (ibuffer.length < BINARY16_HEADER_PREFIX.length) { - break TRIM_LOOP; - } - if (ibuffer[2] === BINARY16_HEADER_PREFIX[2]) { - parser = _parse_binary16; - } else if (ibuffer[2] === BINARY32_HEADER_PREFIX[2]) { - parser = _parse_binary32; - } - } - if (!parser) { - garbage.push(ibuffer.shift()); - } - } - } - if (discard_all) { - garbage.push.apply(garbage, ibuffer.splice(0)); - } - return garbage; - } - /** - * Parse out a Header object from a given array of octet values. - * - * An exception is thrown if the given bytes are definitively invalid - * as header values. - * - * @param {number[]} octets - The octet values to parse. - * Each array member should be an 8-bit unsigned integer (0-255). - * This object is mutated in the function. - * - * @returns {Header|undefined} An instance of the appropriate Header - * subclass, or undefined if not enough octet values are given - * to determine whether there is a valid header here or not. - */ - static parse(octets) { - var hdr; - if (octets[1] === ZPAD) { - hdr = _parse_hex(octets); - return hdr && [hdr, 16]; - } else if (octets[2] === ZBIN) { - hdr = _parse_binary16(octets, 3); - return hdr && [hdr, 16]; - } else if (octets[2] === ZBIN32) { - hdr = _parse_binary32(octets); - return hdr && [hdr, 32]; - } - if (octets.length < 3) return; - throw "Unrecognized/unsupported octets: " + octets.join(); - } - /** - * Build a Header subclass given a name and arguments. - * - * @param {string} name - The header type name, e.g., “ZRINIT”. - * - * @param {...*} args - The arguments to pass to the appropriate - * subclass constructor. These aren’t documented currently - * but are pretty easy to glean from the code. - * - * @returns {Header} An instance of the appropriate Header subclass. - */ - static build(name2) { - var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments); - var Ctr = FRAME_NAME_CREATOR[name2]; - if (!Ctr) throw "No frame class \u201C" + name2 + "\u201D is defined!"; - args.shift(); - var hdr = new (Ctr.bind.apply(Ctr, [null].concat(args)))(); - return hdr; - } - /** - * Return the octet values array that represents the object - * in ZMODEM hex encoding. - * - * @returns {number[]} An array of octet values suitable for sending - * as binary data. - */ - to_hex() { - var to_crc = this._crc_bytes(); - return HEX_HEADER_PREFIX.concat( - Zmodem2.ENCODELIB.octets_to_hex(to_crc.concat(Zmodem2.CRC.crc16(to_crc))), - this._hex_header_ending - ); - } - /** - * Return the octet values array that represents the object - * in ZMODEM binary encoding with a 16-bit CRC. - * - * @param {ZDLE} zencoder - A ZDLE instance to use for - * ZDLE encoding. - * - * @returns {number[]} An array of octet values suitable for sending - * as binary data. - */ - to_binary16(zencoder) { - return this._to_binary(zencoder, BINARY16_HEADER_PREFIX, Zmodem2.CRC.crc16); - } - /** - * Return the octet values array that represents the object - * in ZMODEM binary encoding with a 32-bit CRC. - * - * @param {ZDLE} zencoder - A ZDLE instance to use for - * ZDLE encoding. - * - * @returns {number[]} An array of octet values suitable for sending - * as binary data. - */ - to_binary32(zencoder) { - return this._to_binary(zencoder, BINARY32_HEADER_PREFIX, Zmodem2.CRC.crc32); - } - //This is never called directly, but only as super(). - constructor() { - if (!this._bytes4) { - this._bytes4 = [0, 0, 0, 0]; - } - } - _to_binary(zencoder, prefix, crc_func) { - var to_crc = this._crc_bytes(); - var octets = prefix.concat( - zencoder.encode(to_crc.concat(crc_func(to_crc))) - ); - return octets; - } - _crc_bytes() { - return [this.TYPENUM].concat(this._bytes4); - } - }; - Zmodem2.Header.prototype._hex_header_ending = HEX_HEADER_CRLF_XON; - var ZRQINIT_HEADER = class extends Zmodem2.Header { - }; - var ZRINIT_FLAG = { - //---------------------------------------------------------------------- - // Bit Masks for ZRINIT flags byte ZF0 - //---------------------------------------------------------------------- - CANFDX: 1, - // Rx can send and receive true FDX - CANOVIO: 2, - // Rx can receive data during disk I/O - CANBRK: 4, - // Rx can send a break signal - CANCRY: 8, - // Receiver can decrypt -- nothing does this - CANLZW: 16, - // Receiver can uncompress -- nothing does this - CANFC32: 32, - // Receiver can use 32 bit Frame Check - ESCCTL: 64, - // Receiver expects ctl chars to be escaped - ESC8: 128 - // Receiver expects 8th bit to be escaped - }; - function _get_ZRINIT_flag_num(fl) { - if (!ZRINIT_FLAG[fl]) { - throw new Zmodem2.Error("Invalid ZRINIT flag: " + fl); - } - return ZRINIT_FLAG[fl]; - } - var ZRINIT_HEADER = class extends Zmodem2.Header { - constructor(flags_arr, bufsize) { - super(); - var flags_num = 0; - if (!bufsize) bufsize = 0; - flags_arr.forEach(function(fl) { - flags_num |= _get_ZRINIT_flag_num(fl); - }); - this._bytes4 = [ - bufsize & 255, - bufsize >> 8, - 0, - flags_num - ]; - } - //undefined if nonstop I/O is allowed - get_buffer_size() { - return Zmodem2.ENCODELIB.unpack_u16_be(this._bytes4.slice(0, 2)) || void 0; - } - //Unimplemented: - // can_decrypt - // can_decompress - //---------------------------------------------------------------------- - //function names taken from Jacques Mattheij’s implementation, - //as used in syncterm. - can_full_duplex() { - return !!(this._bytes4[3] & ZRINIT_FLAG.CANFDX); - } - can_overlap_io() { - return !!(this._bytes4[3] & ZRINIT_FLAG.CANOVIO); - } - can_break() { - return !!(this._bytes4[3] & ZRINIT_FLAG.CANBRK); - } - can_fcs_32() { - return !!(this._bytes4[3] & ZRINIT_FLAG.CANFC32); - } - escape_ctrl_chars() { - return !!(this._bytes4[3] & ZRINIT_FLAG.ESCCTL); - } - //Is this used? I don’t see it used in lrzsz or syncterm - //Looks like it was a “foreseen” feature that Forsberg - //never implemented. (The need for it went away, maybe?) - escape_8th_bit() { - return !!(this._bytes4[3] & ZRINIT_FLAG.ESC8); - } - }; - var ZSINIT_FLAG = { - ESCCTL: 64, - // Transmitter will escape ctl chars - ESC8: 128 - // Transmitter will escape 8th bit - }; - function _get_ZSINIT_flag_num(fl) { - if (!ZSINIT_FLAG[fl]) { - throw "Invalid ZSINIT flag: " + fl; - } - return ZSINIT_FLAG[fl]; - } - var ZSINIT_HEADER = class extends Zmodem2.Header { - constructor(flags_arr, attn_seq_arr) { - super(); - var flags_num = 0; - flags_arr.forEach(function(fl) { - flags_num |= _get_ZSINIT_flag_num(fl); - }); - this._bytes4 = [0, 0, 0, flags_num]; - if (attn_seq_arr) { - if (attn_seq_arr.length > 31) { - throw "Attn sequence must be <= 31 bytes"; - } - if (attn_seq_arr.some(function(num) { - return num > 255; - })) { - throw "Attn sequence (" + attn_seq_arr + ") must be <256"; - } - this._data = attn_seq_arr.concat([0]); - } - } - escape_ctrl_chars() { - return !!(this._bytes4[3] & ZSINIT_FLAG.ESCCTL); - } - //Is this used? I don’t see it used in lrzsz or syncterm - escape_8th_bit() { - return !!(this._bytes4[3] & ZSINIT_FLAG.ESC8); - } - }; - var ZACK_HEADER = class extends Zmodem2.Header { - constructor(payload4) { - super(); - if (payload4) { - this._bytes4 = payload4.slice(); - } - } - }; - ZACK_HEADER.prototype._hex_header_ending = HEX_HEADER_CRLF; - var ZFILE_VALUES = { - //ZF3 (i.e., first byte) - extended: { - sparse: 64 - //ZXSPARS - }, - //ZF2 - transport: [ - void 0, - "compress", - //ZTLZW - "encrypt", - //ZTCRYPT - "rle" - //ZTRLE - ], - //ZF1 - management: [ - void 0, - "newer_or_longer", - //ZF1_ZMNEWL - "crc", - //ZF1_ZMCRC - "append", - //ZF1_ZMAPND - "clobber", - //ZF1_ZMCLOB - "newer", - //ZF1_ZMNEW - "mtime_or_length", - //ZF1_ZMNEW - "protect", - //ZF1_ZMPROT - "rename" - //ZF1_ZMPROT - ], - //ZF0 (i.e., last byte) - conversion: [ - void 0, - "binary", - //ZCBIN - "text", - //ZCNL - "resume" - //ZCRESUM - ] - }; - var ZFILE_ORDER = ["extended", "transport", "management", "conversion"]; - var ZMSKNOLOC = 128; - var MANAGEMENT_MASK = 31; - var ZXSPARS = 64; - var ZFILE_HEADER = class extends Zmodem2.Header { - //TODO: allow options on instantiation - get_options() { - var opts = { - sparse: !!(this._bytes4[0] & ZXSPARS) - }; - var bytes_copy = this._bytes4.slice(0); - ZFILE_ORDER.forEach(function(key, i) { - if (ZFILE_VALUES[key] instanceof Array) { - if (key === "management") { - opts.skip_if_absent = !!(bytes_copy[i] & ZMSKNOLOC); - bytes_copy[i] &= MANAGEMENT_MASK; - } - opts[key] = ZFILE_VALUES[key][bytes_copy[i]]; - } else { - for (var extkey in ZFILE_VALUES[key]) { - opts[extkey] = !!(bytes_copy[i] & ZFILE_VALUES[key][extkey]); - if (opts[extkey]) { - bytes_copy[i] ^= ZFILE_VALUES[key][extkey]; - } - } - } - if (!opts[key] && bytes_copy[i]) { - opts[key] = "unknown:" + bytes_copy[i]; - } - }); - return opts; - } - }; - var ZSKIP_HEADER = class extends Zmodem2.Header { - }; - var ZABORT_HEADER = class extends Zmodem2.Header { - }; - var ZFIN_HEADER = class extends Zmodem2.Header { - }; - var ZFERR_HEADER = class extends Zmodem2.Header { - }; - ZFIN_HEADER.prototype._hex_header_ending = HEX_HEADER_CRLF; - var ZOffsetHeader = class extends Zmodem2.Header { - constructor(offset) { - super(); - this._bytes4 = Zmodem2.ENCODELIB.pack_u32_le(offset); - } - get_offset() { - return Zmodem2.ENCODELIB.unpack_u32_le(this._bytes4); - } - }; - var ZRPOS_HEADER = class extends ZOffsetHeader { - }; - var ZDATA_HEADER = class extends ZOffsetHeader { - }; - var ZEOF_HEADER = class extends ZOffsetHeader { - }; - var FRAME_CLASS_TYPES = [ - [ZRQINIT_HEADER, "ZRQINIT"], - [ZRINIT_HEADER, "ZRINIT"], - [ZSINIT_HEADER, "ZSINIT"], - [ZACK_HEADER, "ZACK"], - [ZFILE_HEADER, "ZFILE"], - [ZSKIP_HEADER, "ZSKIP"], - void 0, - // [ ZNAK_HEADER, "ZNAK" ], - [ZABORT_HEADER, "ZABORT"], - [ZFIN_HEADER, "ZFIN"], - [ZRPOS_HEADER, "ZRPOS"], - [ZDATA_HEADER, "ZDATA"], - [ZEOF_HEADER, "ZEOF"], - [ZFERR_HEADER, "ZFERR"], - //see note - void 0, - //[ ZCRC_HEADER, "ZCRC" ], - void 0, - //[ ZCHALLENGE_HEADER, "ZCHALLENGE" ], - void 0, - //[ ZCOMPL_HEADER, "ZCOMPL" ], - void 0, - //[ ZCAN_HEADER, "ZCAN" ], - void 0, - //[ ZFREECNT_HEADER, "ZFREECNT" ], - void 0, - //[ ZCOMMAND_HEADER, "ZCOMMAND" ], - void 0 - //[ ZSTDERR_HEADER, "ZSTDERR" ], - ]; - var FRAME_NAME_CREATOR = {}; - for (fc = 0; fc < FRAME_CLASS_TYPES.length; fc++) { - if (!FRAME_CLASS_TYPES[fc]) continue; - FRAME_NAME_CREATOR[FRAME_CLASS_TYPES[fc][1]] = FRAME_CLASS_TYPES[fc][0]; - Object.assign( - FRAME_CLASS_TYPES[fc][0].prototype, - { - TYPENUM: fc, - NAME: FRAME_CLASS_TYPES[fc][1] - } - ); - } - var fc; - var CREATORS = [ - ZRQINIT_HEADER, - ZRINIT_HEADER, - ZSINIT_HEADER, - ZACK_HEADER, - ZFILE_HEADER, - ZSKIP_HEADER, - "ZNAK", - ZABORT_HEADER, - ZFIN_HEADER, - ZRPOS_HEADER, - ZDATA_HEADER, - ZEOF_HEADER, - ZFERR_HEADER, - "ZCRC", - //ZCRC_HEADER, -- leaving unimplemented? - "ZCHALLENGE", - "ZCOMPL", - "ZCAN", - "ZFREECNT", - // ZFREECNT_HEADER, - "ZCOMMAND", - "ZSTDERR" - ]; - function _get_blank_header(typenum) { - var creator = CREATORS[typenum]; - if (typeof creator === "string") { - throw "Received unsupported header: " + creator; - } - return _get_blank_header_from_constructor(creator); - } - function _get_blank_header_from_constructor(creator) { - if (creator.prototype instanceof ZOffsetHeader) { - return new creator(0); - } - return new creator([]); - } - function _parse_binary16(bytes_arr) { - var zdle_decoded = Zmodem2.ZDLE.splice(bytes_arr, BINARY16_HEADER_PREFIX.length, 7); - return zdle_decoded && _parse_non_zdle_binary16(zdle_decoded); - } - function _parse_non_zdle_binary16(decoded) { - Zmodem2.CRC.verify16( - decoded.slice(0, 5), - decoded.slice(5) - ); - var typenum = decoded[0]; - var hdr = _get_blank_header(typenum); - hdr._bytes4 = decoded.slice(1, 5); - return hdr; - } - function _parse_binary32(bytes_arr) { - var zdle_decoded = Zmodem2.ZDLE.splice( - bytes_arr, - //omit the leading "*", ZDLE, and "C" - BINARY32_HEADER_PREFIX.length, - 9 - ); - if (!zdle_decoded) return; - Zmodem2.CRC.verify32( - zdle_decoded.slice(0, 5), - zdle_decoded.slice(5) - ); - var typenum = zdle_decoded[0]; - var hdr = _get_blank_header(typenum); - hdr._bytes4 = zdle_decoded.slice(1, 5); - return hdr; - } - function _parse_hex(bytes_arr) { - var lf_pos = bytes_arr.indexOf(138); - if (-1 === lf_pos) { - lf_pos = bytes_arr.indexOf(10); - } - var hdr_err, hex_bytes; - if (-1 === lf_pos) { - if (bytes_arr.length > 11) { - hdr_err = "Invalid hex header - no LF detected within 12 bytes!"; - } - return; - } else { - hex_bytes = bytes_arr.splice(0, lf_pos); - bytes_arr.shift(); - if (hex_bytes.length === 19) { - var preceding = hex_bytes.pop(); - if (preceding !== 13 && preceding !== 141) { - hdr_err = "Invalid hex header: (CR/)LF doesn\u2019t have CR!"; - } - } else if (hex_bytes.length !== 18) { - hdr_err = "Invalid hex header: invalid number of bytes before LF!"; - } - } - if (hdr_err) { - hdr_err += " (" + hex_bytes.length + " bytes: " + hex_bytes.join() + ")"; - throw hdr_err; - } - hex_bytes.splice(0, 4); - var octets = Zmodem2.ENCODELIB.parse_hex_octets(hex_bytes); - return _parse_non_zdle_binary16(octets); - } - Zmodem2.Header.parse_hex = _parse_hex; - } -}); - -// node_modules/zmodem.js/src/zsubpacket.js -var require_zsubpacket = __commonJS({ - "node_modules/zmodem.js/src/zsubpacket.js"(exports2, module2) { - "use strict"; - var Zmodem2 = module2.exports; - Object.assign( - Zmodem2, - require_zcrc(), - require_zdle(), - require_zmlib(), - require_zerror() - ); - var ZCRCE = 104; - var ZCRCG = 105; - var ZCRCQ = 106; - var ZCRCW = 107; - var SUBPACKET_BUILDER; - Zmodem2.Subpacket = class ZmodemSubpacket { - /** - * Build a Subpacket subclass given a payload and frame end string. - * - * @param {Array} octets - The octet values to parse. - * Each array member should be an 8-bit unsigned integer (0-255). - * - * @param {string} frameend - One of: - * - `no_end_no_ack` - * - `end_no_ack` - * - `no_end_ack` (unused currently) - * - `end_ack` - * - * @returns {Subpacket} An instance of the appropriate Subpacket subclass. - */ - static build(octets, frameend) { - var Ctr = SUBPACKET_BUILDER[frameend]; - if (!Ctr) { - throw "No subpacket type \u201C" + frameend + "\u201D is defined! Try one of: " + Object.keys(SUBPACKET_BUILDER).join(", "); - } - return new Ctr(octets); - } - /** - * Return the octet values array that represents the object - * encoded with a 16-bit CRC. - * - * @param {ZDLE} zencoder - A ZDLE instance to use for ZDLE encoding. - * - * @returns {number[]} An array of octet values suitable for sending - * as binary data. - */ - encode16(zencoder) { - return this._encode(zencoder, Zmodem2.CRC.crc16); - } - /** - * Return the octet values array that represents the object - * encoded with a 32-bit CRC. - * - * @param {ZDLE} zencoder - A ZDLE instance to use for ZDLE encoding. - * - * @returns {number[]} An array of octet values suitable for sending - * as binary data. - */ - encode32(zencoder) { - return this._encode(zencoder, Zmodem2.CRC.crc32); - } - /** - * Return the subpacket payload’s octet values. - * - * NOTE: For speed, this returns the actual data in the subpacket; - * if you mutate this return value, you alter the Subpacket object - * internals. This is OK if you won’t need the Subpacket anymore, but - * just be careful. - * - * @returns {number[]} The subpacket’s payload, represented as an - * array of octet values. **DO NOT ALTER THIS ARRAY** unless you - * no longer need the Subpacket. - */ - get_payload() { - return this._payload; - } - /** - * Parse out a Subpacket object from a given array of octet values, - * assuming a 16-bit CRC. - * - * An exception is thrown if the given bytes are definitively invalid - * as subpacket values with 16-bit CRC. - * - * @param {number[]} octets - The octet values to parse. - * Each array member should be an 8-bit unsigned integer (0-255). - * This object is mutated in the function. - * - * @returns {Subpacket|undefined} An instance of the appropriate Subpacket - * subclass, or undefined if not enough octet values are given - * to determine whether there is a valid subpacket here or not. - */ - static parse16(octets) { - return ZmodemSubpacket._parse(octets, 2); - } - //parse32 test: - //[102, 105, 108, 101, 110, 97, 109, 101, 119, 105, 116, 104, 115, 112, 97, 99, 101, 115, 0, 49, 55, 49, 51, 49, 52, 50, 52, 51, 50, 49, 55, 50, 49, 48, 48, 54, 52, 52, 48, 49, 49, 55, 0, 43, 8, 63, 115, 23, 17] - /** - * Same as parse16(), but assuming a 32-bit CRC. - * - * @param {number[]} octets - The octet values to parse. - * Each array member should be an 8-bit unsigned integer (0-255). - * This object is mutated in the function. - * - * @returns {Subpacket|undefined} An instance of the appropriate Subpacket - * subclass, or undefined if not enough octet values are given - * to determine whether there is a valid subpacket here or not. - */ - static parse32(octets) { - return ZmodemSubpacket._parse(octets, 4); - } - /** - * Not used directly. - */ - constructor(payload) { - this._payload = payload; - } - _encode(zencoder, crc_func) { - return zencoder.encode(this._payload.slice(0)).concat( - [Zmodem2.ZMLIB.ZDLE, this._frameend_num], - zencoder.encode(crc_func(this._payload.concat(this._frameend_num))) - ); - } - //Because of ZDLE encoding, we’ll never see any of the frame-end octets - //in a stream except as the ends of data payloads. - static _parse(bytes_arr, crc_len) { - var end_at; - var creator; - var _frame_ends_lookup = { - 104: ZEndNoAckSubpacket, - 105: ZNoEndNoAckSubpacket, - 106: ZNoEndAckSubpacket, - 107: ZEndAckSubpacket - }; - var zdle_at = 0; - while (zdle_at < bytes_arr.length) { - zdle_at = bytes_arr.indexOf(Zmodem2.ZMLIB.ZDLE, zdle_at); - if (zdle_at === -1) return; - var after_zdle = bytes_arr[zdle_at + 1]; - creator = _frame_ends_lookup[after_zdle]; - if (creator) { - end_at = zdle_at + 1; - break; - } - zdle_at++; - } - if (!creator) return; - var frameend_num = bytes_arr[end_at]; - if (bytes_arr[end_at - 1] !== Zmodem2.ZMLIB.ZDLE) { - throw "Byte before frame end should be ZDLE, not " + bytes_arr[end_at - 1]; - } - var zdle_encoded_payload = bytes_arr.splice(0, end_at - 1); - var got_crc = Zmodem2.ZDLE.splice(bytes_arr, 2, crc_len); - if (!got_crc) { - bytes_arr.unshift.apply(bytes_arr, zdle_encoded_payload); - return; - } - var payload = Zmodem2.ZDLE.decode(zdle_encoded_payload); - Zmodem2.CRC[crc_len === 2 ? "verify16" : "verify32"]( - payload.concat([frameend_num]), - got_crc - ); - return new creator(payload, got_crc); - } - }; - var ZEndSubpacketBase = class extends Zmodem2.Subpacket { - frame_end() { - return true; - } - }; - var ZNoEndSubpacketBase = class extends Zmodem2.Subpacket { - frame_end() { - return false; - } - }; - var ZEndNoAckSubpacket = class extends ZEndSubpacketBase { - ack_expected() { - return false; - } - }; - ZEndNoAckSubpacket.prototype._frameend_num = ZCRCE; - var ZEndAckSubpacket = class extends ZEndSubpacketBase { - ack_expected() { - return true; - } - }; - ZEndAckSubpacket.prototype._frameend_num = ZCRCW; - var ZNoEndNoAckSubpacket = class extends ZNoEndSubpacketBase { - ack_expected() { - return false; - } - }; - ZNoEndNoAckSubpacket.prototype._frameend_num = ZCRCG; - var ZNoEndAckSubpacket = class extends ZNoEndSubpacketBase { - ack_expected() { - return true; - } - }; - ZNoEndAckSubpacket.prototype._frameend_num = ZCRCQ; - SUBPACKET_BUILDER = { - end_no_ack: ZEndNoAckSubpacket, - end_ack: ZEndAckSubpacket, - no_end_no_ack: ZNoEndNoAckSubpacket, - no_end_ack: ZNoEndAckSubpacket - }; - } -}); - -// node_modules/zmodem.js/src/zvalidation.js -var require_zvalidation = __commonJS({ - "node_modules/zmodem.js/src/zvalidation.js"(exports2, module2) { - "use strict"; - var Zmodem2 = module2.exports; - Object.assign( - Zmodem2, - require_zerror() - ); - var LOOKS_LIKE_ZMODEM_HEADER = /\*\x18[AC]|\*\*\x18B/; - function _validate_number(key, value) { - if (value < 0) { - throw new Zmodem2.Error("validation", "\u201C" + key + "\u201D (" + value + ") must be nonnegative."); - } - if (value !== Math.floor(value)) { - throw new Zmodem2.Error("validation", "\u201C" + key + "\u201D (" + value + ") must be an integer."); - } - } - Zmodem2.Validation = { - /** - * Validates and normalizes a set of parameters for an offer to send. - * NOTE: This returns “mtime” as epoch seconds, not a Date. This is - * inconsistent with the get_details() method in Session, but it’s - * more useful for sending over the wire. - * - * @param {FileDetails} params - The file details. Some fairly trivial - * variances from the specification are allowed. - * - * @return {FileDetails} The parameters that should be sent. `mtime` - * will be a Date rather than a number. - */ - offer_parameters: function offer_parameters(params) { - if (!params.name) { - throw new Zmodem2.Error("validation", "Need \u201Cname\u201D!"); - } - if (typeof params.name !== "string") { - throw new Zmodem2.Error("validation", "\u201Cname\u201D (" + params.name + ") must be a string!"); - } - params = Object.assign({}, params); - if (LOOKS_LIKE_ZMODEM_HEADER.test(params.name)) { - console.warn("The filename " + JSON.stringify(name) + " contains characters that look like a ZMODEM header. This could corrupt the ZMODEM session; consider renaming it so that the filename doesn\u2019t contain control characters."); - } - if (params.serial !== null && params.serial !== void 0) { - throw new Zmodem2.Error("validation", "\u201Cserial\u201D is meaningless."); - } - params.serial = null; - ["size", "mode", "files_remaining", "bytes_remaining"].forEach( - function(k) { - var ok; - switch (typeof params[k]) { - case "object": - ok = params[k] === null; - break; - case "undefined": - params[k] = null; - ok = true; - break; - case "number": - _validate_number(k, params[k]); - ok = true; - break; - } - if (!ok) { - throw new Zmodem2.Error("validation", "\u201C" + k + "\u201D (" + params[k] + ") must be null, undefined, or a number."); - } - } - ); - if (typeof params.mode === "number") { - params.mode |= 32768; - } - if (params.files_remaining === 0) { - throw new Zmodem2.Error("validation", "\u201Cfiles_remaining\u201D, if given, must be positive."); - } - var mtime_ok; - switch (typeof params.mtime) { - case "object": - mtime_ok = true; - if (params.mtime instanceof Date) { - var date_obj = params.mtime; - params.mtime = Math.floor(date_obj.getTime() / 1e3); - if (params.mtime < 0) { - throw new Zmodem2.Error("validation", "\u201Cmtime\u201D (" + date_obj + ") must not be earlier than 1970."); - } - } else if (params.mtime !== null) { - mtime_ok = false; - } - break; - case "undefined": - params.mtime = null; - mtime_ok = true; - break; - case "number": - _validate_number("mtime", params.mtime); - mtime_ok = true; - break; - } - if (!mtime_ok) { - throw new Zmodem2.Error("validation", "\u201Cmtime\u201D (" + params.mtime + ") must be null, undefined, a Date, or a number."); - } - return params; - } - }; - } -}); - -// node_modules/zmodem.js/src/zsession.js -var require_zsession = __commonJS({ - "node_modules/zmodem.js/src/zsession.js"(exports2, module2) { - "use strict"; - var Zmodem2 = module2.exports; - Zmodem2.DEBUG = false; - Object.assign( - Zmodem2, - require_encode(), - require_text(), - require_zdle(), - require_zmlib(), - require_zheader(), - require_zsubpacket(), - require_zvalidation(), - require_zerror() - ); - var KEEPALIVE_INTERVAL = 5e3; - var ZRINIT_FLAGS = [ - "CANFDX", - //full duplex - "CANOVIO", - //overlap I/O - //lsz has a buffer overflow bug that shows itself when: - // - // - 16-bit CRC is used, and - // - lsz receives the abort sequence while sending a file - // - //To avoid this, we just tell lsz to use 32-bit CRC - //even though there is otherwise no reason. This ensures that - //unfixed lsz versions will avoid the buffer overflow. - "CANFC32" - ]; - var FORCE_ESCAPE_CTRL_CHARS = true; - var DEFAULT_RECEIVE_INPUT_MODE = "spool_uint8array"; - var MAX_CHUNK_LENGTH = 8192; - var BS = 8; - var OVER_AND_OUT = [79, 79]; - var ABORT_SEQUENCE = Zmodem2.ZMLIB.ABORT_SEQUENCE; - var _Eventer = class { - /** - * Not called directly. - */ - constructor() { - this._on_evt = {}; - this._evt_once_index = {}; - } - _Add_event(evt_name) { - this._on_evt[evt_name] = []; - this._evt_once_index[evt_name] = []; - } - _get_evt_queue(evt_name) { - if (!this._on_evt[evt_name]) { - throw "Bad event: " + evt_name; - } - return this._on_evt[evt_name]; - } - /** - * Register a callback for a given event. - * - * @param {string} evt_name - The name of the event. - * - * @param {Function} todo - The function to execute when the event happens. - */ - on(evt_name, todo) { - var queue = this._get_evt_queue(evt_name); - queue.push(todo); - return this; - } - /** - * Unregister a callback for a given event. - * - * @param {string} evt_name - The name of the event. - * - * @param {Function} [todo] - The function to execute when the event - * happens. If not given, the last event registered for the event - * is unregistered. - */ - off(evt_name, todo) { - var queue = this._get_evt_queue(evt_name); - if (todo) { - var at = queue.indexOf(todo); - if (at === -1) { - throw "\u201C" + todo + "\u201D is not in the \u201C" + evt_name + "\u201D queue."; - } - queue.splice(at, 1); - } else { - queue.pop(); - } - return this; - } - _Happen(evt_name) { - var queue = this._get_evt_queue(evt_name); - var args = Array.apply(null, arguments); - args.shift(); - var sess = this; - queue.forEach(function(cb) { - cb.apply(sess, args); - }); - return queue.length; - } - }; - Zmodem2.Session = class ZmodemSession extends _Eventer { - /** - * Parse out a hex header from the given array. - * If there’s a ZRQINIT or ZRINIT at the beginning, - * we’ll return it. If the input isn’t a header, - * for whatever reason, we return undefined. - * - * @param {number[]} octets - The bytes to parse. - * - * @return {Session|undefined} A Session object if the beginning - * of a session was parsable in “octets”; otherwise undefined. - */ - static parse(octets) { - var hdr; - try { - hdr = Zmodem2.Header.parse_hex(octets); - } catch (e) { - return; - } - if (!hdr) return; - switch (hdr.NAME) { - case "ZRQINIT": - return new Zmodem2.Session.Receive(); - case "ZRINIT": - return new Zmodem2.Session.Send(hdr); - } - } - /** - * Sets the sender function that a Session object will use. - * - * @param {Function} sender_func - The function to call. - * It will receive an Array with the relevant octets. - * - * @return {Session} The session object (for chaining). - */ - set_sender(sender_func) { - this._sender = sender_func; - return this; - } - /** - * Whether the current Session has ended. - * - * @returns {boolean} The ended state. - */ - has_ended() { - return this._has_ended(); - } - /** - * Consumes an array of octets as ZMODEM session input. - * - * @param {number[]} octets - The input octets. - */ - consume(octets) { - this._before_consume(octets); - if (this._aborted) throw new Zmodem2.Error("already_aborted"); - if (!octets.length) return; - this._strip_and_enqueue_input(octets); - if (!this._check_for_abort_sequence(octets)) { - this._consume_first(); - } - return; - } - /** - * Whether the current Session has been `abort()`ed. - * - * @returns {boolean} The aborted state. - */ - aborted() { - return !!this._aborted; - } - /** - * Not called directly. - */ - constructor() { - super(); - this._config = {}; - this._input_buffer = []; - this._Add_event("receive"); - this._Add_event("garbage"); - this._Add_event("session_end"); - } - /** - * Returns the Session object’s role. - * - * @returns {string} One of: - * - `receive` - * - `send` - */ - get_role() { - return this.type; - } - _trim_leading_garbage_until_header() { - var garbage = Zmodem2.Header.trim_leading_garbage(this._input_buffer); - if (garbage.length) { - if (this._Happen("garbage", garbage) === 0) { - console.debug( - "Garbage: ", - String.fromCharCode.apply(String, garbage), - garbage - ); - } - } - } - _parse_and_consume_header() { - this._trim_leading_garbage_until_header(); - var new_header_and_crc = Zmodem2.Header.parse(this._input_buffer); - if (!new_header_and_crc) return; - if (Zmodem2.DEBUG) { - this._log_header("RECEIVED HEADER", new_header_and_crc[0]); - } - this._consume_header(new_header_and_crc[0]); - this._last_header_name = new_header_and_crc[0].NAME; - this._last_header_crc = new_header_and_crc[1]; - return new_header_and_crc[0]; - } - _log_header(label, header) { - console.debug(this.type, label, header.NAME, header._bytes4.join()); - } - _consume_header(new_header) { - this._on_receive(new_header); - var handler = this._next_header_handler && this._next_header_handler[new_header.NAME]; - if (!handler) { - console.error("Unhandled header!", new_header, this._next_header_handler); - throw new Zmodem2.Error("Unhandled header: " + new_header.NAME); - } - this._next_header_handler = null; - handler.call(this, new_header); - } - //TODO: strip out the abort sequence - _check_for_abort_sequence() { - var abort_at = Zmodem2.ZMLIB.find_subarray(this._input_buffer, ABORT_SEQUENCE); - if (abort_at !== -1) { - this._input_buffer.splice(0, abort_at + ABORT_SEQUENCE.length); - this._aborted = true; - this._on_session_end(); - throw new Zmodem2.Error("peer_aborted"); - } - } - _send_header(name2) { - if (!this._sender) throw "Need sender!"; - var args = Array.apply(null, arguments); - var bytes_hdr = this._create_header_bytes(args); - if (Zmodem2.DEBUG) { - this._log_header("SENDING HEADER", bytes_hdr[1]); - } - this._sender(bytes_hdr[0]); - this._last_sent_header = bytes_hdr[1]; - } - _create_header_bytes(name_and_args) { - var hdr = Zmodem2.Header.build.apply(Zmodem2.Header, name_and_args); - var formatter = this._get_header_formatter(name_and_args[0]); - return [ - hdr[formatter](this._zencoder), - hdr - ]; - } - _strip_and_enqueue_input(input) { - Zmodem2.ZMLIB.strip_ignored_bytes(input); - this._input_buffer.push.apply(this._input_buffer, input); - } - /** - * **STOP!** You probably want to `skip()` an Offer rather than - * `abort()`. See below. - * - * Abort the current session by sending the ZMODEM abort sequence. - * This function will cause the Session object to refuse to send - * any further data. - * - * Zmodem.Sentry is configured to send all output to the terminal - * after a session’s `abort()`. That could result in lots of - * ZMODEM garble being sent to the JavaScript terminal, which you - * probably don’t want. - * - * `skip()` on an Offer is better because Session will continue to - * discard data until we reach either another file or the - * sender-initiated end of the ZMODEM session. So no ZMODEM garble, - * and the session will end successfully. - * - * The behavior of `abort()` is subject to change since it’s not - * very useful as currently implemented. - */ - abort() { - this._sender( - ABORT_SEQUENCE.concat([BS, BS, BS, BS, BS]) - ); - this._aborted = true; - this._sender = function() { - throw new Zmodem2.Error("already_aborted"); - }; - this._on_session_end(); - return; - } - //---------------------------------------------------------------------- - _on_session_end() { - this._Happen("session_end"); - } - _on_receive(hdr_or_pkt) { - this._Happen("receive", hdr_or_pkt); - } - _before_consume() { - } - }; - function _trim_OO(array) { - if (0 === Zmodem2.ZMLIB.find_subarray(array, OVER_AND_OUT)) { - array.splice(0, OVER_AND_OUT.length); - } else if (array[0] === OVER_AND_OUT[OVER_AND_OUT.length - 1]) { - array.splice(0, 1); - } - return array; - } - Zmodem2.Session.Receive = class ZmodemReceiveSession extends Zmodem2.Session { - //We only get 1 file at a time, so on each consume() either - //continue state for the current file or start a new one. - /** - * Not called directly. - */ - constructor() { - super(); - this._Add_event("offer"); - this._Add_event("data_in"); - this._Add_event("file_end"); - } - /** - * Consume input bytes from the sender. - * - * @private - * @param {number[]} octets - The bytes to consume. - */ - _before_consume(octets) { - if (this._bytes_after_OO) { - throw "PROTOCOL: Session is completed!"; - } - this._bytes_being_consumed = octets; - } - /** - * Return any bytes that have been `consume()`d but - * came after the end of the ZMODEM session. - * - * @returns {number[]} The trailing bytes. - */ - get_trailing_bytes() { - if (this._aborted) return []; - if (!this._bytes_after_OO) { - throw "PROTOCOL: Session is not completed!"; - } - return this._bytes_after_OO.slice(0); - } - _has_ended() { - return this.aborted() || !!this._bytes_after_OO; - } - //Receiver always sends hex headers. - _get_header_formatter() { - return "to_hex"; - } - _parse_and_consume_subpacket() { - var parse_func; - if (this._last_header_crc === 16) { - parse_func = "parse16"; - } else { - parse_func = "parse32"; - } - var subpacket = Zmodem2.Subpacket[parse_func](this._input_buffer); - if (subpacket) { - if (Zmodem2.DEBUG) { - console.debug(this.type, "RECEIVED SUBPACKET", subpacket); - } - this._consume_data(subpacket); - if (subpacket.frame_end()) { - this._next_subpacket_handler = null; - } - } - return subpacket; - } - _consume_first() { - if (this._got_ZFIN) { - if (this._input_buffer.length < 2) return; - if (Zmodem2.ZMLIB.find_subarray(this._input_buffer, OVER_AND_OUT) === 0) { - this._bytes_after_OO = _trim_OO(this._bytes_being_consumed.slice(0)); - this._on_session_end(); - return; - } else { - throw "PROTOCOL: Only thing after ZFIN should be \u201COO\u201D (79,79), not: " + this._input_buffer.join(); - } - } - var parsed; - do { - if (this._next_subpacket_handler) { - parsed = this._parse_and_consume_subpacket(); - } else { - parsed = this._parse_and_consume_header(); - } - } while (parsed && this._input_buffer.length); - } - _consume_data(subpacket) { - this._on_receive(subpacket); - if (!this._next_subpacket_handler) { - throw "PROTOCOL: Received unexpected data packet after " + this._last_header_name + " header: " + subpacket.get_payload().join(); - } - this._next_subpacket_handler.call(this, subpacket); - } - _octets_to_string(octets) { - if (!this._textdecoder) { - this._textdecoder = new Zmodem2.Text.Decoder(); - } - return this._textdecoder.decode(new Uint8Array(octets)); - } - _consume_ZFILE_data(hdr, subpacket) { - if (this._file_info) { - throw "PROTOCOL: second ZFILE data subpacket received"; - } - var packet_payload = subpacket.get_payload(); - var nul_at = packet_payload.indexOf(0); - var fname = this._octets_to_string(packet_payload.slice(0, nul_at)); - var the_rest = this._octets_to_string(packet_payload.slice(1 + nul_at)).split(" "); - var mtime = the_rest[1] && parseInt(the_rest[1], 8) || void 0; - if (mtime) { - mtime = new Date(mtime * 1e3); - } - this._file_info = { - name: fname, - size: the_rest[0] ? parseInt(the_rest[0], 10) : null, - mtime: mtime || null, - mode: the_rest[2] && parseInt(the_rest[2], 8) || null, - serial: the_rest[3] && parseInt(the_rest[3], 10) || null, - files_remaining: the_rest[4] ? parseInt(the_rest[4], 10) : null, - bytes_remaining: the_rest[5] ? parseInt(the_rest[5], 10) : null - }; - var xfer = new Offer( - hdr.get_options(), - this._file_info, - this._accept.bind(this), - this._skip.bind(this) - ); - this._current_transfer = xfer; - } - _consume_ZDATA_data(subpacket) { - if (!this._accepted_offer) { - throw "PROTOCOL: Received data without accepting!"; - } - if (!this._offset_ok) { - console.warn("offset not ok!"); - _send_ZRPOS(); - return; - } - this._file_offset += subpacket.get_payload().length; - this._on_data_in(subpacket); - if (subpacket.ack_expected() && !subpacket.frame_end()) { - this._send_header("ZACK", Zmodem2.ENCODELIB.pack_u32_le(this._file_offset)); - } - } - _make_promise_for_between_files() { - var sess = this; - return new Promise(function(res) { - var between_files_handler = { - ZFILE: function(hdr) { - this._next_subpacket_handler = function(subpacket) { - this._next_subpacket_handler = null; - this._consume_ZFILE_data(hdr, subpacket); - this._Happen("offer", this._current_transfer); - res(this._current_transfer); - }; - }, - //We use this as a keep-alive. Maybe other - //implementations do, too? - ZSINIT: function(hdr) { - sess._next_subpacket_handler = function(spkt) { - sess._next_subpacket_handler = null; - sess._consume_ZSINIT_data(spkt); - sess._send_header("ZACK"); - sess._next_header_handler = between_files_handler; - }; - }, - ZFIN: function() { - this._consume_ZFIN(); - res(); - } - }; - sess._next_header_handler = between_files_handler; - }); - } - _consume_ZSINIT_data(spkt) { - this._attn = spkt.get_payload(); - } - /** - * Start the ZMODEM session by signaling to the sender that - * we are ready for the first file offer. - * - * @returns {Promise} A promise that resolves with an Offer object - * or, if the sender closes the session immediately without offering - * anything, nothing. - */ - start() { - if (this._started) throw "Already started!"; - this._started = true; - var ret = this._make_promise_for_between_files(); - this._send_ZRINIT(); - return ret; - } - //Returns a promise that’s fulfilled when the file - //transfer is done. - // - // That ZEOF promise return is another promise that’s - // fulfilled when we get either ZFIN or another ZFILE. - _accept(offset) { - this._accepted_offer = true; - this._file_offset = offset || 0; - var sess = this; - var ret = new Promise(function(resolve_accept) { - var last_ZDATA; - sess._next_header_handler = { - ZDATA: function on_ZDATA(hdr) { - this._consume_ZDATA(hdr); - this._next_subpacket_handler = this._consume_ZDATA_data; - this._next_header_handler = { - ZEOF: function on_ZEOF(hdr2) { - this._consume_ZEOF(hdr2); - this._next_subpacket_handler = null; - this._make_promise_for_between_files(); - resolve_accept(); - this._send_ZRINIT(); - } - }; - } - }; - }); - this._send_ZRPOS(); - return ret; - } - _skip() { - var ret = this._make_promise_for_between_files(); - if (this._accepted_offer) { - if (!this._current_transfer) return; - var bound_make_promise_for_between_files = function() { - this._accepted_offer = false; - this._next_subpacket_handler = null; - this._make_promise_for_between_files(); - }.bind(this); - Object.assign( - this._next_header_handler, - { - ZEOF: bound_make_promise_for_between_files, - ZDATA: function() { - bound_make_promise_for_between_files(); - this._next_header_handler.ZEOF = bound_make_promise_for_between_files; - }.bind(this) - } - ); - } - this._file_info = null; - this._send_header("ZSKIP"); - return ret; - } - _send_ZRINIT() { - this._send_header("ZRINIT", ZRINIT_FLAGS); - } - _consume_ZFIN() { - this._got_ZFIN = true; - this._send_header("ZFIN"); - } - _consume_ZEOF(header) { - if (this._file_offset !== header.get_offset()) { - throw "ZEOF offset mismatch; unimplemented (local: " + this._file_offset + "; ZEOF: " + header.get_offset() + ")"; - } - this._on_file_end(); - this._file_info = null; - this._current_transfer = null; - } - _consume_ZDATA(header) { - if (this._file_offset === header.get_offset()) { - this._offset_ok = true; - } else { - throw "Error correction is unimplemented."; - } - } - _send_ZRPOS() { - this._send_header("ZRPOS", this._file_offset); - } - //---------------------------------------------------------------------- - //events - _on_file_end() { - this._Happen("file_end"); - if (this._current_transfer) { - this._current_transfer._Happen("complete"); - this._current_transfer = null; - } - } - _on_data_in(subpacket) { - this._Happen("data_in", subpacket); - if (this._current_transfer) { - this._current_transfer._Happen("input", subpacket.get_payload()); - } - } - }; - Object.assign( - Zmodem2.Session.Receive.prototype, - { - type: "receive" - } - ); - var Transfer_Offer_Mixin = { - /** - * Returns the file details object. - * @returns {FileDetails} `mtime` is a Date. - */ - get_details: function get_details() { - return Object.assign({}, this._file_info); - }, - /** - * Returns a parse of the ZFILE header’s payload. - * - * @returns {Object} Members are: - * - * - `conversion` (string | undefined) - * - `management` (string | undefined) - * - `transfer` (string | undefined) - * - `sparse` (boolean) - */ - get_options: function get_options() { - return Object.assign({}, this._zfile_opts); - }, - /** - * Returns the offset based on the last transferred chunk. - * @returns {number} The file offset (i.e., number of bytes after - * the start of the file). - */ - get_offset: function get_offset() { - return this._file_offset; - } - }; - var Transfer = class { - /** - * Not called directly. - */ - constructor(file_info, offset, send_func, end_func) { - this._file_info = file_info; - this._file_offset = offset || 0; - this._send = send_func; - this._end = end_func; - } - /** - * Send a (non-terminal) piece of the file. - * - * @param { number[] | Uint8Array } array_like - The bytes to send. - */ - send(array_like) { - this._send(array_like); - this._file_offset += array_like.length; - } - /** - * Complete the file transfer. - * - * @param { number[] | Uint8Array } [array_like] - The last bytes to send. - * - * @return { Promise } Resolves when the receiver has indicated - * acceptance of the end of the file transfer. - */ - end(array_like) { - var ret = this._end(array_like || []); - if (array_like) this._file_offset += array_like.length; - return ret; - } - }; - Object.assign(Transfer.prototype, Transfer_Offer_Mixin); - var Offer = class extends _Eventer { - /** - * Not called directly. - */ - constructor(zfile_opts, file_info, accept_func, skip_func) { - super(); - this._zfile_opts = zfile_opts; - this._file_info = file_info; - this._accept_func = accept_func; - this._skip_func = skip_func; - this._Add_event("input"); - this._Add_event("complete"); - this.on("input", this._input_handler); - } - _verify_not_skipped() { - if (this._skipped) { - throw new Zmodem2.Error("Already skipped!"); - } - } - /** - * Tell the sender that you don’t want the offered file. - * - * You can send this in lieu of `accept()` or after it, e.g., - * if you find that the transfer is taking too long. Note that, - * if you `skip()` after you `accept()`, you’ll likely have to - * wait for buffers to clear out. - * - */ - skip() { - this._verify_not_skipped(); - this._skipped = true; - return this._skip_func.apply(this, arguments); - } - /** - * Tell the sender to send the offered file. - * - * @param {Object} [opts] - Can be: - * @param {string} [opts.oninput=spool_uint8array] - Can be: - * - * - `spool_uint8array`: Stores the ZMODEM - * packet payloads as Uint8Array instances. - * This makes for an easy transition to a Blob, - * which JavaScript can use to save the file to disk. - * - * - `spool_array`: Stores the ZMODEM packet payloads - * as Array instances. Each value is an octet value. - * - * - (function): A handler that receives each payload - * as it arrives. The Offer object does not store - * the payloads internally when thus configured. - * - * @return { Promise } Resolves when the file is fully received. - * If the Offer has been spooling - * the packet payloads, the promise resolves with an Array - * that contains those payloads. - */ - accept(opts) { - this._verify_not_skipped(); - if (this._accepted) { - throw new Zmodem2.Error("Already accepted!"); - } - this._accepted = true; - if (!opts) opts = {}; - this._file_offset = opts.offset || 0; - switch (opts.on_input) { - case null: - case void 0: - case "spool_array": - case DEFAULT_RECEIVE_INPUT_MODE: - this._spool = []; - break; - default: - if (typeof opts.on_input !== "function") { - throw "Invalid \u201Con_input\u201D: " + opts.on_input; - } - } - this._input_handler_mode = opts.on_input || DEFAULT_RECEIVE_INPUT_MODE; - return this._accept_func(this._file_offset).then(this._get_spool.bind(this)); - } - _input_handler(payload) { - this._file_offset += payload.length; - if (typeof this._input_handler_mode === "function") { - this._input_handler_mode(payload); - } else { - if (this._input_handler_mode === DEFAULT_RECEIVE_INPUT_MODE) { - payload = new Uint8Array(payload); - } else if (this._input_handler_mode !== "spool_array") { - throw new Zmodem2.Error("WTF?? _input_handler_mode = " + this._input_handler_mode); - } - this._spool.push(payload); - } - } - _get_spool() { - return this._spool; - } - }; - Object.assign(Offer.prototype, Transfer_Offer_Mixin); - var SENDER_BINARY_HEADER = { - ZFILE: true, - ZDATA: true - }; - Zmodem2.Session.Send = class ZmodemSendSession extends Zmodem2.Session { - /** - * Not called directly. - */ - constructor(zrinit_hdr) { - super(); - if (!zrinit_hdr) { - throw "Need first header!"; - } else if (zrinit_hdr.NAME !== "ZRINIT") { - throw "First header should be ZRINIT, not " + zrinit_hdr.NAME; - } - this._last_header_name = "ZRINIT"; - this._subpacket_encode_func = "encode16"; - this._zencoder = new Zmodem2.ZDLE(); - this._consume_ZRINIT(zrinit_hdr); - this._file_offset = 0; - var zrqinit_count = 0; - this._start_keepalive_on_set_sender = true; - } - /** - * Sets the sender function. The first time this is called, - * it will also initiate a keepalive using ZSINIT until the - * first file is sent. - * - * @param {Function} func - The function to call. - * It will receive an Array with the relevant octets. - * - * @return {Session} The session object (for chaining). - */ - set_sender(func) { - super.set_sender(func); - if (this._start_keepalive_on_set_sender) { - this._start_keepalive_on_set_sender = false; - this._start_keepalive(); - } - return this; - } - //7.3.3 .. The sender also uses hex headers when they are - //not followed by binary data subpackets. - // - //FG: … or when the header is ZSINIT? That’s what lrzsz does, anyway. - //Then it sends a single NUL byte as the payload to an end_ack subpacket. - _get_header_formatter(name2) { - return SENDER_BINARY_HEADER[name2] ? "to_binary16" : "to_hex"; - } - //In order to keep lrzsz from timing out, we send ZSINIT every 5 seconds. - //Maybe make this configurable? - _start_keepalive() { - if (!this._keepalive_promise) { - var sess = this; - this._keepalive_promise = new Promise(function(resolve) { - sess._keepalive_timeout = setTimeout(resolve, KEEPALIVE_INTERVAL); - }).then(function() { - sess._next_header_handler = { - ZACK: function() { - sess._got_ZSINIT_ZACK = true; - } - }; - sess._send_ZSINIT(); - sess._keepalive_promise = null; - sess._start_keepalive(); - }); - } - } - _stop_keepalive() { - if (this._keepalive_promise) { - clearTimeout(this._keepalive_timeout); - this._keep_alive_promise = null; - } - } - _send_ZSINIT() { - var zsinit_flags = []; - if (this._zencoder.escapes_ctrl_chars()) { - zsinit_flags.push("ESCCTL"); - } - this._send_header_and_data( - ["ZSINIT", zsinit_flags], - [0], - "end_ack" - ); - } - _consume_ZRINIT(hdr) { - this._last_ZRINIT = hdr; - if (hdr.get_buffer_size()) { - throw "Buffer size (" + hdr.get_buffer_size() + ") is unsupported!"; - } - if (!hdr.can_full_duplex()) { - throw "Half-duplex I/O is unsupported!"; - } - if (!hdr.can_overlap_io()) { - throw "Non-overlap I/O is unsupported!"; - } - if (hdr.escape_8th_bit()) { - throw "8-bit escaping is unsupported!"; - } - if (FORCE_ESCAPE_CTRL_CHARS) { - this._zencoder.set_escape_ctrl_chars(true); - if (!hdr.escape_ctrl_chars()) { - console.debug("Peer didn\u2019t request escape of all control characters. Will send ZSINIT to force recognition of escaped control characters."); - } - } else { - this._zencoder.set_escape_ctrl_chars(hdr.escape_ctrl_chars()); - } - } - //https://stackoverflow.com/questions/23155939/missing-0xf-and-0x16-when-binary-data-through-virtual-serial-port-pair-created-b - //^^ Because of that, we always escape control characters. - //The alternative would be that lrz would never receive those - //two bytes from zmodem.js. - _ensure_receiver_escapes_ctrl_chars() { - var promise; - var needs_ZSINIT = !this._last_ZRINIT.escape_ctrl_chars() && !this._got_ZSINIT_ZACK; - if (needs_ZSINIT) { - var sess = this; - promise = new Promise(function(res) { - sess._next_header_handler = { - ZACK: (hdr) => { - res(); - } - }; - sess._send_ZSINIT(); - }); - } else { - promise = Promise.resolve(); - } - return promise; - } - _convert_params_to_offer_payload_array(params) { - params = Zmodem2.Validation.offer_parameters(params); - var subpacket_payload = params.name + "\0"; - var subpacket_space_pieces = [ - (params.size || 0).toString(10), - params.mtime ? params.mtime.toString(8) : "0", - params.mode ? (32768 | params.mode).toString(8) : "0", - "0" - //serial - ]; - if (params.files_remaining) { - subpacket_space_pieces.push(params.files_remaining); - if (params.bytes_remaining) { - subpacket_space_pieces.push(params.bytes_remaining); - } - } - subpacket_payload += subpacket_space_pieces.join(" "); - return this._string_to_octets(subpacket_payload); - } - /** - * Send an offer to the receiver. - * - * @param {FileDetails} params - All about the file you want to transfer. - * - * @returns {Promise} If the receiver accepts the offer, then the - * resolution is a Transfer object; otherwise the resolution is - * undefined. - */ - send_offer(params) { - if (Zmodem2.DEBUG) { - console.debug("SENDING OFFER", params); - } - if (!params) throw "need file params!"; - if (this._sending_file) throw "Already sending file!"; - var payload_array = this._convert_params_to_offer_payload_array(params); - this._stop_keepalive(); - var sess = this; - function zrpos_handler_setter_func() { - sess._next_header_handler = { - // The receiver may send ZRPOS in at least two cases: - // - // 1) A malformed subpacket arrived, so we need to - // “rewind” a bit and continue from the receiver’s - // last-successful location in the file. - // - // 2) The receiver hasn’t gotten any data for a bit, - // so it sends ZRPOS as a “ping”. - // - // Case #1 shouldn’t happen since zmodem.js requires a - // reliable transport. Case #2, though, can happen due - // to either normal network congestion or errors in - // implementation. In either case, there’s nothing for - // us to do but to ignore the ZRPOS, with an optional - // warning. - // - ZRPOS: function(hdr) { - if (Zmodem2.DEBUG) { - console.warn("Mid-transfer ZRPOS \u2026 implementation error?"); - } - zrpos_handler_setter_func(); - } - }; - } - ; - var doer_func = function() { - var handler_setter_promise = new Promise(function(res) { - sess._next_header_handler = { - ZSKIP: function() { - sess._start_keepalive(); - res(); - }, - ZRPOS: function(hdr) { - sess._sending_file = true; - zrpos_handler_setter_func(); - res( - new Transfer( - params, - hdr.get_offset(), - sess._send_interim_file_piece.bind(sess), - sess._end_file.bind(sess) - ) - ); - } - }; - }); - sess._send_header_and_data(["ZFILE"], payload_array, "end_ack"); - delete sess._sent_ZDATA; - return handler_setter_promise; - }; - if (FORCE_ESCAPE_CTRL_CHARS) { - return this._ensure_receiver_escapes_ctrl_chars().then(doer_func); - } - return doer_func(); - } - _send_header_and_data(hdr_name_and_args, data_arr, frameend) { - var bytes_hdr = this._create_header_bytes(hdr_name_and_args); - var data_bytes = this._build_subpacket_bytes(data_arr, frameend); - bytes_hdr[0].push.apply(bytes_hdr[0], data_bytes); - if (Zmodem2.DEBUG) { - this._log_header("SENDING HEADER", bytes_hdr[1]); - console.debug(this.type, "-- HEADER PAYLOAD:", frameend, data_bytes.length); - } - this._sender(bytes_hdr[0]); - this._last_sent_header = bytes_hdr[1]; - } - _build_subpacket_bytes(bytes_arr, frameend) { - var subpacket = Zmodem2.Subpacket.build(bytes_arr, frameend); - return subpacket[this._subpacket_encode_func](this._zencoder); - } - _build_and_send_subpacket(bytes_arr, frameend) { - this._sender(this._build_subpacket_bytes(bytes_arr, frameend)); - } - _string_to_octets(string) { - if (!this._textencoder) { - this._textencoder = new Zmodem2.Text.Encoder(); - } - var uint8arr = this._textencoder.encode(string); - return Array.prototype.slice.call(uint8arr); - } - /* - Potential future support for responding to ZRPOS: - send_file_offset(offset) { - } - */ - /* - Sending logic works thus: - - ASSUME the receiver can overlap I/O (CANOVIO) - (so fail if !CANFDX || !CANOVIO) - - Sender opens the firehose … all ZCRCG (!end/!ack) - until the end, when we send a ZCRCE (end/!ack) - NB: try 8k/32k/64k chunk sizes? Looks like there’s - no need to change the packet otherwise. - */ - //TODO: Put this on a Transfer object similar to what Receive uses? - _send_interim_file_piece(bytes_obj) { - this._send_file_part(bytes_obj, "no_end_no_ack"); - return Promise.resolve(); - } - _ensure_we_are_sending() { - if (!this._sending_file) throw "Not sending a file currently!"; - } - //This resolves once we receive ZEOF. - _end_file(bytes_obj) { - this._ensure_we_are_sending(); - this._send_file_part(bytes_obj, "end_no_ack"); - var sess = this; - var ret = new Promise(function(res) { - sess._sending_file = false; - sess._prepare_to_receive_ZRINIT(res); - }); - this._send_header("ZEOF", this._file_offset); - this._file_offset = 0; - return ret; - } - //Called at the beginning of our session - //and also when we’re done sending a file. - _prepare_to_receive_ZRINIT(after_consume) { - this._next_header_handler = { - ZRINIT: function(hdr) { - this._consume_ZRINIT(hdr); - if (after_consume) after_consume(); - } - }; - } - /** - * Signal to the receiver that the ZMODEM session is wrapping up. - * - * @returns {Promise} Resolves when the receiver has responded to - * our signal that the session is over. - */ - close() { - var ok_to_close = this._last_header_name === "ZRINIT"; - if (!ok_to_close) { - ok_to_close = this._last_header_name === "ZSKIP"; - } - if (!ok_to_close) { - ok_to_close = this._last_sent_header.name === "ZSINIT" && this._last_header_name === "ZACK"; - } - if (!ok_to_close) { - throw "Can\u2019t close; last received header was \u201C" + this._last_header_name + "\u201D"; - } - var sess = this; - var ret = new Promise(function(res, rej) { - sess._next_header_handler = { - ZFIN: function() { - sess._sender(OVER_AND_OUT); - sess._sent_OO = true; - sess._on_session_end(); - res(); - } - }; - }); - this._send_header("ZFIN"); - return ret; - } - _has_ended() { - return this.aborted() || !!this._sent_OO; - } - _send_file_part(bytes_obj, final_packetend) { - if (!this._sent_ZDATA) { - this._send_header("ZDATA", this._file_offset); - this._sent_ZDATA = true; - } - var obj_offset = 0; - var bytes_count = bytes_obj.length; - while (true) { - var chunk_size = Math.min(obj_offset + MAX_CHUNK_LENGTH, bytes_count) - obj_offset; - var at_end = chunk_size + obj_offset >= bytes_count; - var chunk = bytes_obj.slice(obj_offset, obj_offset + chunk_size); - if (!(chunk instanceof Array)) { - chunk = Array.prototype.slice.call(chunk); - } - this._build_and_send_subpacket( - chunk, - at_end ? final_packetend : "no_end_no_ack" - ); - this._file_offset += chunk_size; - obj_offset += chunk_size; - if (obj_offset >= bytes_count) break; - } - } - _consume_first() { - if (!this._parse_and_consume_header()) { - if (this._input_buffer.join() === "67") { - throw "Receiver has fallen back to YMODEM."; - } - } - } - _on_session_end() { - this._stop_keepalive(); - super._on_session_end(); - } - }; - Object.assign( - Zmodem2.Session.Send.prototype, - { - type: "send" - } - ); - } -}); - -// node_modules/zmodem.js/src/zsentry.js -var require_zsentry = __commonJS({ - "node_modules/zmodem.js/src/zsentry.js"(exports2, module2) { - "use strict"; - var Zmodem2 = module2.exports; - Object.assign( - Zmodem2, - require_zmlib(), - require_zsession() - ); - var MAX_ZM_HEX_START_LENGTH = 21; - var COMMON_ZM_HEX_START = [42, 42, 24, 66, 48]; - var SENTRY_CONSTRUCTOR_REQUIRED_ARGS = [ - "to_terminal", - "on_detect", - "on_retract", - "sender" - ]; - var Detection = class { - /** - * Not called directly. - */ - constructor(session_type, accepter, denier, checker) { - this._confirmer = accepter; - this._denier = denier; - this._is_valid = checker; - this._session_type = session_type; - } - /** - * Confirm that the detected ZMODEM sequence indicates the - * start of a ZMODEM session. - * - * @return {Session} The ZMODEM Session object (i.e., either a - * Send or Receive instance). - */ - confirm() { - return this._confirmer.apply(this, arguments); - } - /** - * Tell the Sentry that the detected bytes sequence is - * **NOT** intended to be the start of a ZMODEM session. - */ - deny() { - return this._denier.apply(this, arguments); - } - /** - * Tells whether the Detection is still valid; i.e., whether - * the Sentry has `consume()`d bytes that invalidate the - * Detection. - * - * @returns {boolean} Whether the Detection is valid. - */ - is_valid() { - return this._is_valid.apply(this, arguments); - } - /** - * Gives the session’s role. - * - * @returns {string} One of: - * - `receive` - * - `send` - */ - get_session_role() { - return this._session_type; - } - }; - Zmodem2.Sentry = class ZmodemSentry { - /** - * Invoked directly. Creates a new Sentry that inspects all - * traffic before it goes to the terminal. - * - * @param {Object} options - The Sentry parameters - * - * @param {Function} options.to_terminal - Handler that sends - * traffic to the terminal object. Receives an iterable object - * (e.g., an Array) that contains octet numbers. - * - * @param {Function} options.on_detect - Handler for new - * detection events. Receives a new Detection object. - * - * @param {Function} options.on_retract - Handler for retraction - * events. Receives no input. - * - * @param {Function} options.sender - Handler that sends traffic to - * the peer. If, for example, your application uses WebSocket to talk - * to the peer, use this to send data to the WebSocket instance. - */ - constructor(options) { - if (!options) throw "Need options!"; - var sentry = this; - SENTRY_CONSTRUCTOR_REQUIRED_ARGS.forEach(function(arg) { - if (!options[arg]) { - throw "Need \u201C" + arg + "\u201D!"; - } - sentry["_" + arg] = options[arg]; - }); - this._cache = []; - } - _after_session_end() { - this._zsession = null; - } - /** - * “Consumes” a piece of input: - * - * - If there is no active or pending ZMODEM session, the text is - * all output. (This is regardless of whether we’ve got a new - * Detection.) - * - * - If there is no active ZMODEM session and the input **ends** with - * a ZRINIT or ZRQINIT, then a new Detection object is created, - * and it is passed to the “on_detect” function. - * If there was another pending Detection object, it is retracted. - * - * - If there is no active ZMODEM session and the input does NOT end - * with a ZRINIT or ZRQINIT, then any pending Detection object is - * retracted. - * - * - If there is an active ZMODEM session, the input is passed to it. - * Any non-ZMODEM data (i.e., “garbage”) parsed from the input - * is sent to output. - * If the ZMODEM session ends, any post-ZMODEM part of the input - * is sent to output. - * - * @param {number[] | ArrayBuffer} input - Octets to parse as input. - */ - consume(input) { - if (!(input instanceof Array)) { - input = Array.prototype.slice.call(new Uint8Array(input)); - } - if (this._zsession) { - var session_before_consume = this._zsession; - session_before_consume.consume(input); - if (session_before_consume.has_ended()) { - if (session_before_consume.type === "receive") { - input = session_before_consume.get_trailing_bytes(); - } else { - input = []; - } - } else return; - } - var new_session = this._parse(input); - var to_terminal = input; - if (new_session) { - let checker = function() { - return sentry._parsed_session === new_session; - }, accepter = function() { - if (!this.is_valid()) { - throw "Stale ZMODEM session!"; - } - new_session.on("garbage", sentry._to_terminal); - new_session.on( - "session_end", - sentry._after_session_end.bind(sentry) - ); - new_session.set_sender(sentry._sender); - delete sentry._parsed_session; - return sentry._zsession = new_session; - }, denier = function() { - if (!this.is_valid()) return; - }; - let replacement_detect = !!this._parsed_session; - if (replacement_detect) { - if (this._parsed_session.type === new_session.type) { - to_terminal = []; - } - this._on_retract(); - } - this._parsed_session = new_session; - var sentry = this; - ; - ; - this._on_detect(new Detection( - new_session.type, - accepter, - this._send_abort.bind(this), - checker - )); - } else { - var expired_session = this._parsed_session; - this._parsed_session = null; - if (expired_session) { - if (to_terminal.length === 1 && to_terminal[0] === 67) { - this._send_abort(); - } - this._on_retract(); - } - } - this._to_terminal(to_terminal); - } - /** - * @return {Session|null} The sentry’s current Session object, or - * null if there is none. - */ - get_confirmed_session() { - return this._zsession || null; - } - _send_abort() { - this._sender(Zmodem2.ZMLIB.ABORT_SEQUENCE); - } - /** - * Parse an input stream and decide how much of it goes to the - * terminal or to a new Session object. - * - * This will accommodate input strings that are fragmented - * across calls to this function; e.g., if you send the first - * two bytes at the end of one parse() call then send the rest - * at the beginning of the next, parse() will recognize it as - * the beginning of a ZMODEM session. - * - * In order to keep from blocking any actual useful data to the - * terminal in real-time, this will send on the initial - * ZRINIT/ZRQINIT bytes to the terminal. They’re meant to go to the - * terminal anyway, so that should be fine. - * - * @private - * - * @param {Array|Uint8Array} array_like - The input bytes. - * Each member should be a number between 0 and 255 (inclusive). - * - * @return {Array} A two-member list: - * 0) the bytes that should be printed on the terminal - * 1) the created Session object (if any) - */ - _parse(array_like) { - var cache = this._cache; - cache.push.apply(cache, array_like); - while (true) { - let common_hex_at = Zmodem2.ZMLIB.find_subarray(cache, COMMON_ZM_HEX_START); - if (-1 === common_hex_at) break; - let before_common_hex = cache.splice(0, common_hex_at); - let zsession; - try { - zsession = Zmodem2.Session.parse(cache); - } catch (err) { - } - if (!zsession) break; - if (cache.length === 1 && cache[0] === Zmodem2.ZMLIB.XON) { - cache.shift(); - } - return cache.length ? null : zsession; - } - cache.splice(MAX_ZM_HEX_START_LENGTH); - return null; - } - }; - } -}); - -// node_modules/zmodem.js/index.js -var require_zmodem = __commonJS({ - "node_modules/zmodem.js/index.js"(exports2, module2) { - "use strict"; - Object.assign( - module2.exports, - require_zsentry() - ); - } -}); - -// src/main/zmodem.ts -var zmodem_exports = {}; -__export(zmodem_exports, { - attachZmodem: () => attachZmodem, - detachZmodem: () => detachZmodem, - feedZmodem: () => feedZmodem, - isZmodemActive: () => isZmodemActive, - respondZmodem: () => respondZmodem -}); -module.exports = __toCommonJS(zmodem_exports); -var import_path = require("path"); -var import_fs = require("fs"); -var import_promises = require("fs/promises"); -var Zmodem = __toESM(require_zmodem()); - -// src/shared/ipc.ts -var Ipc = { - // ---- PTY session lifecycle ---- - // NOTE: since M2 these channels are session-generic: `id` addresses both - // local pty sessions and ssh sessions; data plane is identical. - PTY_CREATE: "pty:create", - PTY_WRITE: "pty:write", - PTY_RESIZE: "pty:resize", - PTY_KILL: "pty:kill", - /** main -> renderer broadcast: { id, data } */ - PTY_DATA: "pty:data", - /** main -> renderer broadcast: { id, exitCode } */ - PTY_EXIT: "pty:exit", - // ---- settings ---- - SETTINGS_GET: "settings:get", - SETTINGS_SET: "settings:set", - /** main -> renderer broadcast after any save */ - SETTINGS_CHANGED: "settings:changed", - // ---- fonts ---- - FONTS_LIST: "fonts:list", - // ---- layouts ---- - LAYOUTS_LIST: "layouts:list", - LAYOUTS_GET: "layouts:get", - LAYOUTS_SAVE: "layouts:save", - LAYOUTS_DELETE: "layouts:delete", - // ---- sessions (openSession unifies local pty and ssh) ---- - SESSION_OPEN: "session:open", - /** main keeps a short replay buffer per session so late subscribers catch up */ - SESSION_REPLAY: "session:replay", - // ---- ssh connections (bookmarks) ---- - CONNECTIONS_LIST: "connections:list", - CONNECTIONS_SAVE: "connections:save", - CONNECTIONS_DELETE: "connections:delete", - // ---- host key verification ---- - /** main -> renderer: needs user decision before connect proceeds */ - HOSTKEY_PROMPT: "hostkey:prompt", - HOSTKEY_RESPOND: "hostkey:respond", - // ---- sysinfo (M3) ---- - SYSINFO_START: "sysinfo:start", - SYSINFO_STOP: "sysinfo:stop", - /** main -> renderer broadcast: { id, meta } (once per session) */ - SYSINFO_META: "sysinfo:meta", - /** main -> renderer broadcast: { id, sample } (poll interval) */ - SYSINFO_SAMPLE: "sysinfo:sample", - // ---- sftp (M4) ---- - SFTP_LIST: "sftp:list", - SFTP_MKDIR: "sftp:mkdir", - SFTP_RENAME: "sftp:rename", - SFTP_DELETE: "sftp:delete", - SFTP_CHMOD: "sftp:chmod", - SFTP_CHOWN: "sftp:chown", - SFTP_UPLOAD: "sftp:upload", - SFTP_DOWNLOAD: "sftp:download", - TRANSFER_CANCEL: "transfer:cancel", - /** main -> renderer broadcast: TransferProgressEvent */ - TRANSFER_PROGRESS: "transfer:progress", - DIALOG_PICK_FILES: "dialog:pickFiles", - DIALOG_PICK_DIR: "dialog:pickDirectory", - // ---- commands + logs (M5) ---- - COMMANDS_RECORD: "commands:record", - COMMANDS_HISTORY_LIST: "commands:historyList", - COMMANDS_HISTORY_CLEAR: "commands:historyClear", - COMMANDS_LIBRARY_LIST: "commands:libraryList", - COMMANDS_LIBRARY_SAVE: "commands:librarySave", - COMMANDS_LIBRARY_DELETE: "commands:libraryDelete", - LOG_START: "log:start", - LOG_STOP: "log:stop", - LOG_LIST: "log:list", - LOG_OPEN_DIR: "log:openDir", - // ---- zmodem (M6: main-process engine, ssh sessions only) ---- - /** main -> renderer: remote ran rz (mode=send) or sz (mode=receive); renderer must ask the user */ - ZMODEM_OFFER: "zmodem:offer", - /** renderer -> main: user answered the zmodem offer */ - ZMODEM_RESPOND: "zmodem:respond", - /** main -> renderer: zmodem session finished (ok, cancelled or failed) */ - ZMODEM_DONE: "zmodem:done", - // ---- misc ---- - APP_INFO: "app:info" -}; - -// src/main/zmodem.ts -var OFFER_TIMEOUT_MS = 12e4; -var STALL_TIMEOUT_MS = 9e4; -var ABORT_BUFFER = Buffer.from(Zmodem.ZMLIB.ABORT_SEQUENCE); -var engines = /* @__PURE__ */ new Map(); -function current(sessionId) { - return engines.get(sessionId); -} -function cancelTimers(engine) { - if (engine.offerTimer) clearTimeout(engine.offerTimer); - if (engine.stallTimer) clearTimeout(engine.stallTimer); - engine.offerTimer = null; - engine.stallTimer = null; -} -function emitProgress(engine, patch) { - const evt = { - transferId: engine.transferId, - kind: engine.mode === "receive" ? "zmodem-download" : "zmodem-upload", - state: "running", - file: "", - bytes: engine.bytes, - totalBytes: engine.totalBytes, - ...patch - }; - try { - engine.deps.broadcast(Ipc.TRANSFER_PROGRESS, evt); - } catch { - } -} -function emitDone(engine, ok, message) { - if (engine.doneEmitted) return; - engine.doneEmitted = true; - const evt = { id: engine.id, ok, message }; - try { - engine.deps.broadcast(Ipc.ZMODEM_DONE, evt); - } catch { - } -} -function finalize(engine, ok, message) { - engine.active = false; - cancelTimers(engine); - if (engine.receiveStream) { - try { - engine.receiveStream.end(); - } catch { - } - engine.receiveStream = null; - } - engine.session = null; - engine.detection = null; - if (!engine.progressEmitted) { - emitProgress(engine, { state: ok ? "done" : "cancelled", file: message ?? "" }); - } - engine.progressEmitted = true; - if (ok) emitDone(engine, true); - else emitDone(engine, false, message ?? "\u4F20\u8F93\u5931\u8D25"); -} -function makeSessionEnd(engine) { - return () => finalize(engine, true); -} -function touchActivity(engine) { - if (engine.stallTimer) clearTimeout(engine.stallTimer); - const timer = setTimeout(() => { - if (engine.stallTimer === null) return; - finalize(engine, false, "\u4F20\u8F93\u8D85\u65F6"); - }, STALL_TIMEOUT_MS); - engine.stallTimer = timer; -} -function wireSession(engine) { - const session = engine.session; - if (!session) return; - const sendToPeer = (octets) => { - try { - engine.deps.writeStream(engine.id, Buffer.from(octets)); - } catch { - } - }; - session.set_sender(sendToPeer); - session.on("session_end", makeSessionEnd(engine)); - touchActivity(engine); -} -async function sendOneFile(engine, session, file) { - const xfer = await session.send_offer({ - name: file.name, - size: file.size, - mtime: new Date(file.mtimeMs), - mode: void 0 - }); - if (!xfer) return; - emitProgress(engine, { file: file.name, bytes: engine.bytes, totalBytes: engine.totalBytes }); - await new Promise((resolve, reject) => { - const rs = (0, import_fs.createReadStream)(file.path); - rs.on("data", (chunk) => { - rs.pause(); - const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk); - try { - xfer.send(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)); - } catch (err) { - rs.destroy(); - reject(err instanceof Error ? err : new Error("\u53D1\u9001\u5931\u8D25")); - return; - } - engine.bytes += buf.length; - emitProgress(engine, { file: file.name, bytes: engine.bytes, totalBytes: engine.totalBytes }); - touchActivity(engine); - rs.resume(); - }); - rs.on("end", () => { - xfer.end().then(() => resolve()).catch(reject); - }); - rs.on("error", reject); - }); -} -async function runSend(engine, paths) { - try { - const session = engine.session; - const files = await Promise.all( - paths.map(async (p) => { - const s = await (0, import_promises.stat)(p); - return { path: p, name: (0, import_path.basename)(p), size: s.size, mtimeMs: s.mtimeMs }; - }) - ); - engine.totalBytes = files.reduce((acc, f) => acc + f.size, 0); - for (const f of files) { - emitProgress(engine, { file: f.name, bytes: engine.bytes, totalBytes: engine.totalBytes }); - await sendOneFile(engine, session, f); - } - emitProgress(engine, { file: "", bytes: engine.totalBytes, totalBytes: engine.totalBytes }); - await session.close(); - } catch (err) { - finalize(engine, false, err instanceof Error ? err.message : "\u4E0A\u4F20\u5931\u8D25"); - } -} -function handleOffer(engine, offer) { - const details = offer.get_details(); - const name2 = (0, import_path.basename)(String(details.name ?? "file")); - const dest = (0, import_path.join)(engine.dir ?? ".", name2); - if (details.size) engine.totalBytes += details.size; - const stream = (0, import_fs.createWriteStream)(dest); - engine.receiveStream = stream; - emitProgress(engine, { file: name2, bytes: engine.bytes, totalBytes: engine.totalBytes }); - offer.accept({ - on_input: (payload) => { - const buf = Array.isArray(payload) ? Buffer.from(payload) : Buffer.from(payload.buffer, payload.byteOffset, payload.byteLength); - if (!stream.destroyed && !stream.closed) { - stream.write(buf); - } - engine.bytes += buf.byteLength; - emitProgress(engine, { file: name2, bytes: engine.bytes, totalBytes: engine.totalBytes }); - touchActivity(engine); - } - }).then(() => { - stream.end(() => { - if (engine.receiveStream === stream) engine.receiveStream = null; - emitProgress(engine, { file: name2, bytes: engine.bytes, totalBytes: engine.totalBytes }); - }); - }).catch((err) => { - finalize(engine, false, err instanceof Error ? err.message : "\u63A5\u6536\u5931\u8D25"); - }); -} -function attachZmodem(sessionId, deps) { - const engine = { - id: sessionId, - deps, - sentry: new Zmodem.Sentry({ - to_terminal: (octets) => { - if (engine.active) return; - try { - deps.toTerminal(sessionId, Buffer.from(octets).toString("utf8")); - } catch { - } - }, - on_detect: (detection) => { - const role = detection.get_session_role(); - engine.mode = role === "receive" ? "receive" : "send"; - engine.detection = detection; - engine.active = true; - engine.transferId = `zm-${sessionId}`; - emitProgress(engine, { file: "", bytes: 0, totalBytes: 0 }); - try { - deps.broadcast(Ipc.ZMODEM_OFFER, { id: sessionId, mode: engine.mode }); - } catch { - } - touchActivity(engine); - engine.offerTimer = setTimeout(() => { - if (engine.detection && !engine.confirmed) abortWithoutSession(engine, "\u672A\u9009\u62E9\u6587\u4EF6\uFF0C\u5DF2\u53D6\u6D88"); - }, OFFER_TIMEOUT_MS); - }, - on_retract: () => { - engine.detection = null; - engine.mode = null; - engine.active = false; - cancelTimers(engine); - }, - sender: (octets) => { - try { - deps.writeStream(sessionId, Buffer.from(octets)); - } catch { - } - } - }), - detection: null, - session: null, - active: false, - mode: null, - dir: null, - confirmed: false, - transferId: `zm-${sessionId}`, - progressEmitted: false, - doneEmitted: false, - offerTimer: null, - stallTimer: null, - receiveStream: null, - bytes: 0, - totalBytes: 0 - }; - engines.set(sessionId, engine); -} -function abortWithoutSession(engine, message) { - try { - engine.deps.writeStream(engine.id, ABORT_BUFFER); - } catch { - } - engine.active = false; - cancelTimers(engine); - if (!engine.progressEmitted) emitProgress(engine, { state: "cancelled", file: message }); - engine.progressEmitted = true; - emitDone(engine, false, message); -} -function abortSession(engine, message) { - try { - engine.session?.abort(); - } catch { - } - try { - engine.deps.writeStream(engine.id, ABORT_BUFFER); - } catch { - } - finalize(engine, false, message); -} -function feedZmodem(sessionId, data) { - const engine = current(sessionId); - if (!engine) return; - try { - engine.sentry.consume(data); - } catch (err) { - if (!engine.doneEmitted) finalize(engine, false, err instanceof Error ? err.message : "ZMODEM \u4F20\u8F93\u5F02\u5E38"); - } -} -function isZmodemActive(sessionId) { - return current(sessionId)?.active ?? false; -} -function respondZmodem(resp) { - const engine = current(resp.id); - if (!engine || engine.confirmed) return; - if (resp.cancelled) { - abortWithoutSession(engine, "\u5DF2\u53D6\u6D88"); - return; - } - const detection = engine.detection; - if (!detection || !detection.is_valid()) { - abortWithoutSession(engine, "\u4F1A\u8BDD\u5DF2\u5931\u6548"); - return; - } - engine.confirmed = true; - engine.session = detection.confirm(); - if (!engine.session) { - abortWithoutSession(engine, "\u65E0\u6CD5\u5EFA\u7ACB ZMODEM \u4F1A\u8BDD"); - return; - } - wireSession(engine); - if (engine.mode === "receive") { - if (!resp.dir) { - abortSession(engine, "\u672A\u6307\u5B9A\u4FDD\u5B58\u76EE\u5F55"); - return; - } - engine.dir = resp.dir; - const session = engine.session; - session.on("offer", (offer) => handleOffer(engine, offer)); - void session.start().catch((err) => finalize(engine, false, err instanceof Error ? err.message : "\u63A5\u6536\u5931\u8D25")); - } else { - const paths = resp.paths ?? []; - if (paths.length === 0) { - abortSession(engine, "\u672A\u9009\u62E9\u6587\u4EF6"); - return; - } - void runSend(engine, paths); - } -} -function detachZmodem(sessionId) { - const engine = current(sessionId); - if (!engine) return; - engine.active = false; - cancelTimers(engine); - if (engine.receiveStream) { - try { - engine.receiveStream.end(); - } catch { - } - engine.receiveStream = null; - } - engine.session = null; - engine.detection = null; - engines.delete(sessionId); -} -// Annotate the CommonJS export names for ESM import in node: -0 && (module.exports = { - attachZmodem, - detachZmodem, - feedZmodem, - isZmodemActive, - respondZmodem -}); -/*! Bundled license information: - -crc-32/crc32.js: - (*! crc32.js (C) 2014-present SheetJS -- http://sheetjs.com *) -*/