Allowing user to customly setup server charset when connecting to a Telnet host

This commit is contained in:
NI
2019-09-14 15:20:50 +08:00
parent 25b595b5b6
commit 6b5c444f45
5 changed files with 153 additions and 9 deletions

View File

@@ -17,6 +17,49 @@
import Exception from "./exception.js"; import Exception from "./exception.js";
export const charsetPresets = [
"utf-8",
"ibm866",
"iso-8859-2",
"iso-8859-3",
"iso-8859-4",
"iso-8859-5",
"iso-8859-6",
"iso-8859-7",
"iso-8859-8",
"iso-8859-8i",
"iso-8859-10",
"iso-8859-13",
"iso-8859-14",
"iso-8859-15",
"iso-8859-16",
"koi8-r",
"koi8-u",
"macintosh",
"windows-874",
"windows-1250",
"windows-1251",
"windows-1252",
"windows-1253",
"windows-1254",
"windows-1255",
"windows-1256",
"windows-1257",
"windows-1258",
"x-mac-cyrillic",
"gbk",
"gb18030",
"hz-gb-2312",
"big5",
"euc-jp",
"iso-2022-jp",
"shift-jis",
"euc-kr",
"iso-2022-kr",
"utf-16be",
"utf-16le"
];
const numCharators = { const numCharators = {
"0": true, "0": true,
"1": true, "1": true,

View File

@@ -208,6 +208,24 @@ const initialFieldDef = {
return "Look like " + addr.type + " address"; return "Look like " + addr.type + " address";
} }
},
Encoding: {
name: "Encoding",
description: "The character encoding of the server",
type: "select",
value: "utf-8",
example: common.charsetPresets.join(","),
verify(d) {
for (let i in common.charsetPresets) {
if (common.charsetPresets[i] !== d) {
continue;
}
return "";
}
throw new Error('The character encoding "' + d + '" is not supported');
}
} }
}; };
@@ -288,7 +306,8 @@ class Wizard {
let self = this; let self = this;
let parsedConfig = { let parsedConfig = {
host: address.parseHostPort(configInput.host, DEFAULT_PORT) host: address.parseHostPort(configInput.host, DEFAULT_PORT),
charset: configInput.charset
}; };
return new Telnet(sender, parsedConfig, { return new Telnet(sender, parsedConfig, {
@@ -319,6 +338,7 @@ class Wizard {
configInput.host, configInput.host,
self.info, self.info,
self.controls.get("Telnet", { self.controls.get("Telnet", {
charset: parsedConfig.charset,
send(data) { send(data) {
return commandHandler.sendData(data); return commandHandler.sendData(data);
}, },
@@ -359,7 +379,14 @@ class Wizard {
self.hasStarted = true; self.hasStarted = true;
self.streams.request(COMMAND_ID, sd => { self.streams.request(COMMAND_ID, sd => {
return self.buildCommand(sd, this.config, this.session); return self.buildCommand(
sd,
{
host: this.config.host,
charset: this.config.charset ? this.config.charset : "utf-8"
},
this.session
);
}); });
return self.stepWaitForAcceptWait(); return self.stepWaitForAcceptWait();
@@ -373,13 +400,20 @@ class Wizard {
self.hasStarted = true; self.hasStarted = true;
self.streams.request(COMMAND_ID, sd => { self.streams.request(COMMAND_ID, sd => {
return self.buildCommand(sd, r, this.session); return self.buildCommand(
sd,
{
host: r.host,
charset: r.encoding
},
this.session
);
}); });
self.step.resolve(self.stepWaitForAcceptWait()); self.step.resolve(self.stepWaitForAcceptWait());
}, },
() => {}, () => {},
command.fields(initialFieldDef, [{ name: "Host" }]) command.fields(initialFieldDef, [{ name: "Host" }, { name: "Encoding" }])
); );
} }
} }
@@ -408,18 +442,39 @@ export class Command {
} }
launch(info, launcher, streams, subs, controls, history) { launch(info, launcher, streams, subs, controls, history) {
const d = launcher.split("|", 2);
if (d.length <= 0) {
throw new Exception('Given launcher "' + launcher + '" was invalid');
}
try { try {
initialFieldDef["Host"].verify(launcher); initialFieldDef["Host"].verify(d[0]);
} catch (e) { } catch (e) {
throw new Exception( throw new Exception(
'Given launcher "' + launcher + '" was invalid: ' + e 'Given launcher "' + launcher + '" was invalid: ' + e
); );
} }
let charset = "utf-8";
if (d.length > 1) {
try {
initialFieldDef["Encoding"].verify(d[1]);
charset = d[1];
} catch (e) {
throw new Exception(
'Given launcher "' + launcher + '" was invalid: ' + e
);
}
}
return this.builder( return this.builder(
info, info,
{ {
host: launcher host: d[0],
charset: charset
}, },
null, null,
streams, streams,
@@ -430,6 +485,6 @@ export class Command {
} }
launcher(config) { launcher(config) {
return config.host; return config.host + (config.charset ? "|" + config.charset : "");
} }
} }

View File

@@ -356,7 +356,6 @@ body {
display: block; display: block;
width: 100%; width: 100%;
overflow: auto; overflow: auto;
padding: 1px;
} }
.form1 > fieldset .field.horizontal { .form1 > fieldset .field.horizontal {
@@ -381,6 +380,7 @@ body {
.form1 > fieldset .field, .form1 > fieldset .field,
.form1 > fieldset .field input, .form1 > fieldset .field input,
.form1 > fieldset .field select,
.form1 > fieldset .field textarea, .form1 > fieldset .field textarea,
.form1 > fieldset .field button { .form1 > fieldset .field button {
vertical-align: middle; vertical-align: middle;
@@ -416,6 +416,7 @@ body {
} }
.form1 > fieldset .field > input, .form1 > fieldset .field > input,
.form1 > fieldset .field > select,
.form1 > fieldset .field > textarea, .form1 > fieldset .field > textarea,
.form1 > fieldset .field > button { .form1 > fieldset .field > button {
box-sizing: border-box; box-sizing: border-box;
@@ -438,6 +439,7 @@ body {
.form1 > fieldset .field > input[type="tel"], .form1 > fieldset .field > input[type="tel"],
.form1 > fieldset .field > input[type="url"], .form1 > fieldset .field > input[type="url"],
.form1 > fieldset .field > input[type="password"], .form1 > fieldset .field > input[type="password"],
.form1 > fieldset .field > select,
.form1 > fieldset .field > textarea { .form1 > fieldset .field > textarea {
width: 100%; width: 100%;
padding: 10px; padding: 10px;
@@ -481,18 +483,21 @@ body {
.form1 > fieldset .field.error > input[type="tel"], .form1 > fieldset .field.error > input[type="tel"],
.form1 > fieldset .field.error > input[type="url"], .form1 > fieldset .field.error > input[type="url"],
.form1 > fieldset .field.error > input[type="password"], .form1 > fieldset .field.error > input[type="password"],
.form1 > fieldset .field.error > select,
.form1 > fieldset .field.error > textarea { .form1 > fieldset .field.error > textarea {
background: #483535; background: #483535;
border-bottom: 2px solid #a83333; border-bottom: 2px solid #a83333;
} }
.form1 > fieldset .field > input:disabled, .form1 > fieldset .field > input:disabled,
.form1 > fieldset .field > select:disabled,
.form1 > fieldset .field > textarea:disabled, .form1 > fieldset .field > textarea:disabled,
.form1 > fieldset .field > button:disabled { .form1 > fieldset .field > button:disabled {
opacity: 0.35; opacity: 0.35;
} }
.form1 > fieldset .field > input:disabled:active, .form1 > fieldset .field > input:disabled:active,
.form1 > fieldset .field > select:disabled:active,
.form1 > fieldset .field > textarea:disabled:active, .form1 > fieldset .field > textarea:disabled:active,
.form1 > fieldset .field > button:disabled:active { .form1 > fieldset .field > button:disabled:active {
opacity: 0.5; opacity: 0.5;
@@ -516,6 +521,7 @@ body {
.form1 > fieldset .field > input[type="tel"]:focus, .form1 > fieldset .field > input[type="tel"]:focus,
.form1 > fieldset .field > input[type="url"]:focus, .form1 > fieldset .field > input[type="url"]:focus,
.form1 > fieldset .field > input[type="password"]:focus, .form1 > fieldset .field > input[type="password"]:focus,
.form1 > fieldset .field > select:focus,
.form1 > fieldset .field > textarea:focus { .form1 > fieldset .field > textarea:focus {
background: #222; background: #222;
border-bottom: 2px solid #e9a; border-bottom: 2px solid #e9a;

View File

@@ -316,6 +316,23 @@ class Control {
this.colorM = color; this.colorM = color;
this.colors = this.colorM.get(); this.colors = this.colorM.get();
if (!data.charset || data.charset === "utf-8") {
this.charsetDecoder = d => {
return d;
};
} else {
let dec = new TextDecoder(data.charset),
enc = new TextEncoder();
this.charsetDecoder = d => {
return enc.encode(
dec.decode(d, {
stream: true
})
);
};
}
this.sender = data.send; this.sender = data.send;
this.closer = data.close; this.closer = data.close;
this.closed = false; this.closed = false;
@@ -332,7 +349,7 @@ class Control {
this.parser = new Parser( this.parser = new Parser(
this.sender, this.sender,
d => { d => {
self.subs.resolve(d); self.subs.resolve(this.charsetDecoder(d));
}, },
{ {
setEcho(newVal) { setEcho(newVal) {

View File

@@ -153,6 +153,8 @@
autocomplete="off" autocomplete="off"
:name="field.field.name" :name="field.field.name"
:value="option" :value="option"
:checked="field.field.value === option"
:aria-checked="field.field.value === option"
@input="verify(key, field, false)" @input="verify(key, field, false)"
@change="verify(key, field, true)" @change="verify(key, field, true)"
/> />
@@ -160,6 +162,27 @@
</label> </label>
</div> </div>
<div v-if="field.field.type === 'select'" class="field">
<select
v-model="field.field.value"
autocomplete="off"
:name="field.field.name"
:value="field.field.value"
@input="verify(key, field, false)"
@change="verify(key, field, true)"
>
<option
v-for="(option, oKey) in field.field.example.split(',')"
:key="oKey"
:value="option"
:selected="field.field.value === option"
:aria-selected="field.field.value === option"
>
{{ option }}
</option>
</select>
</div>
<div v-if="field.error.length > 0" class="error">{{ field.error }}</div> <div v-if="field.error.length > 0" class="error">{{ field.error }}</div>
<div v-else-if="field.message.length > 0" class="message"> <div v-else-if="field.message.length > 0" class="message">
{{ field.message }} {{ field.message }}