Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

Commit

Permalink
fix: strip control characters from user output (#3420)
Browse files Browse the repository at this point in the history
Removes control characters (e.g. char code < 32 or 127 (DEL)) from any fields printed by the CLI that could have once have been user input.

For `jsipfs dag get` it attempts to strip control characters from dag-pb and dag-cbor nodes and escapes them from everything else.

raw nodes get blurted into the terminal the same as if you'd done `jsipfs cat ...`

Also brings the output of `jsipfs dag get` more into line with go-ipfs and allows specifying which encoding to display data fields in.
  • Loading branch information
achingbrain committed Nov 25, 2020
1 parent 75dd865 commit d13b064
Show file tree
Hide file tree
Showing 36 changed files with 729 additions and 161 deletions.
16 changes: 9 additions & 7 deletions packages/ipfs-cli/src/commands/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const multibase = require('multibase')
const {
createProgressBar,
coerceMtime,
coerceMtimeNsecs
coerceMtimeNsecs,
stripControlCharacters
} = require('../utils')
const { cidToString } = require('ipfs-core-utils/src/cid')
const globSource = require('ipfs-utils/src/files/glob-source')
Expand Down Expand Up @@ -262,28 +263,29 @@ module.exports = {
let finalCid

try {
for await (const added of ipfs.addAll(source, options)) {
for await (const { cid, path } of ipfs.addAll(source, options)) {
if (silent) {
continue
}

if (quieter) {
finalCid = added.cid
finalCid = cid
continue
}

const cid = cidToString(added.cid, { base: cidBase })
let message = cid
const pathStr = stripControlCharacters(path)
const cidStr = cidToString(cid, { base: cidBase })
let message = cidStr

if (!quiet) {
// print the hash twice if we are piping from stdin
message = `added ${cid} ${file ? added.path || '' : cid}`.trim()
message = `added ${cidStr} ${file ? pathStr || '' : cidStr}`.trim()
}

log(message)
}
} catch (err) {
// Tweak the error message and add more relevant infor for the CLI
// Tweak the error message and add more relevant info for the CLI
if (err.code === 'ERR_DIR_NON_RECURSIVE') {
err.message = `'${err.path}' is a directory, use the '-r' flag to specify directories`
}
Expand Down
3 changes: 1 addition & 2 deletions packages/ipfs-cli/src/commands/cat.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict'

const parseDuration = require('parse-duration').default
const uint8ArrayToString = require('uint8arrays/to-string')

module.exports = {
command: 'cat <ipfsPath>',
Expand All @@ -27,7 +26,7 @@ module.exports = {

async handler ({ ctx: { ipfs, print }, ipfsPath, offset, length, timeout }) {
for await (const buf of ipfs.cat(ipfsPath, { offset, length, timeout })) {
print.write(uint8ArrayToString(buf))
print.write(buf)
}
}
}
51 changes: 33 additions & 18 deletions packages/ipfs-cli/src/commands/dag/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
const parseDuration = require('parse-duration').default
const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path')
const uint8ArrayToString = require('uint8arrays/to-string')
const { cidToString } = require('ipfs-core-utils/src/cid')
const {
stripControlCharacters,
makeEntriesPrintable,
escapeControlCharacters
} = require('../../utils')
const multibase = require('multibase')

module.exports = {
command: 'get <cid path>',
Expand All @@ -14,13 +21,24 @@ module.exports = {
type: 'boolean',
default: false
},
'cid-base': {
describe: 'Number base to display CIDs in.',
type: 'string',
choices: Object.keys(multibase.names)
},
'data-enc': {
describe: 'String encoding to display data in.',
type: 'string',
choices: ['base16', 'base64', 'base58btc'],
default: 'base64'
},
timeout: {
type: 'string',
coerce: parseDuration
}
},

async handler ({ ctx: { ipfs, print }, cidpath, localResolve, timeout }) {
async handler ({ ctx: { ipfs, print }, cidpath, cidBase, dataEnc, localResolve, timeout }) {
const options = {
localResolve,
timeout
Expand Down Expand Up @@ -48,24 +66,21 @@ module.exports = {

const node = result.value

// TODO we need to find* a way to pretty print objects
// * reads as 'agree in'
if (node._json) {
delete node._json.multihash
node._json.data = '0x' + uint8ArrayToString(node._json.data, 'base16')
print(JSON.stringify(node._json, null, 4))
return
}

if (node instanceof Uint8Array) {
print('0x' + uint8ArrayToString(node, 'base16'))
return
}

if (node.raw) {
print(node.raw)
if (cid.codec === 'dag-pb') {
print(JSON.stringify({
data: node.Data ? uint8ArrayToString(node.Data, dataEnc) : undefined,
links: (node.Links || []).map(link => ({
Name: stripControlCharacters(link.Name),
Size: link.Size,
Cid: { '/': cidToString(link.Hash, { base: cidBase }) }
}))
}))
} else if (cid.codec === 'raw') {
print(uint8ArrayToString(node, dataEnc))
} else if (cid.codec === 'dag-cbor') {
print(JSON.stringify(makeEntriesPrintable(node, cidBase)))
} else {
print(node)
print(escapeControlCharacters(node.toString()))
}
}
}
5 changes: 4 additions & 1 deletion packages/ipfs-cli/src/commands/dns.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
'use strict'

const parseDuration = require('parse-duration').default
const {
stripControlCharacters
} = require('../utils')

module.exports = {
command: 'dns <domain>',
Expand All @@ -25,6 +28,6 @@ module.exports = {

async handler ({ ctx: { ipfs, print }, domain, recursive, format, timeout }) {
const path = await ipfs.dns(domain, { recursive, format, timeout })
print(path)
print(stripControlCharacters(path))
}
}
9 changes: 6 additions & 3 deletions packages/ipfs-cli/src/commands/files/ls.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict'

const {
asBoolean
asBoolean,
stripControlCharacters
} = require('../../utils')
const formatMode = require('ipfs-core-utils/src/files/format-mode')
const formatMtime = require('ipfs-core-utils/src/files/format-mtime')
Expand Down Expand Up @@ -37,10 +38,12 @@ module.exports = {
timeout
}) {
const printListing = file => {
const name = stripControlCharacters(file.name)

if (long) {
print(`${formatMode(file.mode, file.type === 1)}\t${formatMtime(file.mtime)}\t${file.name}\t${file.cid.toString(cidBase)}\t${file.size}`)
print(`${formatMode(file.mode, file.type === 1)}\t${formatMtime(file.mtime)}\t${name}\t${file.cid.toString(cidBase)}\t${file.size}`)
} else {
print(file.name)
print(name)
}
}

Expand Down
5 changes: 4 additions & 1 deletion packages/ipfs-cli/src/commands/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ const toIterable = require('stream-to-it')
const { pipe } = require('it-pipe')
const { map } = require('streaming-iterables')
const parseDuration = require('parse-duration').default
const {
stripControlCharacters
} = require('../utils')

module.exports = {
command: 'get <ipfsPath>',
Expand All @@ -30,7 +33,7 @@ module.exports = {
},

async handler ({ ctx: { ipfs, print }, ipfsPath, output, force, timeout }) {
print(`Saving file(s) ${ipfsPath}`)
print(`Saving file(s) ${stripControlCharacters(ipfsPath)}`)

for await (const file of ipfs.get(ipfsPath, {
timeout
Expand Down
5 changes: 4 additions & 1 deletion packages/ipfs-cli/src/commands/key/gen.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
'use strict'

const parseDuration = require('parse-duration').default
const {
stripControlCharacters
} = require('../../utils')

module.exports = {
command: 'gen <name>',
Expand Down Expand Up @@ -31,6 +34,6 @@ module.exports = {
size,
timeout
})
print(`generated ${key.id} ${key.name}`)
print(`generated ${key.id} ${stripControlCharacters(key.name)}`)
}
}
5 changes: 4 additions & 1 deletion packages/ipfs-cli/src/commands/key/list.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
'use strict'

const parseDuration = require('parse-duration').default
const {
stripControlCharacters
} = require('../../utils')

module.exports = {
command: 'list',
Expand All @@ -18,6 +21,6 @@ module.exports = {
const keys = await ipfs.key.list({
timeout
})
keys.forEach((ki) => print(`${ki.id} ${ki.name}`))
keys.forEach((ki) => print(`${ki.id} ${stripControlCharacters(ki.name)}`))
}
}
5 changes: 4 additions & 1 deletion packages/ipfs-cli/src/commands/key/rename.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
'use strict'

const parseDuration = require('parse-duration').default
const {
stripControlCharacters
} = require('../../utils')

module.exports = {
command: 'rename <name> <newName>',
Expand All @@ -18,6 +21,6 @@ module.exports = {
const res = await ipfs.key.rename(name, newName, {
timeout
})
print(`renamed to ${res.id} ${res.now}`)
print(`renamed to ${res.id} ${stripControlCharacters(res.now)}`)
}
}
5 changes: 4 additions & 1 deletion packages/ipfs-cli/src/commands/key/rm.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
'use strict'

const parseDuration = require('parse-duration').default
const {
stripControlCharacters
} = require('../../utils')

module.exports = {
command: 'rm <name>',
Expand All @@ -18,6 +21,6 @@ module.exports = {
const key = await ipfs.key.rm(name, {
timeout
})
print(`${key.id} ${key.name}`)
print(`${key.id} ${stripControlCharacters(key.name)}`)
}
}
5 changes: 3 additions & 2 deletions packages/ipfs-cli/src/commands/ls.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const multibase = require('multibase')
const { rightpad } = require('../utils')
const { rightpad, stripControlCharacters } = require('../utils')
const { cidToString } = require('ipfs-core-utils/src/cid')
const formatMode = require('ipfs-core-utils/src/files/format-mode')
const formatMtime = require('ipfs-core-utils/src/files/format-mtime')
Expand Down Expand Up @@ -65,6 +65,7 @@ module.exports = {
}

const printLink = (mode, mtime, cid, size, name, depth = 0) => {
name = stripControlCharacters(name)
const widths = getMaxWidths(mode, mtime, cid, size, name)
// todo: fix this by resolving https://github.com/ipfs/js-ipfs-unixfs-exporter/issues/24
const padding = Math.max(depth - pathParts.length, 0)
Expand All @@ -82,7 +83,7 @@ module.exports = {
const mtime = formatMtime(link.mtime)
const cid = cidToString(link.cid, { base: cidBase })
const size = link.size ? String(link.size) : '-'
const name = link.type === 'dir' ? `${link.name || ''}/` : link.name
const name = stripControlCharacters(link.type === 'dir' ? `${link.name || ''}/` : link.name)

if (first) {
first = false
Expand Down
5 changes: 4 additions & 1 deletion packages/ipfs-cli/src/commands/name/publish.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
'use strict'

const parseDuration = require('parse-duration').default
const {
stripControlCharacters
} = require('../../utils')

module.exports = {
command: 'publish <ipfsPath>',
Expand Down Expand Up @@ -45,6 +48,6 @@ module.exports = {
ttl,
timeout
})
print(`Published to ${result.name}: ${result.value}`)
print(`Published to ${stripControlCharacters(result.name)}: ${result.value}`)
}
}
5 changes: 4 additions & 1 deletion packages/ipfs-cli/src/commands/name/pubsub/subs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
'use strict'

const parseDuration = require('parse-duration').default
const {
stripControlCharacters
} = require('../../../utils')

module.exports = {
command: 'subs',
Expand All @@ -18,6 +21,6 @@ module.exports = {
const result = await ipfs.name.pubsub.subs({
timeout
})
result.forEach(s => print(s))
result.forEach(s => print(stripControlCharacters(s)))
}
}
5 changes: 4 additions & 1 deletion packages/ipfs-cli/src/commands/object/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const multibase = require('multibase')
const { cidToString } = require('ipfs-core-utils/src/cid')
const parseDuration = require('parse-duration').default
const uint8ArrayToString = require('uint8arrays/to-string')
const {
stripControlCharacters
} = require('../../utils')

module.exports = {
command: 'get <key>',
Expand Down Expand Up @@ -52,7 +55,7 @@ module.exports = {
Size: node.Size,
Links: node.Links.map((l) => {
return {
Name: l.Name,
Name: stripControlCharacters(l.Name),
Size: l.Tsize,
Hash: cidToString(l.Hash, { base: cidBase, upgrade: false })
}
Expand Down
5 changes: 4 additions & 1 deletion packages/ipfs-cli/src/commands/object/links.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
const multibase = require('multibase')
const { cidToString } = require('ipfs-core-utils/src/cid')
const parseDuration = require('parse-duration').default
const {
stripControlCharacters
} = require('../../utils')

module.exports = {
command: 'links <key>',
Expand All @@ -26,7 +29,7 @@ module.exports = {

links.forEach((link) => {
const cidStr = cidToString(link.Hash, { base: cidBase, upgrade: false })
print(`${cidStr} ${link.Tsize} ${link.Name}`)
print(`${cidStr} ${link.Tsize} ${stripControlCharacters(link.Name)}`)
})
}
}
7 changes: 5 additions & 2 deletions packages/ipfs-cli/src/commands/pin/ls.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const multibase = require('multibase')
const all = require('it-all')
const { cidToString } = require('ipfs-core-utils/src/cid')
const parseDuration = require('parse-duration').default
const {
makeEntriesPrintable
} = require('../../utils')

module.exports = {
// bracket syntax with '...' tells yargs to optionally accept a list
Expand Down Expand Up @@ -48,8 +51,8 @@ module.exports = {
if (!quiet) {
line += ` ${res.type}`

if (res.comments) {
line += ` ${res.comments}`
if (res.metadata) {
line += ` ${JSON.stringify(makeEntriesPrintable(res.metadata))}`
}
}
print(line)
Expand Down

0 comments on commit d13b064

Please sign in to comment.