ssh-config
Advanced tools
Comparing version 4.2.1 to 4.3.0
{ | ||
"name": "ssh-config", | ||
"description": "SSH config parser and stringifier", | ||
"version": "4.2.1", | ||
"version": "4.3.0", | ||
"author": "Chen Yangjian (https://www.cyj.me)", | ||
@@ -12,3 +12,5 @@ "repository": { | ||
"index.js", | ||
"src" | ||
"index.d.ts", | ||
"src/*.js", | ||
"src/*.d.ts" | ||
], | ||
@@ -15,0 +17,0 @@ "devDependencies": { |
@@ -9,2 +9,3 @@ "use strict"; | ||
const child_process_1 = require("child_process"); | ||
const os_1 = __importDefault(require("os")); | ||
const RE_SPACE = /\s/; | ||
@@ -43,21 +44,32 @@ const RE_LINE_BREAK = /\r|\n/; | ||
} | ||
function capitalize(str) { | ||
if (typeof str !== 'string') | ||
return str; | ||
return str[0].toUpperCase() + str.slice(1); | ||
} | ||
function match(criteria, params) { | ||
function match(criteria, context) { | ||
const testCriterion = (key, criterion) => { | ||
switch (key.toLowerCase()) { | ||
case "all": | ||
return true; | ||
case "final": | ||
if (context.inFinalPass) { | ||
return true; | ||
} | ||
context.doFinalPass = true; | ||
return false; | ||
case "exec": | ||
const command = `function main { | ||
${criterion} | ||
} | ||
main`; | ||
return (0, child_process_1.spawnSync)(command, { shell: true }).status === 0; | ||
case "host": | ||
return (0, glob_1.default)(criterion, context.params.HostName); | ||
case "originalhost": | ||
return (0, glob_1.default)(criterion, context.params.OriginalHost); | ||
case "user": | ||
return (0, glob_1.default)(criterion, context.params.User); | ||
case "localuser": | ||
return (0, glob_1.default)(criterion, context.params.LocalUser); | ||
} | ||
}; | ||
for (const key in criteria) { | ||
const criterion = criteria[key]; | ||
const keyword = key.toLowerCase(); | ||
if (keyword === 'exec') { | ||
const command = `function main { | ||
${criterion} | ||
} | ||
main`; | ||
const { status } = (0, child_process_1.spawnSync)(command, { shell: true }); | ||
if (status != 0) | ||
return false; | ||
} | ||
else if (!(0, glob_1.default)(criterion, params[capitalize(keyword)])) { | ||
if (!testCriterion(key, criterion)) { | ||
return false; | ||
@@ -69,8 +81,16 @@ } | ||
class SSHConfig extends Array { | ||
/** | ||
* Query ssh config by host. | ||
*/ | ||
compute(params) { | ||
if (typeof params === 'string') | ||
params = { Host: params }; | ||
compute(opts) { | ||
if (typeof opts === 'string') | ||
opts = { Host: opts }; | ||
const context = { | ||
params: { | ||
Host: opts.Host, | ||
HostName: opts.Host, | ||
OriginalHost: opts.Host, | ||
User: os_1.default.userInfo().username, | ||
LocalUser: os_1.default.userInfo().username, | ||
}, | ||
inFinalPass: false, | ||
doFinalPass: false, | ||
}; | ||
const obj = {}; | ||
@@ -83,32 +103,46 @@ const setProperty = (name, value) => { | ||
else if (obj[name] == null) { | ||
if (name === "HostName") { | ||
context.params.HostName = value; | ||
} | ||
else if (name === "User") { | ||
context.params.User = value; | ||
} | ||
obj[name] = value; | ||
} | ||
}; | ||
for (const line of this) { | ||
if (line.type !== LineType.DIRECTIVE) | ||
continue; | ||
if (line.param === 'Host' && (0, glob_1.default)(line.value, params.Host)) { | ||
setProperty(line.param, line.value); | ||
for (const subline of line.config) { | ||
if (subline.type === LineType.DIRECTIVE) { | ||
setProperty(subline.param, subline.value); | ||
if (opts.User !== undefined) { | ||
setProperty("User", opts.User); | ||
} | ||
const doPass = () => { | ||
for (const line of this) { | ||
if (line.type !== LineType.DIRECTIVE) | ||
continue; | ||
if (line.param === 'Host' && (0, glob_1.default)(line.value, context.params.Host)) { | ||
setProperty(line.param, line.value); | ||
for (const subline of line.config) { | ||
if (subline.type === LineType.DIRECTIVE) { | ||
setProperty(subline.param, subline.value); | ||
} | ||
} | ||
} | ||
} | ||
else if (line.param === 'Match' && 'criteria' in line && match(line.criteria, params)) { | ||
for (const subline of line.config) { | ||
if (subline.type === LineType.DIRECTIVE) { | ||
setProperty(subline.param, subline.value); | ||
else if (line.param === 'Match' && 'criteria' in line && match(line.criteria, context)) { | ||
for (const subline of line.config) { | ||
if (subline.type === LineType.DIRECTIVE) { | ||
setProperty(subline.param, subline.value); | ||
} | ||
} | ||
} | ||
else if (line.param !== 'Host' && line.param !== 'Match') { | ||
setProperty(line.param, line.value); | ||
} | ||
} | ||
else if (line.param !== 'Host' && line.param !== 'Match') { | ||
setProperty(line.param, line.value); | ||
} | ||
}; | ||
doPass(); | ||
if (context.doFinalPass) { | ||
context.inFinalPass = true; | ||
context.params.Host = context.params.HostName; | ||
doPass(); | ||
} | ||
return obj; | ||
} | ||
/** | ||
* find section by Host / Match or function | ||
*/ | ||
find(opts) { | ||
@@ -122,5 +156,2 @@ if (typeof opts === 'function') | ||
} | ||
/** | ||
* Remove section by Host / Match or function | ||
*/ | ||
remove(opts) { | ||
@@ -144,4 +175,3 @@ let index; | ||
/** | ||
* Append new section to existing ssh config. | ||
* @param {Object} opts | ||
* Append new section to existing SSH config. | ||
*/ | ||
@@ -186,4 +216,3 @@ append(opts) { | ||
/** | ||
* Prepend new section to existing ssh config. | ||
* @param {Object} opts | ||
* Prepend new section to existing SSH config. | ||
*/ | ||
@@ -246,3 +275,3 @@ prepend(opts, beforeFirstSection = false) { | ||
/** | ||
* Parse ssh config text into structured object. | ||
* Parse SSH config text into structured object. | ||
*/ | ||
@@ -384,6 +413,23 @@ function parse(text) { | ||
const criteria = {}; | ||
for (let i = 0; i < result.value.length; i += 2) { | ||
if (typeof result.value === "string") { | ||
result.value = [result.value]; | ||
} | ||
let i = 0; | ||
while (i < result.value.length) { | ||
const keyword = result.value[i]; | ||
const value = result.value[i + 1]; | ||
criteria[keyword] = value; | ||
switch (keyword.toLowerCase()) { | ||
case "all": | ||
case "canonical": | ||
case "final": | ||
criteria[keyword] = []; | ||
i += 1; | ||
break; | ||
default: | ||
if (i + 1 >= result.value.length) { | ||
throw new Error(`Missing value for match criteria ${keyword}`); | ||
} | ||
criteria[keyword] = result.value[i + 1]; | ||
i += 2; | ||
break; | ||
} | ||
} | ||
@@ -411,3 +457,8 @@ result.criteria = criteria; | ||
// blank lines at file end | ||
config[config.length - 1].after += node.before; | ||
if (config.length === 0) { | ||
configWas[configWas.length - 1].after += node.before; | ||
} | ||
else { | ||
config[config.length - 1].after += node.before; | ||
} | ||
} | ||
@@ -422,3 +473,3 @@ else { | ||
/** | ||
* Stringify structured object into ssh config text | ||
* Stringify structured object into SSH config text. | ||
*/ | ||
@@ -428,8 +479,2 @@ function stringify(config) { | ||
function formatValue(value, quoted) { | ||
if (value && typeof value === 'object' && !Array.isArray(value)) { | ||
const result = []; | ||
for (const key in value) | ||
result.push(key, value[key]); | ||
value = result; | ||
} | ||
if (Array.isArray(value)) { | ||
@@ -436,0 +481,0 @@ return value.map(chunk => formatValue(chunk, RE_SPACE.test(chunk))).join(' '); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
30291
9
664