scanoss 0.39.0 → 0.40.0
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/CHANGELOG.md +8 -0
- package/build/main/cli/commands/wfp.js +3 -3
- package/build/main/sdk/scanner/Scannable/ScannableItem.d.ts +2 -1
- package/build/main/sdk/scanner/Scannable/ScannableItem.js +3 -2
- package/build/main/sdk/scanner/WfpProvider/WfpCalculator/WfpCalculator.js +30 -15
- package/build/main/tsconfig.tsbuildinfo +1 -1
- package/build/module/cli/commands/wfp.js +3 -3
- package/build/module/sdk/scanner/Scannable/ScannableItem.d.ts +2 -1
- package/build/module/sdk/scanner/Scannable/ScannableItem.js +4 -2
- package/build/module/sdk/scanner/WfpProvider/WfpCalculator/WfpCalculator.js +30 -15
- package/build/module/tsconfig.module.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import { isFolder } from './helpers';
|
|
|
4
4
|
import { ScannerEvents, WinnowingMode } from '../../sdk/scanner/ScannerTypes';
|
|
5
5
|
import { WfpCalculator } from '../../sdk/scanner/WfpProvider/WfpCalculator/WfpCalculator';
|
|
6
6
|
import { Tree } from '../../sdk/tree/Tree';
|
|
7
|
-
import {
|
|
7
|
+
import { ScanFilter } from '../../sdk/tree/Filters/ScanFilter';
|
|
8
8
|
export async function wfpHandler(rootPath, options) {
|
|
9
9
|
rootPath = rootPath.replace(/\/$/, ''); // Remove trailing slash if exists
|
|
10
10
|
rootPath = rootPath.replace(/^\./, process.env.PWD); // Convert relative path to absolute path.
|
|
@@ -14,7 +14,7 @@ export async function wfpHandler(rootPath, options) {
|
|
|
14
14
|
if (pathIsFolder) {
|
|
15
15
|
const tree = new Tree(rootPath);
|
|
16
16
|
tree.build();
|
|
17
|
-
filesToFingerprint = tree.getFileList(new
|
|
17
|
+
filesToFingerprint = tree.getFileList(new ScanFilter(""));
|
|
18
18
|
}
|
|
19
19
|
else {
|
|
20
20
|
filesToFingerprint.push(rootPath);
|
|
@@ -45,4 +45,4 @@ export async function wfpHandler(rootPath, options) {
|
|
|
45
45
|
wfpInput.winnowingMode = WinnowingMode.FULL_WINNOWING_HPSM;
|
|
46
46
|
await wfpCalculator.start(wfpInput);
|
|
47
47
|
}
|
|
48
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
48
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ZwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NsaS9jb21tYW5kcy93ZnAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBRXBCLE9BQU8sV0FBVyxNQUFNLGNBQWMsQ0FBQztBQUV2QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFOUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDJEQUEyRCxDQUFDO0FBRTFGLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMzQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFHL0QsTUFBTSxDQUFDLEtBQUssVUFBVSxVQUFVLENBQUMsUUFBZ0IsRUFBRSxPQUFZO0lBRTdELFFBQVEsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFFLGtDQUFrQztJQUMzRSxRQUFRLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFFLDBDQUEwQztJQUNoRyxNQUFNLFlBQVksR0FBRyxNQUFNLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM5QyxNQUFNLGFBQWEsR0FBRyxJQUFJLGFBQWEsRUFBRSxDQUFDO0lBRTFDLElBQUksa0JBQWtCLEdBQWEsRUFBRSxDQUFDO0lBQ3RDLElBQUksWUFBWSxFQUFFLENBQUM7UUFDakIsTUFBTSxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2Isa0JBQWtCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzVELENBQUM7U0FBTSxDQUFDO1FBQ04sa0JBQWtCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQ25DLENBQUM7SUFHRCxNQUFNLE9BQU8sR0FBRyxFQUFFLE1BQU0sRUFBRSx5RkFBeUYsRUFBRSxDQUFDO0lBQ3RILE1BQU0sSUFBSSxHQUFHLElBQUksV0FBVyxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUNwRixJQUFJLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUV6QyxJQUFJLFlBQVksR0FBRyxFQUFFLENBQUM7SUFDdEIsYUFBYSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxrQkFBc0MsRUFBRSxFQUFFO1FBQy9GLElBQUksQ0FBQyxTQUFTLENBQUMsa0JBQWtCLENBQUMsMkJBQTJCLEVBQUUsQ0FBQyxDQUFDO1FBQ2pFLFlBQVksR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFFLGtCQUFrQixDQUFDLFVBQVUsRUFBRSxDQUFFLENBQUM7SUFDeEUsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLE9BQU8sQ0FBQyxPQUFPO1FBQ2pCLGFBQWEsQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLFlBQVksRUFBRSxDQUFDLEdBQVcsRUFBRSxFQUFFO1lBQzNELE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDckIsQ0FBQyxDQUFDLENBQUM7SUFFTCxhQUFhLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLEVBQUU7UUFDdEQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ1osSUFBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbEIsRUFBRSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ2pELENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUM1QixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFFSCxNQUFNLFFBQVEsR0FBc0IsRUFBQyxRQUFRLEVBQUUsa0JBQWtCLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFBO0lBQ3ZILElBQUcsT0FBTyxDQUFDLElBQUk7UUFBRSxRQUFRLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQyxtQkFBbUIsQ0FBQztJQUM1RSxNQUFNLGFBQWEsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7QUFHdEMsQ0FBQyJ9
|
|
@@ -6,7 +6,8 @@ export declare class ScannableItem {
|
|
|
6
6
|
private fingerprint;
|
|
7
7
|
private maxSizeWfp;
|
|
8
8
|
private lineOffset;
|
|
9
|
-
|
|
9
|
+
private isBinary;
|
|
10
|
+
constructor(content: Buffer, contentSource: string, winnowingMode: any, maxSizeWfp: number, isBinary?: boolean);
|
|
10
11
|
getContent(): Buffer<ArrayBufferLike>;
|
|
11
12
|
getContentSource(): string;
|
|
12
13
|
getFingerprint(): any;
|
|
@@ -5,12 +5,14 @@ export class ScannableItem {
|
|
|
5
5
|
fingerprint;
|
|
6
6
|
maxSizeWfp;
|
|
7
7
|
lineOffset;
|
|
8
|
-
|
|
8
|
+
isBinary;
|
|
9
|
+
constructor(content, contentSource, winnowingMode, maxSizeWfp, isBinary = false) {
|
|
9
10
|
this.contentSource = contentSource;
|
|
10
11
|
this.content = content;
|
|
11
12
|
this.winnowingMode = winnowingMode;
|
|
12
13
|
this.maxSizeWfp = maxSizeWfp;
|
|
13
14
|
this.lineOffset = 0;
|
|
15
|
+
this.isBinary = isBinary;
|
|
14
16
|
}
|
|
15
17
|
getContent() {
|
|
16
18
|
return this.content;
|
|
@@ -34,4 +36,4 @@ export class ScannableItem {
|
|
|
34
36
|
return this.lineOffset;
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2Nhbm5hYmxlSXRlbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9zZGsvc2Nhbm5lci9TY2FubmFibGUvU2Nhbm5hYmxlSXRlbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxNQUFNLE9BQU8sYUFBYTtJQUNoQixhQUFhLENBQVM7SUFFdEIsT0FBTyxDQUFTO0lBRWhCLGFBQWEsQ0FBZ0I7SUFFN0IsV0FBVyxDQUFNO0lBRWpCLFVBQVUsQ0FBTTtJQUVoQixVQUFVLENBQVM7SUFFbkIsUUFBUSxDQUFVO0lBRTFCLFlBQVksT0FBZSxFQUFFLGFBQXFCLEVBQUUsYUFBa0IsRUFBRSxVQUFrQixFQUFFLFFBQVEsR0FBRyxLQUFLO1FBQzFHLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDO1FBQ25DLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDO1FBQ25DLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO0lBQzNCLENBQUM7SUFFTSxVQUFVO1FBQ2YsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3RCLENBQUM7SUFFTSxnQkFBZ0I7UUFDckIsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQzVCLENBQUM7SUFFTSxjQUFjO1FBQ25CLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztJQUMxQixDQUFDO0lBRU0sZ0JBQWdCO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQztJQUM1QixDQUFDO0lBRU0sYUFBYTtRQUNsQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDekIsQ0FBQztJQUVNLGFBQWEsQ0FBQyxNQUFjO1FBQ2pDLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDO0lBQzNCLENBQUM7SUFFTSxhQUFhO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUN6QixDQUFDO0NBQ0YifQ==
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
+
import { isBinaryFileSync } from 'isbinaryfile';
|
|
2
3
|
import { Worker } from 'worker_threads';
|
|
3
4
|
import { ScannableItem } from '../../Scannable/ScannableItem';
|
|
4
5
|
import { ScannerCfg } from '../../ScannerCfg';
|
|
@@ -16,18 +17,21 @@ parentPort.on('message', async (scannableItem) => {
|
|
|
16
17
|
fingerprint = wfp_for_content(
|
|
17
18
|
scannableItem.content,
|
|
18
19
|
scannableItem.contentSource,
|
|
19
|
-
scannableItem.maxSizeWfp
|
|
20
|
+
scannableItem.maxSizeWfp,
|
|
21
|
+
scannableItem.isBinary
|
|
20
22
|
);
|
|
21
23
|
} else if (scannableItem.winnowingMode === "FULL_WINNOWING_HPSM") {
|
|
22
24
|
fingerprint = wfp_hpsm_for_content(
|
|
23
25
|
scannableItem.content,
|
|
24
26
|
scannableItem.contentSource,
|
|
25
|
-
scannableItem.maxSizeWfp
|
|
27
|
+
scannableItem.maxSizeWfp,
|
|
28
|
+
scannableItem.isBinary
|
|
26
29
|
);
|
|
27
30
|
} else if (scannableItem.winnowingMode === "WINNOWING_ONLY_MD5") {
|
|
28
31
|
fingerprint = wfp_only_md5(
|
|
29
32
|
scannableItem.content,
|
|
30
|
-
scannableItem.contentSource
|
|
33
|
+
scannableItem.contentSource,
|
|
34
|
+
scannableItem.isBinary
|
|
31
35
|
);
|
|
32
36
|
}
|
|
33
37
|
|
|
@@ -290,18 +294,25 @@ function join_wfp_hpsm(wfp, hpsm) {
|
|
|
290
294
|
* @param {Buffer} content
|
|
291
295
|
* @param {string} contentSource
|
|
292
296
|
* @param {number} maxSize
|
|
297
|
+
* @param {boolean} isBinary When true, HPSM and snippet winnowing are skipped (binary content has no line/code semantics)
|
|
293
298
|
* @returns {string}
|
|
294
299
|
*/
|
|
295
|
-
function wfp_hpsm_for_content(content, contentSource, maxSize) {
|
|
296
|
-
let wfp = wfp_for_content(content, contentSource, maxSize)
|
|
300
|
+
function wfp_hpsm_for_content(content, contentSource, maxSize, isBinary) {
|
|
301
|
+
let wfp = wfp_for_content(content, contentSource, maxSize, isBinary)
|
|
302
|
+
if (isBinary) return truncate_string(wfp, maxSize)
|
|
297
303
|
let hpsm = calc_hpsm(content) //Returns a string
|
|
298
304
|
let wfp_hpsm_joined = join_wfp_hpsm(wfp, hpsm)
|
|
299
305
|
return truncate_string(wfp_hpsm_joined, maxSize)
|
|
300
306
|
}
|
|
301
307
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
308
|
+
// Snippet winnowing and HPSM are line/code semantics — meaningless on
|
|
309
|
+
// binary content (random bytes produce noise grams). Binary files emit
|
|
310
|
+
// only the file= MD5 line, matching the behavior of WINNOWING_ONLY_MD5.
|
|
311
|
+
function wfp_for_content(content, contentSource, maxSize, isBinary) {
|
|
312
|
+
let wfp = wfp_only_md5(content, contentSource, isBinary);
|
|
313
|
+
if (!isBinary) {
|
|
314
|
+
wfp += calc_wfp(content, maxSize);
|
|
315
|
+
}
|
|
305
316
|
return wfp;
|
|
306
317
|
}
|
|
307
318
|
|
|
@@ -410,14 +421,17 @@ function calculate_opposite_line_ending_hash(contents) {
|
|
|
410
421
|
return crypto.createHash('md5').update(opposite_contents).digest('hex');
|
|
411
422
|
}
|
|
412
423
|
|
|
413
|
-
function wfp_only_md5(contents, contentSource) {
|
|
424
|
+
function wfp_only_md5(contents, contentSource, isBinary) {
|
|
414
425
|
const file_md5 = crypto.createHash('md5').update(contents).digest('hex');
|
|
415
426
|
let wfp = 'file=' + String(file_md5) + ',' + String(contents.length) + ',' + String(contentSource)+ String.fromCharCode(10);
|
|
416
427
|
|
|
417
|
-
//
|
|
418
|
-
|
|
419
|
-
if (
|
|
420
|
-
|
|
428
|
+
// fh2 has no meaning on binary content (no line endings to flip) and the
|
|
429
|
+
// normalization loop blows past V8 limits on large buffers.
|
|
430
|
+
if (!isBinary) {
|
|
431
|
+
const opposite_hash = calculate_opposite_line_ending_hash(contents);
|
|
432
|
+
if (opposite_hash !== null) {
|
|
433
|
+
wfp += 'fh2=' + String(opposite_hash) + String.fromCharCode(10);
|
|
434
|
+
}
|
|
421
435
|
}
|
|
422
436
|
|
|
423
437
|
return wfp;
|
|
@@ -557,10 +571,11 @@ export class WfpCalculator extends WfpProvider {
|
|
|
557
571
|
const path = this.fileList[this.fileListIndex];
|
|
558
572
|
const contentSource = path.replace(`${this.folderRoot}`, '');
|
|
559
573
|
const content = await this.readFile(path);
|
|
574
|
+
const isBinary = content.length > 0 && isBinaryFileSync(path);
|
|
560
575
|
this.fileListIndex += 1;
|
|
561
576
|
if (!(this.fileListIndex % this.scannerCfg.WINNOWING_REPORT_STATUS_AFTER_X))
|
|
562
577
|
this.emit(ScannerEvents.WINNOWING_STATUS, this.scannerCfg.WINNOWING_REPORT_STATUS_AFTER_X);
|
|
563
|
-
const scannable = new ScannableItem(content, contentSource, this.winnowingMode, this.scannerCfg.WFP_FILE_MAX_SIZE);
|
|
578
|
+
const scannable = new ScannableItem(content, contentSource, this.winnowingMode, this.scannerCfg.WFP_FILE_MAX_SIZE, isBinary);
|
|
564
579
|
if (this.headerFilter && content.length > 0) {
|
|
565
580
|
const lineOffset = this.headerFilter.filter(path, content.toString('utf-8'));
|
|
566
581
|
scannable.setLineOffset(lineOffset);
|
|
@@ -636,4 +651,4 @@ export class WfpCalculator extends WfpProvider {
|
|
|
636
651
|
this.sendFingerprint(fingerprint);
|
|
637
652
|
}
|
|
638
653
|
}
|
|
639
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
654
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV2ZwQ2FsY3VsYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9zZGsvc2Nhbm5lci9XZnBQcm92aWRlci9XZnBDYWxjdWxhdG9yL1dmcENhbGN1bGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3BCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNoRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzlELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUErQixNQUFNLG9CQUFvQixDQUFDO0FBRWhGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzNELE9BQU8sRUFBcUIsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEUsT0FBTyxFQUFFLFlBQVksRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXJFLE1BQU0sWUFBWSxHQUFHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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
|