Add charset support for SSH as well

This commit is contained in:
NI
2019-10-02 22:30:14 +08:00
parent 81a9424066
commit e77ad353f0
2 changed files with 91 additions and 11 deletions

View File

@@ -289,6 +289,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');
}
},
Notice: { Notice: {
name: "Notice", name: "Notice",
description: "", description: "",
@@ -535,6 +553,7 @@ class Wizard {
let config = { let config = {
user: common.strToUint8Array(configInput.user), user: common.strToUint8Array(configInput.user),
auth: getAuthMethodFromStr(configInput.authentication), auth: getAuthMethodFromStr(configInput.authentication),
charset: configInput.charset,
credential: sessionData.credential, credential: sessionData.credential,
host: address.parseHostPort(configInput.host, DEFAULT_PORT), host: address.parseHostPort(configInput.host, DEFAULT_PORT),
fingerprint: configInput.fingerprint fingerprint: configInput.fingerprint
@@ -585,6 +604,7 @@ class Wizard {
configInput.user + "@" + configInput.host, configInput.user + "@" + configInput.host,
self.info, self.info,
self.controls.get("SSH", { self.controls.get("SSH", {
charset: configInput.charset,
send(data) { send(data) {
return commandHandler.sendData(data); return commandHandler.sendData(data);
}, },
@@ -659,7 +679,17 @@ 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,
{
user: this.config.user,
authentication: this.config.authentication,
host: this.config.host,
charset: this.config.charset ? this.config.charset : "utf-8",
fingerprint: this.config.fingerprint
},
this.session
);
}); });
return self.stepWaitForAcceptWait(); return self.stepWaitForAcceptWait();
@@ -679,6 +709,7 @@ class Wizard {
user: r.user, user: r.user,
authentication: r.authentication, authentication: r.authentication,
host: r.host, host: r.host,
charset: r.encoding,
fingerprint: "" fingerprint: ""
}, },
this.session this.session
@@ -692,6 +723,7 @@ class Wizard {
{ name: "User" }, { name: "User" },
{ name: "Host" }, { name: "Host" },
{ name: "Authentication" }, { name: "Authentication" },
{ name: "Encoding" },
{ name: "Notice" } { name: "Notice" }
]) ])
); );
@@ -828,20 +860,28 @@ export class Command {
} }
launch(info, launcher, streams, subs, controls, history) { launch(info, launcher, streams, subs, controls, history) {
let matchResult = launcher.match(new RegExp("^(.*)\\@(.*)\\|(.*)$")); const d = launcher.split("|", 3);
if (!matchResult || matchResult.length !== 4) { if (d.length < 2) {
throw new Exception('Given launcher "' + launcher + '" was invalid');
}
const userHostName = d[0].match(new RegExp("^(.*)\\@(.*)$"));
if (!userHostName || userHostName.length !== 3) {
throw new Exception('Given launcher "' + launcher + '" was malformed'); throw new Exception('Given launcher "' + launcher + '" was malformed');
} }
let user = matchResult[1], let user = userHostName[1],
host = matchResult[2], host = userHostName[2],
auth = matchResult[3]; auth = d[1],
charset = d.length >= 3 && d[2] ? d[2] : "utf-8"; // RM after depreciation
try { try {
initialFieldDef["User"].verify(user); initialFieldDef["User"].verify(user);
initialFieldDef["Host"].verify(host); initialFieldDef["Host"].verify(host);
initialFieldDef["Authentication"].verify(auth); initialFieldDef["Authentication"].verify(auth);
initialFieldDef["Encoding"].verify(charset);
} catch (e) { } catch (e) {
throw new Exception( throw new Exception(
'Given launcher "' + launcher + '" was malformed ' + e 'Given launcher "' + launcher + '" was malformed ' + e
@@ -853,7 +893,8 @@ export class Command {
{ {
user: user, user: user,
host: host, host: host,
authentication: auth authentication: auth,
charset: charset
}, },
null, null,
streams, streams,
@@ -864,6 +905,14 @@ export class Command {
} }
launcher(config) { launcher(config) {
return config.user + "@" + config.host + "|" + config.authentication; return (
config.user +
"@" +
config.host +
"|" +
config.authentication +
"|" +
(config.charset ? config.charset : "utf-8")
);
} }
} }

View File

@@ -15,6 +15,8 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import * as iconv from "iconv-lite";
import * as subscribe from "../stream/subscribe.js"; import * as subscribe from "../stream/subscribe.js";
import * as reader from "../stream/reader.js"; import * as reader from "../stream/reader.js";
import * as color from "../commands/color.js"; import * as color from "../commands/color.js";
@@ -24,6 +26,35 @@ class Control {
this.colorM = color; this.colorM = color;
this.colors = this.colorM.get(); this.colors = this.colorM.get();
this.charset = data.charset;
if (this.charset === "utf-8") {
let enc = new TextEncoder();
this.charsetDecoder = d => {
return d;
};
this.charsetEncoder = dStr => {
return enc.encode(dStr);
};
} else {
let dec = new TextDecoder(this.charset),
enc = new TextEncoder();
this.charsetDecoder = d => {
return enc.encode(
dec.decode(d, {
stream: true
})
);
};
this.charsetEncoder = dStr => {
return iconv.encode(dStr, this.charset);
};
}
this.enable = false; this.enable = false;
this.sender = data.send; this.sender = data.send;
this.closer = data.close; this.closer = data.close;
@@ -34,7 +65,7 @@ class Control {
data.events.place("stdout", async rd => { data.events.place("stdout", async rd => {
try { try {
self.subs.resolve(await reader.readCompletely(rd)); self.subs.resolve(self.charsetDecoder(await reader.readCompletely(rd)));
} catch (e) { } catch (e) {
// Do nothing // Do nothing
} }
@@ -42,7 +73,7 @@ class Control {
data.events.place("stderr", async rd => { data.events.place("stderr", async rd => {
try { try {
self.subs.resolve(await reader.readCompletely(rd)); self.subs.resolve(self.charsetDecoder(await reader.readCompletely(rd)));
} catch (e) { } catch (e) {
// Do nothing // Do nothing
} }
@@ -91,7 +122,7 @@ class Control {
return; return;
} }
return this.sender(new TextEncoder().encode(data)); return this.sender(this.charsetEncoder(data));
} }
color() { color() {