scanoss 0.2.10 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -18
- package/build/main/bin/cli-bin.js +7 -1
- package/build/main/commands/dep.d.ts +1 -0
- package/build/main/commands/dep.js +26 -0
- package/build/main/index.d.ts +2 -0
- package/build/main/index.js +3 -1
- package/build/main/lib/dependencies/Dependency.d.ts +9 -0
- package/build/main/lib/dependencies/Dependency.js +50 -0
- package/build/main/lib/dependencies/DependencyTypes.d.ts +19 -0
- package/build/main/lib/dependencies/DependencyTypes.js +3 -0
- package/build/main/lib/dependencies/PurlGenerator.d.ts +2 -0
- package/build/main/lib/dependencies/PurlGenerator.js +39 -0
- package/build/main/lib/dependencies/parsers/golangParser.d.ts +0 -0
- package/build/main/lib/dependencies/parsers/golangParser.js +3 -0
- package/build/main/lib/dependencies/parsers/mavenParser.d.ts +2 -0
- package/build/main/lib/dependencies/parsers/mavenParser.js +44 -0
- package/build/main/lib/dependencies/parsers/npmParser.d.ts +3 -0
- package/build/main/lib/dependencies/parsers/npmParser.js +45 -0
- package/build/main/lib/dependencies/parsers/pyParser.d.ts +2 -0
- package/build/main/lib/dependencies/parsers/pyParser.js +51 -0
- package/build/main/lib/dependencies/parsers/rubyParser.d.ts +3 -0
- package/build/main/lib/dependencies/parsers/rubyParser.js +135 -0
- package/build/main/lib/dependencies/parsers/types.d.ts +15 -0
- package/build/main/lib/dependencies/parsers/types.js +33 -0
- package/build/main/lib/dependencies/parsers/utils.d.ts +2 -0
- package/build/main/lib/dependencies/parsers/utils.js +20 -0
- package/build/main/lib/dependencies/src/PurlGenerator.d.ts +2 -0
- package/build/main/lib/dependencies/src/PurlGenerator.js +62 -0
- package/build/main/lib/dependencies/src/parsers/golangParser.d.ts +0 -0
- package/build/main/lib/dependencies/src/parsers/golangParser.js +3 -0
- package/build/main/lib/dependencies/src/parsers/mavenParser.d.ts +2 -0
- package/build/main/lib/dependencies/src/parsers/mavenParser.js +44 -0
- package/build/main/lib/dependencies/src/parsers/npmParser.d.ts +3 -0
- package/build/main/lib/dependencies/src/parsers/npmParser.js +45 -0
- package/build/main/lib/dependencies/src/parsers/pyParser.d.ts +2 -0
- package/build/main/lib/dependencies/src/parsers/pyParser.js +51 -0
- package/build/main/lib/dependencies/src/parsers/rubyParser.d.ts +3 -0
- package/build/main/lib/dependencies/src/parsers/rubyParser.js +135 -0
- package/build/main/lib/dependencies/src/parsers/types.d.ts +15 -0
- package/build/main/lib/dependencies/src/parsers/types.js +33 -0
- package/build/main/lib/dependencies/src/parsers/utils.d.ts +2 -0
- package/build/main/lib/dependencies/src/parsers/utils.js +19 -0
- package/build/main/lib/dependencyScan/dependencyScan.d.ts +2 -0
- package/build/main/lib/dependencyScan/dependencyScan.js +37 -0
- package/build/main/lib/dependencyScan/parser.d.ts +7 -0
- package/build/main/lib/dependencyScan/parser.js +41 -0
- package/build/main/lib/dependencyScan/utils.d.ts +1 -0
- package/build/main/lib/dependencyScan/utils.js +16 -0
- package/build/main/lib/scanner/Dependency/dependency.d.ts +9 -0
- package/build/main/lib/scanner/Dependency/dependency.js +46 -0
- package/build/main/lib/scanner/Dependency/dependencyScan.d.ts +9 -0
- package/build/main/lib/scanner/Dependency/dependencyScan.js +48 -0
- package/build/main/lib/scanner/Dependency/parser.d.ts +7 -0
- package/build/main/lib/scanner/Dependency/parser.js +41 -0
- package/build/main/lib/scanner/Dependency/utils.d.ts +1 -0
- package/build/main/lib/scanner/Dependency/utils.js +16 -0
- package/build/main/lib/tree/Tree.js +2 -2
- package/build/module/bin/cli-bin.js +7 -1
- package/build/module/commands/dep.d.ts +1 -0
- package/build/module/commands/dep.js +19 -0
- package/build/module/index.d.ts +2 -0
- package/build/module/index.js +3 -1
- package/build/module/lib/dependencies/Dependency.d.ts +9 -0
- package/build/module/lib/dependencies/Dependency.js +45 -0
- package/build/module/lib/dependencies/DependencyTypes.d.ts +19 -0
- package/build/module/lib/dependencies/DependencyTypes.js +2 -0
- package/build/module/lib/dependencies/PurlGenerator.d.ts +2 -0
- package/build/module/lib/dependencies/PurlGenerator.js +32 -0
- package/build/module/lib/dependencies/parsers/golangParser.d.ts +0 -0
- package/build/module/lib/dependencies/parsers/golangParser.js +3 -0
- package/build/module/lib/dependencies/parsers/mavenParser.d.ts +2 -0
- package/build/module/lib/dependencies/parsers/mavenParser.js +37 -0
- package/build/module/lib/dependencies/parsers/npmParser.d.ts +3 -0
- package/build/module/lib/dependencies/parsers/npmParser.js +37 -0
- package/build/module/lib/dependencies/parsers/pyParser.d.ts +2 -0
- package/build/module/lib/dependencies/parsers/pyParser.js +44 -0
- package/build/module/lib/dependencies/parsers/rubyParser.d.ts +3 -0
- package/build/module/lib/dependencies/parsers/rubyParser.js +132 -0
- package/build/module/lib/dependencies/parsers/types.d.ts +15 -0
- package/build/module/lib/dependencies/parsers/types.js +32 -0
- package/build/module/lib/dependencies/parsers/utils.d.ts +2 -0
- package/build/module/lib/dependencies/parsers/utils.js +15 -0
- package/build/module/lib/dependencies/src/PurlGenerator.d.ts +2 -0
- package/build/module/lib/dependencies/src/PurlGenerator.js +55 -0
- package/build/module/lib/dependencies/src/parsers/golangParser.d.ts +0 -0
- package/build/module/lib/dependencies/src/parsers/golangParser.js +3 -0
- package/build/module/lib/dependencies/src/parsers/mavenParser.d.ts +2 -0
- package/build/module/lib/dependencies/src/parsers/mavenParser.js +37 -0
- package/build/module/lib/dependencies/src/parsers/npmParser.d.ts +3 -0
- package/build/module/lib/dependencies/src/parsers/npmParser.js +37 -0
- package/build/module/lib/dependencies/src/parsers/pyParser.d.ts +2 -0
- package/build/module/lib/dependencies/src/parsers/pyParser.js +44 -0
- package/build/module/lib/dependencies/src/parsers/rubyParser.d.ts +3 -0
- package/build/module/lib/dependencies/src/parsers/rubyParser.js +132 -0
- package/build/module/lib/dependencies/src/parsers/types.d.ts +15 -0
- package/build/module/lib/dependencies/src/parsers/types.js +32 -0
- package/build/module/lib/dependencies/src/parsers/utils.d.ts +2 -0
- package/build/module/lib/dependencies/src/parsers/utils.js +14 -0
- package/build/module/lib/dependencyScan/dependencyScan.d.ts +2 -0
- package/build/module/lib/dependencyScan/dependencyScan.js +29 -0
- package/build/module/lib/dependencyScan/parser.d.ts +7 -0
- package/build/module/lib/dependencyScan/parser.js +38 -0
- package/build/module/lib/dependencyScan/utils.d.ts +1 -0
- package/build/module/lib/dependencyScan/utils.js +12 -0
- package/build/module/lib/scanner/Dependency/dependency.d.ts +9 -0
- package/build/module/lib/scanner/Dependency/dependency.js +38 -0
- package/build/module/lib/scanner/Dependency/dependencyScan.d.ts +9 -0
- package/build/module/lib/scanner/Dependency/dependencyScan.js +40 -0
- package/build/module/lib/scanner/Dependency/parser.d.ts +7 -0
- package/build/module/lib/scanner/Dependency/parser.js +38 -0
- package/build/module/lib/scanner/Dependency/utils.d.ts +1 -0
- package/build/module/lib/scanner/Dependency/utils.js +12 -0
- package/build/module/lib/tree/Tree.js +2 -2
- package/package.json +2 -1
- package/.circleci/config.yml +0 -64
- package/.cspell.json +0 -34
- package/.editorconfig +0 -15
- package/.eslintrc.json +0 -37
- package/.gitignore +0 -11
- package/.prettierignore +0 -2
- package/.vscode/extensions.json +0 -8
- package/.vscode/launch.json +0 -29
- package/.vscode/settings.json +0 -7
- package/build/tsconfig.module.tsbuildinfo +0 -1
- package/build/tsconfig.tsbuildinfo +0 -1
- package/examples/defaultFilter.json +0 -203
- package/package-lock.json +0 -18266
- package/src/bin/cli-bin.ts +0 -52
- package/src/commands/scan.ts +0 -97
- package/src/index.ts +0 -4
- package/src/lib/filters/defaultFilter.ts +0 -207
- package/src/lib/filters/filtering.ts +0 -234
- package/src/lib/scanner/Dispatcher/DispatchableItem.ts +0 -29
- package/src/lib/scanner/Dispatcher/Dispatcher.ts +0 -151
- package/src/lib/scanner/Dispatcher/DispatcherResponse.ts +0 -40
- package/src/lib/scanner/Dispatcher/GlobalControllerAborter.ts +0 -33
- package/src/lib/scanner/Scannable/ScannableItem.ts +0 -43
- package/src/lib/scanner/Scanner.ts +0 -319
- package/src/lib/scanner/ScannerCfg.ts +0 -29
- package/src/lib/scanner/ScannerTypes.ts +0 -41
- package/src/lib/scanner/Winnower/Winnower.ts +0 -439
- package/src/lib/scanner/Winnower/WinnowerExtractor.ts +0 -38
- package/src/lib/scanner/Winnower/WinnowerResponse.ts +0 -38
- package/src/lib/tree/File.ts +0 -20
- package/src/lib/tree/Folder.ts +0 -50
- package/src/lib/tree/Node.ts +0 -34
- package/src/lib/tree/Tree.ts +0 -89
- package/tsconfig.json +0 -47
- package/tsconfig.module.json +0 -11
- package/yarn.lock +0 -5670
|
@@ -1,439 +0,0 @@
|
|
|
1
|
-
import EventEmitter from 'events';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import { Worker } from 'worker_threads';
|
|
4
|
-
|
|
5
|
-
import { ScannableItem } from '../Scannable/ScannableItem';
|
|
6
|
-
import { ScannerCfg } from '../ScannerCfg';
|
|
7
|
-
import { ScannerEvents, ScannerInput, WinnowingMode } from '../ScannerTypes';
|
|
8
|
-
import { WinnowerExtractor } from './WinnowerExtractor';
|
|
9
|
-
|
|
10
|
-
import { WinnowerResponse } from './WinnowerResponse';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const stringWorker = `
|
|
15
|
-
const { parentPort } = require('worker_threads');
|
|
16
|
-
|
|
17
|
-
parentPort.on('message', async (scannableItem) => {
|
|
18
|
-
|
|
19
|
-
let fingerprint;
|
|
20
|
-
if ( scannableItem.winnowingMode === "FULL_WINNOWING") {
|
|
21
|
-
fingerprint = wfp_for_content(
|
|
22
|
-
scannableItem.content,
|
|
23
|
-
scannableItem.contentSource,
|
|
24
|
-
scannableItem.maxSizeWfp
|
|
25
|
-
);
|
|
26
|
-
} else {
|
|
27
|
-
fingerprint = wfp_only_md5(
|
|
28
|
-
scannableItem.content,
|
|
29
|
-
scannableItem.contentSource
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
scannableItem.fingerprint = fingerprint;
|
|
34
|
-
|
|
35
|
-
parentPort.postMessage(scannableItem);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const crypto = require('crypto');
|
|
40
|
-
|
|
41
|
-
const isWin = process.platform === 'win32';
|
|
42
|
-
const pathSeparator = isWin ? String.fromCharCode(92) : '/';
|
|
43
|
-
|
|
44
|
-
// Winnowing configuration. DO NOT CHANGE.
|
|
45
|
-
const GRAM = 30;
|
|
46
|
-
const WINDOW = 64;
|
|
47
|
-
|
|
48
|
-
// ASCII characters
|
|
49
|
-
const ASCII_0 = 48;
|
|
50
|
-
const ASCII_9 = 57;
|
|
51
|
-
const ASCII_A = 65;
|
|
52
|
-
const ASCII_Z = 90;
|
|
53
|
-
const ASCII_a = 97;
|
|
54
|
-
const ASCII_z = 122;
|
|
55
|
-
const ASCII_LF = 10;
|
|
56
|
-
|
|
57
|
-
function normalize(byte) {
|
|
58
|
-
if (byte < ASCII_0 || byte > ASCII_z) {
|
|
59
|
-
return 0;
|
|
60
|
-
}
|
|
61
|
-
if (byte <= ASCII_9 || byte >= ASCII_a) {
|
|
62
|
-
return byte;
|
|
63
|
-
}
|
|
64
|
-
if (byte >= ASCII_A && byte <= ASCII_Z) {
|
|
65
|
-
return byte + 32;
|
|
66
|
-
}
|
|
67
|
-
return 0;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function min_hex_array(array) {
|
|
71
|
-
let min = 'ffffffff';
|
|
72
|
-
for (let i = 0; i < array.length; i++) {
|
|
73
|
-
if (array[i] < min) {
|
|
74
|
-
min = array[i];
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return min;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function wfp_for_content(content, contentSource, maxSize) {
|
|
81
|
-
let wfp = wfp_only_md5(content, contentSource);
|
|
82
|
-
wfp += calc_wfp(content, maxSize);
|
|
83
|
-
return wfp;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function wfp_only_md5(contents, contentSource) {
|
|
87
|
-
const file_md5 = crypto.createHash('md5').update(contents).digest('hex');
|
|
88
|
-
let wfp = 'file=' + String(file_md5) + ',' + String(contents.length) + ',' + String(contentSource)+ String.fromCharCode(10);
|
|
89
|
-
return wfp;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function calc_wfp(contents, maxSize) {
|
|
93
|
-
let gram = '';
|
|
94
|
-
const window = [];
|
|
95
|
-
let normalized = 0;
|
|
96
|
-
let line = 1;
|
|
97
|
-
let min_hash = 'ffffffff';
|
|
98
|
-
let last_hash = 'ffffffff';
|
|
99
|
-
let last_line = 0;
|
|
100
|
-
let output = '';
|
|
101
|
-
let gram_crc32 = 0;
|
|
102
|
-
let wfp = '';
|
|
103
|
-
|
|
104
|
-
for (let i = 0; i < contents.length; i++) {
|
|
105
|
-
if(wfp.length > maxSize)
|
|
106
|
-
return wfp;
|
|
107
|
-
|
|
108
|
-
const byte = contents[i];
|
|
109
|
-
if (byte == ASCII_LF) {
|
|
110
|
-
line += 1;
|
|
111
|
-
normalized = 0;
|
|
112
|
-
} else {
|
|
113
|
-
normalized = normalize(byte);
|
|
114
|
-
}
|
|
115
|
-
// Is this an useful byte?
|
|
116
|
-
if (normalized) {
|
|
117
|
-
gram += String.fromCharCode(normalized);
|
|
118
|
-
|
|
119
|
-
if (gram.length >= GRAM) {
|
|
120
|
-
gram_crc32 = crc32c_hex(gram);
|
|
121
|
-
window.push(gram_crc32);
|
|
122
|
-
|
|
123
|
-
if (window.length >= WINDOW) {
|
|
124
|
-
min_hash = min_hex_array(window);
|
|
125
|
-
if (min_hash !== last_hash) {
|
|
126
|
-
// Hashing the hash will result in a better balanced output data set
|
|
127
|
-
// as it will counter the winnowing effect which selects the "minimum"
|
|
128
|
-
// hash in each window
|
|
129
|
-
const min_hash_bytes_le = parseHexString(
|
|
130
|
-
toLittleEndianCRCHex(min_hash)
|
|
131
|
-
);
|
|
132
|
-
const crc_hex = crc32c_for_bytes_hex(min_hash_bytes_le);
|
|
133
|
-
|
|
134
|
-
if (last_line != line) {
|
|
135
|
-
if (output.length > 0) {
|
|
136
|
-
wfp += String(output) + String.fromCharCode(10);
|
|
137
|
-
}
|
|
138
|
-
output = String(line) + '=' + String(crc_hex);
|
|
139
|
-
} else {
|
|
140
|
-
output += ',' + String(crc_hex);
|
|
141
|
-
}
|
|
142
|
-
last_line = line;
|
|
143
|
-
last_hash = min_hash;
|
|
144
|
-
}
|
|
145
|
-
window.shift();
|
|
146
|
-
}
|
|
147
|
-
gram = gram.slice(1);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (output.length > 0) {
|
|
152
|
-
wfp += String(output) + String.fromCharCode(10);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return wfp;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function parseHexString(str) {
|
|
159
|
-
const result = [];
|
|
160
|
-
while (str.length >= 2) {
|
|
161
|
-
result.push(parseInt(str.substring(0, 2), 16));
|
|
162
|
-
str = str.substring(2, str.length);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return result;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
*
|
|
170
|
-
* @param {string} hex
|
|
171
|
-
*/
|
|
172
|
-
function toLittleEndianCRCHex(hex) {
|
|
173
|
-
return (
|
|
174
|
-
hex.charAt(6) +
|
|
175
|
-
hex.charAt(7) +
|
|
176
|
-
hex.charAt(4) +
|
|
177
|
-
hex.charAt(5) +
|
|
178
|
-
hex.charAt(2) +
|
|
179
|
-
hex.charAt(3) +
|
|
180
|
-
hex.charAt(0) +
|
|
181
|
-
hex.charAt(1)
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
let CRC_TABLE = [];
|
|
186
|
-
|
|
187
|
-
function makeCRCTable() {
|
|
188
|
-
let c;
|
|
189
|
-
const crcTable = [];
|
|
190
|
-
for (let n = 0; n < 256; n++) {
|
|
191
|
-
c = n;
|
|
192
|
-
for (let k = 0; k < 8; k++) {
|
|
193
|
-
c = c & 1 ? 0x82f63b78 ^ (c >>> 1) : c >>> 1;
|
|
194
|
-
}
|
|
195
|
-
crcTable[n] = c;
|
|
196
|
-
}
|
|
197
|
-
return crcTable;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function crc32c(str) {
|
|
201
|
-
if (CRC_TABLE.length == 0) {
|
|
202
|
-
CRC_TABLE = makeCRCTable();
|
|
203
|
-
}
|
|
204
|
-
let crc = 0 ^ -1;
|
|
205
|
-
|
|
206
|
-
for (let i = 0; i < str.length; i++) {
|
|
207
|
-
crc = (crc >>> 8) ^ CRC_TABLE[(crc ^ str.charCodeAt(i)) & 0xff];
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return (crc ^ -1) >>> 0;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function crc32c_for_bytes(bytes) {
|
|
214
|
-
if (CRC_TABLE.length == 0) {
|
|
215
|
-
CRC_TABLE = makeCRCTable();
|
|
216
|
-
}
|
|
217
|
-
let crc = 0 ^ -1;
|
|
218
|
-
|
|
219
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
220
|
-
crc = (crc >>> 8) ^ CRC_TABLE[(crc ^ bytes[i]) & 0xff];
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return (crc ^ -1) >>> 0;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function crc32c_for_bytes_hex(bytes) {
|
|
227
|
-
return crc32c_for_bytes(bytes).toString(16).padStart(8, '0');
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function crc32c_hex(str) {
|
|
231
|
-
return crc32c(str).toString(16).padStart(8, '0');
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
`;
|
|
235
|
-
|
|
236
|
-
export class Winnower extends EventEmitter {
|
|
237
|
-
private scannerCfg: ScannerCfg;
|
|
238
|
-
|
|
239
|
-
private fileList: any;
|
|
240
|
-
|
|
241
|
-
private fileListIndex: number;
|
|
242
|
-
|
|
243
|
-
private folderRoot: string;
|
|
244
|
-
|
|
245
|
-
private wfp: string;
|
|
246
|
-
|
|
247
|
-
private worker: Worker;
|
|
248
|
-
|
|
249
|
-
private continue: boolean;
|
|
250
|
-
|
|
251
|
-
private isRunning: boolean;
|
|
252
|
-
|
|
253
|
-
private winnowingMode: WinnowingMode;
|
|
254
|
-
|
|
255
|
-
private readingFromFile: boolean;
|
|
256
|
-
|
|
257
|
-
private winnowingExtractor: WinnowerExtractor;
|
|
258
|
-
|
|
259
|
-
constructor(scannerCfg = new ScannerCfg()) {
|
|
260
|
-
super();
|
|
261
|
-
this.scannerCfg = scannerCfg;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
init() {
|
|
265
|
-
this.wfp = '';
|
|
266
|
-
this.folderRoot = '';
|
|
267
|
-
this.continue = true;
|
|
268
|
-
this.isRunning = false;
|
|
269
|
-
this.readingFromFile = false;
|
|
270
|
-
this.fileList = [];
|
|
271
|
-
this.fileListIndex = 0;
|
|
272
|
-
this.winnowingMode = WinnowingMode.FULL_WINNOWING;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
prepareWorker() {
|
|
276
|
-
this.worker = new Worker(stringWorker, { eval: true });
|
|
277
|
-
this.worker.on('message', async (scannableItem) => {
|
|
278
|
-
await this.winnowerPacker(scannableItem.fingerprint);
|
|
279
|
-
await this.nextStepMachine();
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
recoveryIndex() {
|
|
284
|
-
// Files: contains all files winnowed but not packed yet
|
|
285
|
-
const files = new WinnowerResponse(this.wfp, this.folderRoot).getFilesWinnowed();
|
|
286
|
-
if (files.length) {
|
|
287
|
-
const lastFileWinnowed = files[files.length - 1];
|
|
288
|
-
let i = 0;
|
|
289
|
-
while (i <= files.length && lastFileWinnowed !== this.fileList[this.fileListIndex - i]) {
|
|
290
|
-
i += 1;
|
|
291
|
-
}
|
|
292
|
-
// If file already winnowed cannot be found in fileList emit an error.
|
|
293
|
-
if (i > files.length) {
|
|
294
|
-
this.emit(ScannerEvents.ERROR, new Error('Cannot recovery index on winnower'));
|
|
295
|
-
return -1;
|
|
296
|
-
}
|
|
297
|
-
this.fileListIndex -= i;
|
|
298
|
-
if (this.fileList[this.fileListIndex] === lastFileWinnowed) this.fileListIndex += 1;
|
|
299
|
-
}
|
|
300
|
-
return 0;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
forceStopWorker() {
|
|
304
|
-
this.worker.removeAllListeners();
|
|
305
|
-
this.worker.terminate();
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// returns true if the a winnowing packet was sended
|
|
309
|
-
private winnowerPacker(winnowingResult: string): boolean {
|
|
310
|
-
// When the fingerprint of one file is bigger than 64Kb, truncate to the last 64Kb line.
|
|
311
|
-
if (winnowingResult.length > this.scannerCfg.WFP_FILE_MAX_SIZE) {
|
|
312
|
-
let truncateStringOnIndex = this.scannerCfg.WFP_FILE_MAX_SIZE;
|
|
313
|
-
let keepRemovingCharacters = true;
|
|
314
|
-
while (keepRemovingCharacters) {
|
|
315
|
-
if (winnowingResult[truncateStringOnIndex] === '\n') keepRemovingCharacters = false;
|
|
316
|
-
truncateStringOnIndex -= 1;
|
|
317
|
-
}
|
|
318
|
-
truncateStringOnIndex += 1;
|
|
319
|
-
// eslint-disable-next-line no-param-reassign
|
|
320
|
-
winnowingResult = winnowingResult.substring(0, truncateStringOnIndex);
|
|
321
|
-
// eslint-disable-next-line no-param-reassign
|
|
322
|
-
winnowingResult += '\n';
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (this.wfp.length + winnowingResult.length >= this.scannerCfg.WFP_FILE_MAX_SIZE) {
|
|
326
|
-
this.processPackedWfp(this.wfp);
|
|
327
|
-
this.wfp = '';
|
|
328
|
-
}
|
|
329
|
-
this.wfp += winnowingResult;
|
|
330
|
-
|
|
331
|
-
if(this.wfp !== winnowingResult) return false;
|
|
332
|
-
return true;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
processPackedWfp(content) {
|
|
336
|
-
const wnRsp = new WinnowerResponse(content, this.folderRoot);
|
|
337
|
-
this.emit(ScannerEvents.WINNOWING_NEW_CONTENT, wnRsp);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
async getNextScannableItem() {
|
|
341
|
-
if (this.fileListIndex >= this.fileList.length) return null;
|
|
342
|
-
const path = this.fileList[this.fileListIndex];
|
|
343
|
-
const contentSource = path.replace(`${this.folderRoot}`, '');
|
|
344
|
-
const content = await fs.promises.readFile(path);
|
|
345
|
-
this.fileListIndex += 1;
|
|
346
|
-
const scannable = new ScannableItem(content, contentSource, this.winnowingMode, this.scannerCfg.WFP_FILE_MAX_SIZE);
|
|
347
|
-
return scannable;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
async nextStepMachine() {
|
|
351
|
-
if (!this.continue) return;
|
|
352
|
-
const scannableItem = await this.getNextScannableItem();
|
|
353
|
-
if (scannableItem) this.worker.postMessage(scannableItem);
|
|
354
|
-
else this.finishWinnowing();
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
public startWinnowingFromFile(filePath: string) {
|
|
358
|
-
this.emit(ScannerEvents.WINNOWER_LOG, '[ SCANNER ]: Starting Winnowing from file...');
|
|
359
|
-
this.readingFromFile = true;
|
|
360
|
-
this.isRunning = true;
|
|
361
|
-
this.winnowingExtractor = new WinnowerExtractor();
|
|
362
|
-
this.winnowingExtractor.loadFile(filePath);
|
|
363
|
-
this.extractionProcess(this.scannerCfg.DISPATCHER_QUEUE_SIZE_MAX_LIMIT);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
private async extractionProcess(n: number) {
|
|
367
|
-
let winBlock = '-';
|
|
368
|
-
while(winBlock !== '' && n>=0) { // this.continue will change on method pause();
|
|
369
|
-
winBlock = this.winnowingExtractor.extractWinBlock(); // TODO Make async funcion
|
|
370
|
-
if(winBlock !== '') {
|
|
371
|
-
if (this.winnowerPacker(winBlock))
|
|
372
|
-
n-=1;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Last winnowing block
|
|
377
|
-
if(winBlock === '') this.finishWinnowing();
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
public async startWinnowing(scanInput: ScannerInput): Promise<void> {
|
|
381
|
-
this.emit(ScannerEvents.WINNOWER_LOG, '[ SCANNER ]: Starting Winnowing...');
|
|
382
|
-
|
|
383
|
-
this.init();
|
|
384
|
-
this.prepareWorker();
|
|
385
|
-
|
|
386
|
-
if(scanInput.winnowingMode) this.setWinnowingMode(scanInput.winnowingMode);
|
|
387
|
-
this.readingFromFile = false;
|
|
388
|
-
this.isRunning = true;
|
|
389
|
-
this.folderRoot = scanInput.folderRoot;
|
|
390
|
-
this.fileList = scanInput.fileList;
|
|
391
|
-
this.nextStepMachine();
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
private finishWinnowing() {
|
|
395
|
-
if (this.wfp.length !== 0) {
|
|
396
|
-
this.processPackedWfp(this.wfp);
|
|
397
|
-
}
|
|
398
|
-
this.isRunning = false;
|
|
399
|
-
this.emit(ScannerEvents.WINNOWER_LOG, '[ SCANNER ]: Winnowing Finished...');
|
|
400
|
-
this.forceStopWorker();
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
public pause(): void {
|
|
404
|
-
this.emit(ScannerEvents.WINNOWER_LOG, '[ SCANNER ]: Winnowing paused...');
|
|
405
|
-
this.continue = false;
|
|
406
|
-
if (!this.readingFromFile) {
|
|
407
|
-
this.forceStopWorker();
|
|
408
|
-
this.prepareWorker();
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
public resume(): void {
|
|
413
|
-
this.emit(ScannerEvents.WINNOWER_LOG, '[ SCANNER ]: Winnowing resumed...');
|
|
414
|
-
this.continue = true;
|
|
415
|
-
if (!this.readingFromFile) {
|
|
416
|
-
this.recoveryIndex();
|
|
417
|
-
this.nextStepMachine();
|
|
418
|
-
} else {
|
|
419
|
-
this.extractionProcess(this.scannerCfg.DISPATCHER_QUEUE_SIZE_MAX_LIMIT *2 );
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
public stop(): void {
|
|
424
|
-
this.continue = false;
|
|
425
|
-
this.isRunning = false;
|
|
426
|
-
this.winnowingExtractor = null;
|
|
427
|
-
this.forceStopWorker();
|
|
428
|
-
this.prepareWorker();
|
|
429
|
-
this.init();
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
public hasPendingFiles(): boolean {
|
|
433
|
-
return this.isRunning;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
public setWinnowingMode(mode: WinnowingMode): void {
|
|
437
|
-
this.winnowingMode = mode;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
|
|
3
|
-
export class WinnowerExtractor {
|
|
4
|
-
|
|
5
|
-
private winnowing: string;
|
|
6
|
-
|
|
7
|
-
private winnowingFilePath: string;
|
|
8
|
-
|
|
9
|
-
private blocksIndex: Array<number>;
|
|
10
|
-
|
|
11
|
-
private currentBlock: number;
|
|
12
|
-
|
|
13
|
-
constructor() {
|
|
14
|
-
this.init();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
private init() {
|
|
18
|
-
this.winnowing = '';
|
|
19
|
-
this.currentBlock = 0;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public loadFile(path: string) {
|
|
23
|
-
this.init();
|
|
24
|
-
this.winnowingFilePath = path;
|
|
25
|
-
this.winnowing = fs.readFileSync(path, 'utf-8');
|
|
26
|
-
const reg = /file=/g;
|
|
27
|
-
this.blocksIndex = [...((this.winnowing).matchAll(reg))].map(x => x.index);
|
|
28
|
-
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
public extractWinBlock(): string {
|
|
32
|
-
let res = '';
|
|
33
|
-
if (this.currentBlock < this.blocksIndex.length-1)
|
|
34
|
-
res = this.winnowing.substring(this.blocksIndex[this.currentBlock], this.blocksIndex[this.currentBlock+1]);
|
|
35
|
-
this.currentBlock+=1;
|
|
36
|
-
return res;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export class WinnowerResponse {
|
|
2
|
-
private wfpContent: string;
|
|
3
|
-
|
|
4
|
-
private engineFlags: number;
|
|
5
|
-
|
|
6
|
-
private scanRoot: string;
|
|
7
|
-
|
|
8
|
-
constructor(wfpContent, scanRoot = '') {
|
|
9
|
-
this.wfpContent = wfpContent;
|
|
10
|
-
this.scanRoot = scanRoot;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
public isEqual(winnowerResponse) {
|
|
14
|
-
return this.getContent() === winnowerResponse.getContent();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public getContent() {
|
|
18
|
-
return this.wfpContent;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public setEngineFlags(engineFlags: number): void {
|
|
22
|
-
this.engineFlags = engineFlags;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
public getEngineFlags(): number {
|
|
26
|
-
return this.engineFlags;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
public getFilesWinnowed() {
|
|
30
|
-
const files = [];
|
|
31
|
-
const regExp = new RegExp(/,(\/.*)/g);
|
|
32
|
-
let result;
|
|
33
|
-
// eslint-disable-next-line no-cond-assign
|
|
34
|
-
while ((result = regExp.exec(this.wfpContent))) files.push(this.scanRoot + result[1]);
|
|
35
|
-
return files || '';
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
package/src/lib/tree/File.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { NodeType } from './Node';
|
|
2
|
-
import Node from './Node';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export default class File extends Node {
|
|
6
|
-
constructor(name: string, path: string) {
|
|
7
|
-
super(name, path);
|
|
8
|
-
this.type = NodeType.FILE;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
public getNode(path: string): Node {
|
|
12
|
-
if (path === this.getPath()) return this;
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
public getFiles(): Array<string> {
|
|
17
|
-
return [this.getPath()];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
}
|
package/src/lib/tree/Folder.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { NodeType } from "./Node";
|
|
2
|
-
import Node from './Node';
|
|
3
|
-
|
|
4
|
-
export default class Folder extends Node {
|
|
5
|
-
private children: Node[];
|
|
6
|
-
|
|
7
|
-
constructor(path: string, label: string) {
|
|
8
|
-
super(path, label);
|
|
9
|
-
this.type = NodeType.FOLDER;
|
|
10
|
-
this.children = [];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
public addChild(node: Node): void {
|
|
14
|
-
this.children.push(node);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public getChildren(): Node[] {
|
|
18
|
-
return this.children;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public getNode(path: string): Node {
|
|
22
|
-
if (!this.checkMyPath(path)) return null;
|
|
23
|
-
if (path === this.getPath()) return this;
|
|
24
|
-
for (const child of this.children) {
|
|
25
|
-
const node = child.getNode(path);
|
|
26
|
-
if (node !== null) return node;
|
|
27
|
-
}
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Returns true only if my path is contained in the path (parameter)
|
|
32
|
-
private checkMyPath(path: string): boolean {
|
|
33
|
-
if (!path.includes(this.getPath())) return false;
|
|
34
|
-
// Only if first filter is passed.
|
|
35
|
-
const myPathExploded = this.getPath().split('/');
|
|
36
|
-
const pathExploded = path.split('/');
|
|
37
|
-
for (let i = 0; i < myPathExploded.length; i += 1) {
|
|
38
|
-
if (myPathExploded[i] !== pathExploded[i]) return false;
|
|
39
|
-
}
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public getFiles(): Array<string> {
|
|
44
|
-
const files: Array<string> = [];
|
|
45
|
-
this.children.forEach((child) => {
|
|
46
|
-
files.push(...child.getFiles());
|
|
47
|
-
});
|
|
48
|
-
return files;
|
|
49
|
-
}
|
|
50
|
-
}
|
package/src/lib/tree/Node.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export default abstract class Node {
|
|
2
|
-
protected type: NodeType;
|
|
3
|
-
|
|
4
|
-
protected rPath: string; // Relative path to the folder or file
|
|
5
|
-
|
|
6
|
-
protected label: string;
|
|
7
|
-
|
|
8
|
-
protected action: string;
|
|
9
|
-
|
|
10
|
-
constructor(path: string, label: string) {
|
|
11
|
-
this.rPath = path;
|
|
12
|
-
this.label = label;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
public abstract getNode(path: string): Node;
|
|
17
|
-
|
|
18
|
-
public abstract getFiles(): Array<string> ;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
public getName(): string {
|
|
22
|
-
return this.label;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
public getPath(): string {
|
|
26
|
-
return this.rPath;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export enum NodeType {
|
|
32
|
-
FOLDER = 'FOLDER',
|
|
33
|
-
FILE = 'FILE',
|
|
34
|
-
};
|
package/src/lib/tree/Tree.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import pathLib from 'path';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { NodeType } from './Node';
|
|
7
|
-
import Node from './Node';
|
|
8
|
-
import File from './File';
|
|
9
|
-
import Folder from './Folder';
|
|
10
|
-
import { FilterList } from '../filters/filtering';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export class Tree {
|
|
14
|
-
private rootFolder: Folder;
|
|
15
|
-
|
|
16
|
-
private rootName: string;
|
|
17
|
-
|
|
18
|
-
private rootPath: string;
|
|
19
|
-
|
|
20
|
-
private filter: FilterList;
|
|
21
|
-
|
|
22
|
-
constructor(path: string) {
|
|
23
|
-
const pathParts = path.split(pathLib.sep);
|
|
24
|
-
this.rootName = pathLib.basename(path);
|
|
25
|
-
this.rootPath = path;
|
|
26
|
-
this.rootFolder = new Folder('/', this.rootName);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
public buildTree(): Node {
|
|
30
|
-
this.buildTreeRec(this.rootPath, this.rootFolder);
|
|
31
|
-
return this.rootFolder;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
public loadFilter(f: FilterList){
|
|
35
|
-
this.filter = f;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
private buildTreeRec(path: string, root: Folder): Node {
|
|
39
|
-
const dirEntries = fs
|
|
40
|
-
.readdirSync(path, { withFileTypes: true }) // Returns a list of files and folders
|
|
41
|
-
.sort(this.dirFirstFileAfter)
|
|
42
|
-
.filter((dirent: any) => !dirent.isSymbolicLink());
|
|
43
|
-
|
|
44
|
-
for (const dirEntry of dirEntries) {
|
|
45
|
-
const fullPath = `${path}/${dirEntry.name}`;
|
|
46
|
-
const relativePath = `${path}/${dirEntry.name}`.replace(this.rootPath, '');
|
|
47
|
-
if (this.filter && this.filter.include(fullPath))
|
|
48
|
-
if (dirEntry.isDirectory()) {
|
|
49
|
-
const f: Folder = new Folder(relativePath, dirEntry.name);
|
|
50
|
-
const subTree = this.buildTreeRec(`${path}/${dirEntry.name}`, f);
|
|
51
|
-
root.addChild(subTree);
|
|
52
|
-
} else root.addChild(new File(relativePath, dirEntry.name));
|
|
53
|
-
}
|
|
54
|
-
return root;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// This is a sorter that will sort folders before files in alphabetical order.
|
|
58
|
-
private dirFirstFileAfter(a: any, b: any) {
|
|
59
|
-
if (!a.isDirectory() && b.isDirectory()) return 1;
|
|
60
|
-
if (a.isDirectory() && !b.isDirectory()) return -1;
|
|
61
|
-
return 0;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
public loadTree(data: any): void {
|
|
65
|
-
this.rootFolder = this.deserialize(data) as Folder;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
private deserialize(data: any): Node {
|
|
69
|
-
if (data.type === NodeType.FILE) {
|
|
70
|
-
return Object.assign(Object.create(File.prototype), data);
|
|
71
|
-
}
|
|
72
|
-
const children = data.children.map((child: any) => this.deserialize(child));
|
|
73
|
-
return Object.assign(Object.create(Folder.prototype), { ...data, children });
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
public getRootFolder(): Folder {
|
|
77
|
-
return this.rootFolder;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
public getRootPath(): string {
|
|
81
|
-
return this.rootPath;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
public getFileList(): Array<string> {
|
|
85
|
-
const rootPath = this.rootPath.substring(0, this.rootPath.length);
|
|
86
|
-
const fList = this.rootFolder.getFiles();
|
|
87
|
-
return fList.map((fileRelativePath: string) => {return (rootPath + fileRelativePath)});
|
|
88
|
-
}
|
|
89
|
-
}
|