Skip to content
This repository has been archived by the owner on Oct 28, 2019. It is now read-only.

Commit

Permalink
Merge pull request #10 from oganexon/develop
Browse files Browse the repository at this point in the history
1.1.1
  • Loading branch information
SteelAlloy authored Aug 20, 2019
2 parents 91f4c63 + 5b42f80 commit ca4c352
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 25 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.1.1] - 2019-08-20

### Added
- Comment on every file.
- Error recap at the end of the process.

## [1.1.0] - 2019-08-19

### Fixed
Expand Down
39 changes: 35 additions & 4 deletions bin/cli/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,35 @@ const inquirer = require('inquirer')
const chalk = require('chalk')
const log = require('./log')
const srm = require('../../')
const { methods } = require('../../lib/methods')
const { methods, eventEmitter } = require('../../lib/methods')

function check (argv, { method, retries, force, globbing }) {
let paths = []
// Search for files if globbing is enabled
if (globbing) {
for (let i = 0; i < argv.length; i++) {
// If relative path, transform to absolute
if (!path.isAbsolute(argv[i])) {
argv[i] = path.join(process.cwd(), argv[i])
}

// If on windows, transform backslashes in forwardslashes
if (path.sep !== '/') {
argv[i] = argv[i].split(path.sep).join('/')
}

// Search for files
paths = paths.concat(glob.sync(argv[i]))
}
} else paths = argv
if (paths.length === 0) console.log(chalk.bold.yellow('No such file or directory.'))

// if there are files then continue
else {
console.log(chalk.bold.yellow('Method: ' + methods[method].name + '\n'))
if (force) remove(paths, method, retries)

// Ask for confirmation
else {
inquirer.prompt([
{
Expand All @@ -44,15 +54,36 @@ function check (argv, { method, retries, force, globbing }) {
}
}

let errorsRecord = {}

eventEmitter.on('error', (file, err) => {
errorsRecord[err] = errorsRecord[err] || []
errorsRecord[err].push(file)
})

function remove (paths, methodID, retries) {
let progress = 0
for (let i = paths.length - 1; i >= 0; i--) {
// Record time
const start = process.hrtime()
srm(paths[i], { method: methodID, maxBusyTries: retries })
.then((path) => log.info(chalk.cyan(path) + chalk.cyan.bold(` deleted in ${duration(start)}.`)))
.catch((err) => log.error(chalk.red.bold('Deletion of ') + chalk.red(paths[i]) + chalk.red.bold(` failed in ${duration(start)}:\n`) + chalk.red(err)))

srm(paths[i], { method: methodID, maxBusyTries: retries }, (err, path) => {
if (err) log.error(chalk.red.bold('Deletion of ') + chalk.red(paths[i]) + chalk.red.bold(` failed in ${duration(start)}:\n`) + chalk.red(err))
else log.info(chalk.cyan(path) + chalk.cyan.bold(` deleted in ${duration(start)}.`))
progress++
if (progress === paths.length) {
if (Object.keys(errorsRecord).length !== 0) {
log.info(chalk.cyan('Process ended with errors:\n'))
for (let err in errorsRecord) {
log(chalk.cyan.bold(err) + chalk.cyan('\n ' + errorsRecord[err].reduce((accumulator, currentValue) => `${accumulator}\n ${currentValue}`)))
}
}
}
})
}
}

// Time taken
function duration (start) {
const diff = process.hrtime(start)
return diff[0] > 0
Expand Down
21 changes: 14 additions & 7 deletions bin/cli/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@ const check = require('./check')
const table = require('./table')
const { methods } = require('../../lib/methods')

// List of valid methods IDs
const validIDs = Array.from(Object.keys(methods))

// Parse the input
class SecureRmCommand extends Command {
async run () {
const { flags, argv } = this.parse(SecureRmCommand)
check(argv, flags)
}
}

// Custom flag
flags.custom = (opts = {}, action) => {
return Parser.flags.boolean(Object.assign(
opts, {
Expand All @@ -17,18 +27,13 @@ flags.custom = (opts = {}, action) => {
}))
}

class SecureRmCommand extends Command {
async run () {
const { flags, argv } = this.parse(SecureRmCommand)
check(argv, flags)
}
}

// CLI description
SecureRmCommand.description = `CLI help:
Completely erases files by making recovery impossible.
For extra documentation, go to https://www.npmjs.com/package/secure-rm
`

// CLI flags
SecureRmCommand.flags = {
// add --version flag to show CLI version
version: flags.version({ char: 'v' }),
Expand Down Expand Up @@ -60,8 +65,10 @@ SecureRmCommand.flags = {
table: flags.custom({ char: 't', description: 'show the methods table' }, table)
}

// CLI args
SecureRmCommand.args = [{ name: 'path', required: true }]

// Multiple args allowed
SecureRmCommand.strict = false

module.exports = SecureRmCommand
2 changes: 2 additions & 0 deletions bin/cli/table.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const chalk = require('chalk')
const Table = require('tty-table')
const { methods } = require('../../lib/methods')

// Draw the methods table

const header = [
{
value: 'Id',
Expand Down
28 changes: 15 additions & 13 deletions lib/methods.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { write, eventEmitter } = require('./write')

function logError (err, file) {
// Emit event with better message error
function eventError (err, file) {
if (err) {
switch (err.code) {
case 'EMFILE':
Expand All @@ -24,6 +25,7 @@ function logError (err, file) {
}
}

// Object listing every methods
const methods = {
'randomData': {
name: 'Pseudorandom data',
Expand All @@ -37,7 +39,7 @@ Your data is overwritten with cryptographically strong pseudo-random data. (The
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand All @@ -52,7 +54,7 @@ Your data is overwritten with cryptographically strong pseudo-random data. (The
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand All @@ -67,7 +69,7 @@ Your data is overwritten with cryptographically strong pseudo-random data. (The
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand All @@ -82,7 +84,7 @@ Your data is overwritten with cryptographically strong pseudo-random data. (The
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand All @@ -102,7 +104,7 @@ Pass 3: Truncating between 25% and 75% of the file.`,
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand All @@ -120,7 +122,7 @@ Pass 2: Overwriting with random data.`,
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand All @@ -144,7 +146,7 @@ Pass 3: Overwriting with random data as well as verifying the writing of this da
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand All @@ -164,7 +166,7 @@ Pass 3: Overwriting with the complement of the 2nd pass, and verifying the writi
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand All @@ -190,7 +192,7 @@ Pass 7: Overwriting with a random data as well as review the writing of this cha
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand All @@ -210,7 +212,7 @@ Pass 3-7: Overwriting with random data.`,
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand All @@ -226,7 +228,7 @@ Pass 3-7: Overwriting with random data.`,
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand Down Expand Up @@ -256,7 +258,7 @@ Pass 32-35: Overwriting with random data.`,
.then(({ file }) => write.unlink(file))
.then(() => callback())
.catch((err) => {
logError(err, file)
eventError(err, file)
callback(err)
})
}
Expand Down
6 changes: 6 additions & 0 deletions lib/secure-rm.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@ const rimraf = require('rimraf')
const { methods, eventEmitter } = require('./methods')
const { write } = require('./write')

// List of valid methods IDs
const validIDs = Array.from(Object.keys(methods))

// Main function when secure-rm is called
function secureRm (path, options, callback) {
// Parse if callback is provided
if (callback === undefined && typeof options === 'function') {
callback = options
options = { method: 'secure' }
}
// Define method if none is provided
if (options.method == null) options.method = 'secure'

if (callback) secureRmCallback(path, options, (err, path) => callback(err, path))
else return secureRmPromise(path, options)
}

// Callback version
function secureRmCallback (path, options, callback) {
if (options.customMethod) {
rimraf(path, {
Expand All @@ -33,6 +38,7 @@ function secureRmCallback (path, options, callback) {
}
}

// Promise version
function secureRmPromise (path, options) {
return new Promise((resolve, reject) => {
if (options.customMethod) {
Expand Down
13 changes: 13 additions & 0 deletions lib/write.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ const { kMaxLength } = require('buffer')

const eventEmitter = new events.EventEmitter()

// Function to offset an array
const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]

// Object listing writing methods
const write = {
// Needed to provide file size
init: file => {
return new Promise((resolve, reject) => {
fs.stat(file, (err, stats) => {
Expand Down Expand Up @@ -65,6 +68,7 @@ const write = {
})
})
},
// Write one byte on the whole file
byte: (file, data, fileSize, passes) => {
return new Promise((resolve, reject) => {
eventEmitter.emit('info', file, `Writing 0x${data.toString(16)} `)
Expand All @@ -78,6 +82,7 @@ const write = {
})
})
},
// Write an array of bytes on the whole file
bytes: (file, dataArray, fileSize, passes) => {
return new Promise((resolve, reject) => {
eventEmitter.emit('info', file, `Writing ${dataArray.map(x => '0x' + x.toString(16))} `)
Expand All @@ -92,6 +97,8 @@ const write = {
})
})
},
// Write an array of bytes on the whole file
// And then cycle through the array
cycleBytes: (file, dataArray, fileSize, passes = 1) => {
return new Promise((resolve, reject) => {
eventEmitter.emit('info', file, `Writing ${dataArray.map(x => '0x' + x.toString(16))} `)
Expand All @@ -106,6 +113,8 @@ const write = {
})
})
},
// Write start byte on the whole file
// And then + increment until end byte
incrementByte: (file, { start, end, increment }, fileSize) => {
return new Promise((resolve, reject) => {
eventEmitter.emit('info', file, `Writing 0x${start.toString(16)} `)
Expand All @@ -132,6 +141,7 @@ const write = {
})
})
},
// Write the binary complement
complementary: (file, fileSize) => {
return new Promise((resolve, reject) => {
eventEmitter.emit('info', file, 'Reading file ')
Expand All @@ -151,6 +161,7 @@ const write = {
})
})
},
// Rename to random string
rename: (file, fileSize) => {
return new Promise((resolve, reject) => {
const newName = crypto.randomBytes(9).toString('base64').replace(/\//g, '0').replace(/\+/g, 'a')
Expand All @@ -162,6 +173,7 @@ const write = {
})
})
},
// Truncate to between 25% and 75% of the file size
truncate: (file, fileSize) => {
return new Promise((resolve, reject) => {
eventEmitter.emit('info', file, 'Truncating ')
Expand All @@ -172,6 +184,7 @@ const write = {
})
})
},
// End function: unlink the file pointer
unlink: file => {
return new Promise((resolve, reject) => {
eventEmitter.emit('unlink', file)
Expand Down
Loading

0 comments on commit ca4c352

Please sign in to comment.