From 00eda04f439727f478da38a3b58f856ed79a1989 Mon Sep 17 00:00:00 2001 From: "sbs20@omicron.sbs20.com" Date: Sun, 13 Sep 2020 21:52:13 +0100 Subject: [PATCH 1/5] Build bump --- package-lock.json | 586 +--------------------------------------------- package.json | 25 +- 2 files changed, 32 insertions(+), 579 deletions(-) diff --git a/package-lock.json b/package-lock.json index a4dc23c4..0534437f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "scanservjs", - "version": "2.0.0", + "version": "2.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4086,6 +4086,13 @@ "upath": "^1.1.1" }, "dependencies": { + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -7578,552 +7585,11 @@ "dev": true }, "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "dev": true, - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } - } + "optional": true }, "function-bind": { "version": "1.1.1", @@ -11101,13 +10567,6 @@ "path-exists": "^4.0.0" } }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -11493,13 +10952,6 @@ "thenify-all": "^1.0.0" } }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -11780,13 +11232,6 @@ "to-regex-range": "^5.0.1" } }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -16105,13 +15550,6 @@ "to-regex-range": "^5.0.1" } }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", diff --git a/package.json b/package.json index af2b42bd..a1ca1397 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "scanservjs", - "version": "2.0.1", + "version": "2.0.2", "description": "scanservjs is a simple web-based UI for SANE which allows you to share a scanner on a network without the need for drivers or complicated installation. scanserv does not do image conversion or manipulation (beyond the bare minimum necessary for the purposes of browser preview) or OCR.", "scripts": { "serve": "nodemon --exec 'vue-cli-service serve'", @@ -67,16 +67,31 @@ "brace-style": 1, "comma-spacing": 1, "eqeqeq": 1, - "indent": ["error", 2, { "SwitchCase": 1 }], + "indent": [ + "error", + 2, + { + "SwitchCase": 1 + } + ], "keyword-spacing": 1, "no-mixed-spaces-and-tabs": 1, "no-undef": 1, "no-unused-vars": 1, "no-var": 1, - "object-shorthand": [1, "methods"], + "object-shorthand": [ + 1, + "methods" + ], "prefer-arrow-callback": 1, - "quotes": ["error", "single"], - "semi": ["error", "always"], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ], "space-before-blocks": 1, "space-infix-ops": 1 } From c3a724e45d9967a8f4dc20a32782555ee5e300da Mon Sep 17 00:00:00 2001 From: "sbs20@omicron.sbs20.com" Date: Sun, 13 Sep 2020 22:17:34 +0100 Subject: [PATCH 2/5] Disallow delete outside of data #43 --- server/Api.js | 5 +++++ server/FileInfo.js | 4 ++++ test/fileinfo.test.js | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/server/Api.js b/server/Api.js index 3ac0be3c..34c78d23 100644 --- a/server/Api.js +++ b/server/Api.js @@ -31,6 +31,11 @@ class Api { static fileDelete(fullpath) { const file = new FileInfo(fullpath); + const parent = new FileInfo(file.path); + const data = new FileInfo(Config.outputDirectory); + if (!parent.equals(data)) { + throw new Error('Cannot delete outside of data directory'); + } return file.delete(); } diff --git a/server/FileInfo.js b/server/FileInfo.js index 68177863..de90171b 100644 --- a/server/FileInfo.js +++ b/server/FileInfo.js @@ -36,6 +36,10 @@ class FileInfo { return this; } + equals(fileinfo) { + return path.resolve(this.fullname) === path.resolve(fileinfo.fullname); + } + exists() { return fs.existsSync(this.fullname); } diff --git a/test/fileinfo.test.js b/test/fileinfo.test.js index 3d159a51..0e9e6624 100644 --- a/test/fileinfo.test.js +++ b/test/fileinfo.test.js @@ -13,4 +13,13 @@ describe('FileInfo', () => { assert.throws(() => new FileInfo('../package.json'), Error, '../package.json'); assert.throws(() => new FileInfo('/usr/bin/ls'), Error, '/usr/bin/ls'); }); + it('Check file path variations', () => { + const dir1 = new FileInfo('./test/resource'); + const dir2 = new FileInfo('test/resource'); + assert.strictEqual(dir1.equals(dir2), true); + + const file1 = new FileInfo('./test/resource/logo.png'); + const file2 = new FileInfo('test/resource/logo.png'); + assert.strictEqual(file1.equals(file2), true); + }); }); \ No newline at end of file From acb464d99bc11a0c3066f14e97979a20cbb83a45 Mon Sep 17 00:00:00 2001 From: "sbs20@omicron.sbs20.com" Date: Sun, 13 Sep 2020 22:46:59 +0100 Subject: [PATCH 3/5] Device unit tests --- server/Device.js | 9 ++++ test/device.test.js | 31 ++++++++++++ test/fileinfo.test.js | 2 + test/resource/scanimage-a1.txt | 88 ++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 test/device.test.js create mode 100644 test/resource/scanimage-a1.txt diff --git a/server/Device.js b/server/Device.js index 0e758e91..678ee776 100644 --- a/server/Device.js +++ b/server/Device.js @@ -23,6 +23,15 @@ const decorate = (device) => { feature.options = ['50', '75', '100', '150', '200', '300', '600', '1200']; if (feature.parameters.indexOf('|') > -1) { feature.options = feature.parameters.split('|'); + } else if (feature.parameters.indexOf('..') > -1) { + params = feature.parameters.replace(/[a-z]/ig, '').split('..'); + feature.options = []; + for (let value = Number(params[1]); value > Number(params[0]); value /= 2) { + feature.options.push(value); + } + feature.options.push(Number(params[0])); + feature.options.sort((a, b) => a - b); + feature.options = feature.options.map(n => n.toString()); } break; diff --git a/test/device.test.js b/test/device.test.js new file mode 100644 index 00000000..65e48d9c --- /dev/null +++ b/test/device.test.js @@ -0,0 +1,31 @@ +/* eslint-env mocha */ +const assert = require('assert'); +const Device = require('../server/Device'); +const FileInfo = require('../server/FileInfo'); + +describe('Device', () => { + it('scanimage-a1.txt', () => { + const file = new FileInfo('test/resource/scanimage-a1.txt'); + const device = Device.from(file.toText()); + + assert.deepStrictEqual(device.features['--mode'].options, ['Lineart', 'Gray', 'Color']); + assert.strictEqual(device.features['--mode'].default, 'Color'); + assert.deepStrictEqual(device.features['--resolution'].options, ['50', '75', '150', '300', '600', '1200']); + assert.strictEqual(device.features['--resolution'].default, '50'); + assert.strictEqual(device.features['-l'].limits[0], 0); + assert.strictEqual(device.features['-l'].limits[1], 215); + assert.strictEqual(device.features['-t'].limits[0], 0); + assert.strictEqual(device.features['-t'].limits[1], 297); + assert.strictEqual(device.features['-x'].limits[0], 0); + assert.strictEqual(device.features['-x'].limits[1], 215); + assert.strictEqual(device.features['-y'].limits[0], 0); + assert.strictEqual(device.features['-y'].limits[1], 297); + assert.strictEqual(device.features['--brightness'].limits[0], -100); + assert.strictEqual(device.features['--brightness'].limits[1], 100); + assert.strictEqual(device.features['--brightness'].interval, 1); + assert.strictEqual(device.features['--contrast'].limits[0], -100); + assert.strictEqual(device.features['--contrast'].limits[1], 100); + assert.strictEqual(device.features['--contrast'].interval, 1); + }); + +}); \ No newline at end of file diff --git a/test/fileinfo.test.js b/test/fileinfo.test.js index 0e9e6624..e464650c 100644 --- a/test/fileinfo.test.js +++ b/test/fileinfo.test.js @@ -9,10 +9,12 @@ describe('FileInfo', () => { assert.strictEqual(file.size > 0, true); assert.strictEqual(file.toText().indexOf('scanservjs is a simple web-based UI') > 0, true); }); + it('Security', () => { assert.throws(() => new FileInfo('../package.json'), Error, '../package.json'); assert.throws(() => new FileInfo('/usr/bin/ls'), Error, '/usr/bin/ls'); }); + it('Check file path variations', () => { const dir1 = new FileInfo('./test/resource'); const dir2 = new FileInfo('test/resource'); diff --git a/test/resource/scanimage-a1.txt b/test/resource/scanimage-a1.txt new file mode 100644 index 00000000..ec4a7271 --- /dev/null +++ b/test/resource/scanimage-a1.txt @@ -0,0 +1,88 @@ + +All options specific to device `plustek:libusb:001:008': + Scan Mode: + --mode Lineart|Gray|Color [Color] + Selects the scan mode (e.g., lineart, monochrome, or color). + --depth 8|16bit [8] + Number of bits per sample, typical values are 1 for "line-art" and 8 + for multibit scans. + --source Normal|Transparency|Negative [inactive] + Selects the scan source (such as a document-feeder). + --resolution 50..1200dpi [50] + Sets the resolution of the scanned image. + --preview[=(yes|no)] [no] + Request a preview-quality scan. + Geometry: + -l 0..215mm [0] + Top-left x position of scan area. + -t 0..297mm [0] + Top-left y position of scan area. + -x 0..215mm [103] + Width of scan-area. + -y 0..297mm [76.21] + Height of scan-area. + Enhancement: + --brightness -100..100% (in steps of 1) [0] + Controls the brightness of the acquired image. + --contrast -100..100% (in steps of 1) [0] + Controls the contrast of the acquired image. + --custom-gamma[=(yes|no)] [no] + Determines whether a builtin or a custom gamma-table should be used. + --gamma-table 0..255,... [inactive] + Gamma-correction table. In color mode this option equally affects the + red, green, and blue channels simultaneously (i.e., it is an intensity + gamma table). + --red-gamma-table 0..255,... [inactive] + Gamma-correction table for the red band. + --green-gamma-table 0..255,... [inactive] + Gamma-correction table for the green band. + --blue-gamma-table 0..255,... [inactive] + Gamma-correction table for the blue band. + Device-Settings: + --lamp-switch[=(yes|no)] [no] + Manually switching the lamp(s). + --lampoff-time 0..999 (in steps of 1) [300] + Lampoff-time in seconds. + --lamp-off-at-exit[=(yes|no)] [yes] + Turn off lamp when program exits + --warmup-time -1..999 (in steps of 1) [inactive] + Warmup-time in seconds. + --lamp-off-during-dcal[=(yes|no)] [inactive] + Always switches lamp off when doing dark calibration. + --calibration-cache[=(yes|no)] [no] + Enables or disables calibration data cache. + --speedup-switch[=(yes|no)] [inactive] + Enables or disables speeding up sensor movement. + --calibrate [inactive] + Performs calibration + Analog frontend: + --red-gain -1..63 (in steps of 1) [-1] + Red gain value of the AFE + --green-gain -1..63 (in steps of 1) [-1] + Green gain value of the AFE + --blue-gain -1..63 (in steps of 1) [-1] + Blue gain value of the AFE + --red-offset -1..63 (in steps of 1) [-1] + Red offset value of the AFE + --green-offset -1..63 (in steps of 1) [-1] + Green offset value of the AFE + --blue-offset -1..63 (in steps of 1) [-1] + Blue offset value of the AFE + --redlamp-off -1..16363 (in steps of 1) [-1] + Defines red lamp off parameter + --greenlamp-off -1..16363 (in steps of 1) [-1] + Defines green lamp off parameter + --bluelamp-off -1..16363 (in steps of 1) [-1] + Defines blue lamp off parameter + Buttons: + --button 0[=(yes|no)] [no] [hardware] + This option reflects the status of the scanner buttons. + --button 1[=(yes|no)] [no] [hardware] + This option reflects the status of the scanner buttons. + --button 2[=(yes|no)] [no] [hardware] + This option reflects the status of the scanner buttons. + --button 3[=(yes|no)] [inactive] + This option reflects the status of the scanner buttons. + --button 4[=(yes|no)] [inactive] + This option reflects the status of the scanner buttons. + From 38b8f6f79cb15fdcd76de20a3f5bae2e21d084ca Mon Sep 17 00:00:00 2001 From: "sbs20@omicron.sbs20.com" Date: Sun, 13 Sep 2020 22:59:37 +0100 Subject: [PATCH 4/5] Inactive features #61 --- server/Device.js | 16 ++++---- test/device.test.js | 23 ++++++++++- test/resource/scanimage-a2.txt | 71 ++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 test/resource/scanimage-a2.txt diff --git a/server/Device.js b/server/Device.js index 678ee776..833e7b44 100644 --- a/server/Device.js +++ b/server/Device.js @@ -22,7 +22,7 @@ const decorate = (device) => { case '--resolution': feature.options = ['50', '75', '100', '150', '200', '300', '600', '1200']; if (feature.parameters.indexOf('|') > -1) { - feature.options = feature.parameters.split('|'); + feature.options = feature.parameters.replace(/[a-z]/ig, '').split('|'); } else if (feature.parameters.indexOf('..') > -1) { params = feature.parameters.replace(/[a-z]/ig, '').split('..'); feature.options = []; @@ -40,8 +40,8 @@ const decorate = (device) => { case '-x': case '-y': params = feature.parameters.replace(/[a-z]/ig, '').split('..'); - feature.limits = [Number(params[0]), Number(params[1])]; - feature.default = Number(feature.default); + feature.limits = [Math.floor(Number(params[0])), Math.floor(Number(params[1]))]; + feature.default = Math.floor(Number(feature.default)); break; case '--brightness': @@ -75,10 +75,12 @@ const parse = (response) => { let pattern = /\s+([-]{1,2}[-a-zA-Z0-9]+) ?(.*) \[(.*)\]\n/g; let match; while ((match = pattern.exec(response)) !== null) { - device.features[match[1]] = { - 'default': match[3], - 'parameters': match[2] - }; + if (match[3] !== 'inactive') { + device.features[match[1]] = { + 'default': match[3], + 'parameters': match[2] + }; + } } pattern = /All options specific to device `(.*)'/; diff --git a/test/device.test.js b/test/device.test.js index 65e48d9c..3aa652b3 100644 --- a/test/device.test.js +++ b/test/device.test.js @@ -22,10 +22,29 @@ describe('Device', () => { assert.strictEqual(device.features['-y'].limits[1], 297); assert.strictEqual(device.features['--brightness'].limits[0], -100); assert.strictEqual(device.features['--brightness'].limits[1], 100); - assert.strictEqual(device.features['--brightness'].interval, 1); + //assert.strictEqual(device.features['--brightness'].interval, 1); assert.strictEqual(device.features['--contrast'].limits[0], -100); assert.strictEqual(device.features['--contrast'].limits[1], 100); - assert.strictEqual(device.features['--contrast'].interval, 1); + //assert.strictEqual(device.features['--contrast'].interval, 1); }); + it('scanimage-a2.txt', () => { + const file = new FileInfo('test/resource/scanimage-a2.txt'); + const device = Device.from(file.toText()); + + assert.deepStrictEqual(device.features['--mode'].options, ['Lineart', 'Gray', 'Color']); + assert.strictEqual(device.features['--mode'].default, 'Lineart'); + assert.deepStrictEqual(device.features['--resolution'].options, ['75', '300', '600', '1200']); + assert.strictEqual(device.features['--resolution'].default, '75'); + assert.strictEqual(device.features['-l'].limits[0], 0); + assert.strictEqual(device.features['-l'].limits[1], 215); + assert.strictEqual(device.features['-t'].limits[0], 0); + assert.strictEqual(device.features['-t'].limits[1], 297); + assert.strictEqual(device.features['-x'].limits[0], 0); + assert.strictEqual(device.features['-x'].limits[1], 215); + assert.strictEqual(device.features['-y'].limits[0], 0); + assert.strictEqual(device.features['-y'].limits[1], 297); + assert.strictEqual(device.features['--brightness'], undefined); + assert.strictEqual(device.features['--contrast'], undefined); + }); }); \ No newline at end of file diff --git a/test/resource/scanimage-a2.txt b/test/resource/scanimage-a2.txt new file mode 100644 index 00000000..09f00fa4 --- /dev/null +++ b/test/resource/scanimage-a2.txt @@ -0,0 +1,71 @@ + +All options specific to device `epson2:libusb:001:029': + Scan Mode: + --mode Lineart|Gray|Color [Lineart] + Selects the scan mode (e.g., lineart, monochrome, or color). + --depth 8bit [inactive] + Number of bits per sample, typical values are 1 for "line-art" and 8 + for multibit scans. + --halftoning None|Halftone A (Hard Tone)|Halftone B (Soft Tone)|Halftone C (Net Screen)|Dither A (4x4 Bayer)|Dither B (4x4 Spiral)|Dither C (4x4 Net Screen)|Dither D (8x4 Net Screen)|Text Enhanced Technology|Download pattern A|Download pattern B [inactive] + Selects the halftone. + --dropout None|Red|Green|Blue [None] + Selects the dropout. + --brightness 0..0 [inactive] + Selects the brightness. + --sharpness -2..2 [inactive] + + --gamma-correction User defined (Gamma=1.0)|User defined (Gamma=1.8) [User defined (Gamma=1.8)] + Selects the gamma correction value from a list of pre-defined devices + or the user defined table, which can be downloaded to the scanner + --color-correction None|Built in CCT profile|User defined CCT profile [inactive] + Sets the color correction table for the selected output device. + --resolution 75|300|600|1200dpi [75] + Sets the resolution of the scanned image. + --threshold 0..255 [128] + Select minimum-brightness to get a white point + Advanced: + --mirror[=(yes|no)] [inactive] + Mirror the image. + --auto-area-segmentation[=(yes|no)] [inactive] + Enables different dithering modes in image and text areas + --red-gamma-table 0..255,... + Gamma-correction table for the red band. + --green-gamma-table 0..255,... + Gamma-correction table for the green band. + --blue-gamma-table 0..255,... + Gamma-correction table for the blue band. + --wait-for-button[=(yes|no)] [no] + After sending the scan command, wait until the button on the scanner + is pressed to actually start the scan process. + Color correction: + --cct-type Automatic|Reflective|Colour negatives|Monochrome negatives|Colour positives [inactive] + Color correction profile type + --cct-profile -2..2,... + Color correction profile data + Preview: + --preview[=(yes|no)] [no] + Request a preview-quality scan. + Geometry: + -l 0..215.9mm [0] + Top-left x position of scan area. + -t 0..297.18mm [0] + Top-left y position of scan area. + -x 0..215.9mm [215.9] + Width of scan-area. + -y 0..297.18mm [297.18] + Height of scan-area. + Optional equipment: + --source Flatbed [inactive] + Selects the scan source (such as a document-feeder). + --auto-eject[=(yes|no)] [inactive] + Eject document after scanning + --film-type Positive Film|Negative Film|Positive Slide|Negative Slide [inactive] + + --focus-position Focus on glass|Focus 2.5mm above glass [inactive] + Sets the focus position to either the glass or 2.5mm above the glass + --bay 1|2|3|4|5|6 [inactive] + Select bay to scan + --eject [inactive] + Eject the sheet in the ADF + --adf-mode Simplex|Duplex [inactive] + Selects the ADF mode (simplex/duplex) From b589e3eacbcb3f8565a7835bfc06c89f67b455fc Mon Sep 17 00:00:00 2001 From: "sbs20@omicron.sbs20.com" Date: Mon, 14 Sep 2020 08:58:31 +0100 Subject: [PATCH 5/5] README --- README.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ec77dd3f..57690706 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # scanservjs scanservjs is a simple web-based UI for your scanner. It allows you to share a scanner (using SANE) on a network without the need for drivers or complicated -installation. It can save to TIF, JPG, PNG and PDF with varyings compression -settings. It also allows for configurable output conversions through -configuration. +installation. It can save to TIF, JPG, PNG and PDF with varying compression +settings, all of which can configured. It supports all +[SANE compatible devices](http://www.sane-project.org/sane-supported-devices.html). ![screenshot](https://github.com/sbs20/scanservjs/raw/master/docs/screen0.png) -Copyright 2016 [Sam Strachan](https://github.com/sbs20) +Copyright 2016-2020 [Sam Strachan](https://github.com/sbs20) ## Requirements * SANE @@ -41,7 +41,7 @@ docker run -d -p 8080:8080 --restart unless-stopped --name scanservjs-container More installation options: -* Manual installation notes [here](docs/install.md) +* [Manual installation notes](docs/install.md) * [Development notes](docs/development.md) * [Configuring the scanner and SANE](docs/sane.md) @@ -50,12 +50,8 @@ This is yet another scanimage-web-front-end. Why? It originally started as an adaptation of phpsane - just to make everything a bit newer, give it a refresh and make it work on minimal installations without imagemagick - that version is [still available](https://github.com/sbs20/scanserv) but is no longer -maintained. Then, I just wanted to write in node, and it's been a labour of love -ever since. - -## Roadmap -* Configuration page for debugging set up assisting new users -* Multi-language support +maintained. Then, I just wanted to write it in node and enhance it a bit, and +it's been a labour of love ever since. ## Acknowledgements * This project owes a lot to [phpsane](http://sourceforge.net/projects/phpsane/)