mirror of
https://github.com/sorenisanerd/gotty.git
synced 2024-11-24 04:54:25 +00:00
ZModem support
This commit is contained in:
parent
5588ef2cb4
commit
b416641004
27
js/package-lock.json
generated
27
js/package-lock.json
generated
@ -372,6 +372,15 @@
|
|||||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"crc-32": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==",
|
||||||
|
"requires": {
|
||||||
|
"exit-on-epipe": "~1.0.1",
|
||||||
|
"printj": "~1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cross-spawn": {
|
"cross-spawn": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||||
@ -533,6 +542,11 @@
|
|||||||
"strip-final-newline": "^2.0.0"
|
"strip-final-newline": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"exit-on-epipe": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
|
||||||
|
},
|
||||||
"fast-json-stable-stringify": {
|
"fast-json-stable-stringify": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||||
@ -961,6 +975,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
|
||||||
"integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
|
"integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
|
||||||
},
|
},
|
||||||
|
"printj": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ=="
|
||||||
|
},
|
||||||
"process-nextick-args": {
|
"process-nextick-args": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
||||||
@ -1477,6 +1496,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"zmodem.js": {
|
||||||
|
"version": "0.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/zmodem.js/-/zmodem.js-0.1.10.tgz",
|
||||||
|
"integrity": "sha512-Z1DWngunZ/j3BmIzSJpFZVNV73iHkj89rxXX4IciJdU9ga3nZ7rJ5LkfjV/QDsKhc7bazDWTTJCLJ+iRXD82dw==",
|
||||||
|
"requires": {
|
||||||
|
"crc-32": "^1.1.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"xterm": "^4.11.0",
|
"xterm": "^4.11.0",
|
||||||
"xterm-addon-fit": "^0.5.0",
|
"xterm-addon-fit": "^0.5.0",
|
||||||
"xterm-addon-web-links": "^0.4.0",
|
"xterm-addon-web-links": "^0.4.0",
|
||||||
"xterm-addon-webgl": "^0.10.0"
|
"xterm-addon-webgl": "^0.10.0",
|
||||||
|
"zmodem.js": "^0.1.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
js/src/xterm-addon-zmodem/package.json
Normal file
5
js/src/xterm-addon-zmodem/package.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "xterm.zmodem",
|
||||||
|
"main": "zmodem.js",
|
||||||
|
"private": true
|
||||||
|
}
|
21
js/src/xterm-addon-zmodem/tsconfig.json
Normal file
21
js/src/xterm-addon-zmodem/tsconfig.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es5",
|
||||||
|
"lib": [
|
||||||
|
"es5"
|
||||||
|
],
|
||||||
|
"rootDir": ".",
|
||||||
|
"outDir": "../../../lib/addons/zmodem/",
|
||||||
|
"sourceMap": true,
|
||||||
|
"removeComments": true,
|
||||||
|
"declaration": true,
|
||||||
|
"types": [
|
||||||
|
"../../node_modules/@types/mocha"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.ts",
|
||||||
|
"../../../typings/xterm.d.ts"
|
||||||
|
]
|
||||||
|
}
|
31
js/src/xterm-addon-zmodem/typings/xterm-addon-zmodem.d.ts
vendored
Normal file
31
js/src/xterm-addon-zmodem/typings/xterm-addon-zmodem.d.ts
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import { Terminal, ITerminalAddon } from 'xterm';
|
||||||
|
|
||||||
|
declare module 'xterm-addon-zmodem' {
|
||||||
|
/**
|
||||||
|
* An xterm.js addon that enables zmodem transfers.
|
||||||
|
*/
|
||||||
|
export class ZModemAddon implements ITerminalAddon {
|
||||||
|
/**
|
||||||
|
* Creates a new zmodem addon.
|
||||||
|
* @param handler The callback when the link is called.
|
||||||
|
*/
|
||||||
|
constructor(handler?: (event: MouseEvent, uri: string) => void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates the addon
|
||||||
|
* @param terminal The terminal the addon is being loaded in.
|
||||||
|
*/
|
||||||
|
public activate(terminal: Terminal): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes the addon.
|
||||||
|
*/
|
||||||
|
public dispose(): void;
|
||||||
|
}
|
||||||
|
}
|
20
js/src/xterm-addon-zmodem/zmodem.test.ts
Normal file
20
js/src/xterm-addon-zmodem/zmodem.test.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { assert } from 'chai';
|
||||||
|
|
||||||
|
import * as zmodem from './zmodem';
|
||||||
|
|
||||||
|
class MockTerminal {}
|
||||||
|
|
||||||
|
describe('zmodem addon', () => {
|
||||||
|
describe('apply', () => {
|
||||||
|
it('should do register the `zmodemAttach` method and `zmodemBrowser` attribute', () => {
|
||||||
|
zmodem.apply(<any>MockTerminal);
|
||||||
|
assert.equal(typeof (<any>MockTerminal).prototype.zmodemAttach, 'function');
|
||||||
|
assert.equal(typeof (<any>MockTerminal).prototype.zmodemBrowser, 'object');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
95
js/src/xterm-addon-zmodem/zmodem.ts
Normal file
95
js/src/xterm-addon-zmodem/zmodem.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Terminal, ITerminalAddon } from 'xterm';
|
||||||
|
|
||||||
|
declare module 'xterm-addon-zmodem' {
|
||||||
|
export class ZModemAddon implements ITerminalAddon {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Allow xterm.js to handle ZMODEM uploads and downloads.
|
||||||
|
*
|
||||||
|
* This addon is a wrapper around zmodem.js. It adds the following to the
|
||||||
|
* Terminal class:
|
||||||
|
*
|
||||||
|
* - function `zmodemAttach(<WebSocket>, <Object>)` - creates a Zmodem.Sentry
|
||||||
|
* on the passed WebSocket object. The Object passed is optional and
|
||||||
|
* can contain:
|
||||||
|
* - noTerminalWriteOutsideSession: Suppress writes from the Sentry
|
||||||
|
* object to the Terminal while there is no active Session. This
|
||||||
|
* is necessary for compatibility with, for example, the
|
||||||
|
* `attach.js` addon.
|
||||||
|
*
|
||||||
|
* - event `zmodemDetect` - fired on Zmodem.Sentry’s `on_detect` callback.
|
||||||
|
* Passes the zmodem.js Detection object.
|
||||||
|
*
|
||||||
|
* - event `zmodemRetract` - fired on Zmodem.Sentry’s `on_retract` callback.
|
||||||
|
*
|
||||||
|
* You’ll need to provide logic to handle uploads and downloads.
|
||||||
|
* See zmodem.js’s documentation for more details.
|
||||||
|
*
|
||||||
|
* **IMPORTANT:** After you confirm() a zmodem.js Detection, if you have
|
||||||
|
* used the `attach` or `terminado` addons, you’ll need to suspend their
|
||||||
|
* operation for the duration of the ZMODEM session. (The demo does this
|
||||||
|
* via `detach()` and a re-`attach()`.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
let zmodem: any;
|
||||||
|
|
||||||
|
export interface IZmodemOptions {
|
||||||
|
noTerminalWriteOutsideSession?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function zmodemAttach(ws: WebSocket, opts: IZmodemOptions = {}): void {
|
||||||
|
const term = this;
|
||||||
|
const senderFunc = (octets: ArrayLike<number>) => ws.send(new Uint8Array(octets));
|
||||||
|
|
||||||
|
let zsentry: any;
|
||||||
|
|
||||||
|
function shouldWrite(): boolean {
|
||||||
|
return !!zsentry.get_confirmed_session() || !opts.noTerminalWriteOutsideSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
zsentry = new zmodem.Sentry({
|
||||||
|
to_terminal: (octets: ArrayLike<number>) => {
|
||||||
|
if (shouldWrite()) {
|
||||||
|
term.write(
|
||||||
|
String.fromCharCode.apply(String, octets)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sender: senderFunc,
|
||||||
|
on_retract: () => (<any>term).emit('zmodemRetract'),
|
||||||
|
on_detect: (detection: any) => (<any>term).emit('zmodemDetect', detection)
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleWSMessage(evt: MessageEvent): void {
|
||||||
|
|
||||||
|
// In testing with xterm.js’s demo the first message was
|
||||||
|
// always text even if the rest were binary. While that
|
||||||
|
// may be specific to xterm.js’s demo, ultimately we
|
||||||
|
// should reject anything that isn’t binary.
|
||||||
|
if (typeof evt.data === 'string') {
|
||||||
|
if (shouldWrite()) {
|
||||||
|
term.write(evt.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
zsentry.consume(evt.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.binaryType = 'arraybuffer';
|
||||||
|
ws.addEventListener('message', handleWSMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function apply(terminalConstructor: typeof Terminal): void {
|
||||||
|
zmodem = (typeof window === 'object') ? (<any>window).Zmodem : { Browser: null }; // Nullify browser for tests
|
||||||
|
|
||||||
|
(<any>terminalConstructor.prototype).zmodemAttach = zmodemAttach;
|
||||||
|
(<any>terminalConstructor.prototype).zmodemBrowser = zmodem.Browser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ import { Terminal, IDisposable } from "xterm";
|
|||||||
import { FitAddon } from 'xterm-addon-fit';
|
import { FitAddon } from 'xterm-addon-fit';
|
||||||
import { WebLinksAddon } from 'xterm-addon-web-links';
|
import { WebLinksAddon } from 'xterm-addon-web-links';
|
||||||
import { WebglAddon } from 'xterm-addon-webgl';
|
import { WebglAddon } from 'xterm-addon-webgl';
|
||||||
|
import { ZModemAddon } from 'xterm-addon-zmodem';
|
||||||
import { lib } from "libapps"
|
import { lib } from "libapps"
|
||||||
|
|
||||||
export class Xterm {
|
export class Xterm {
|
||||||
|
Loading…
Reference in New Issue
Block a user