@cyclonedx/cdxgen 9.7.5 → 9.8.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/README.md +2 -1
- package/bin/cdxgen.js +3 -0
- package/index.js +33 -46
- package/package.json +7 -6
- package/utils.js +495 -391
- package/utils.test.js +201 -50
package/utils.js
CHANGED
|
@@ -1,29 +1,50 @@
|
|
|
1
1
|
import { globSync } from "glob";
|
|
2
|
-
import { homedir,
|
|
2
|
+
import { homedir, platform, tmpdir } from "node:os";
|
|
3
3
|
import {
|
|
4
|
-
dirname,
|
|
5
|
-
sep as _sep,
|
|
6
4
|
basename,
|
|
5
|
+
delimiter as _delimiter,
|
|
6
|
+
dirname,
|
|
7
7
|
extname,
|
|
8
8
|
join,
|
|
9
9
|
resolve,
|
|
10
|
-
|
|
10
|
+
sep as _sep
|
|
11
11
|
} from "node:path";
|
|
12
12
|
import {
|
|
13
|
+
chmodSync,
|
|
14
|
+
constants,
|
|
15
|
+
copyFileSync,
|
|
13
16
|
existsSync,
|
|
14
|
-
readFileSync,
|
|
15
17
|
lstatSync,
|
|
16
18
|
mkdtempSync,
|
|
19
|
+
readFileSync,
|
|
17
20
|
rmSync,
|
|
18
|
-
copyFileSync,
|
|
19
|
-
constants,
|
|
20
|
-
writeFileSync,
|
|
21
21
|
unlinkSync,
|
|
22
|
-
|
|
22
|
+
writeFileSync
|
|
23
23
|
} from "node:fs";
|
|
24
24
|
import got from "got";
|
|
25
|
+
import Arborist from "@npmcli/arborist";
|
|
26
|
+
import path from "path";
|
|
25
27
|
import { xml2js } from "xml-js";
|
|
26
28
|
import { fileURLToPath } from "node:url";
|
|
29
|
+
import { load } from "cheerio";
|
|
30
|
+
import { load as _load } from "js-yaml";
|
|
31
|
+
import { spawnSync } from "node:child_process";
|
|
32
|
+
import propertiesReader from "properties-reader";
|
|
33
|
+
import {
|
|
34
|
+
clean,
|
|
35
|
+
coerce,
|
|
36
|
+
compare,
|
|
37
|
+
maxSatisfying,
|
|
38
|
+
satisfies,
|
|
39
|
+
valid,
|
|
40
|
+
parse
|
|
41
|
+
} from "semver";
|
|
42
|
+
import StreamZip from "node-stream-zip";
|
|
43
|
+
import { parseEDNString } from "edn-data";
|
|
44
|
+
import { PackageURL } from "packageurl-js";
|
|
45
|
+
import { getTreeWithPlugin } from "./piptree.js";
|
|
46
|
+
import iconv from "iconv-lite";
|
|
47
|
+
|
|
27
48
|
let url = import.meta.url;
|
|
28
49
|
if (!url.startsWith("file://")) {
|
|
29
50
|
url = new URL(`file://${import.meta.url}`).toString();
|
|
@@ -45,16 +66,6 @@ const knownLicenses = JSON.parse(
|
|
|
45
66
|
const mesonWrapDB = JSON.parse(
|
|
46
67
|
readFileSync(join(dirNameStr, "data", "wrapdb-releases.json"))
|
|
47
68
|
);
|
|
48
|
-
import { load } from "cheerio";
|
|
49
|
-
import { load as _load } from "js-yaml";
|
|
50
|
-
import { spawnSync } from "node:child_process";
|
|
51
|
-
import propertiesReader from "properties-reader";
|
|
52
|
-
import { satisfies, coerce, maxSatisfying, clean, valid } from "semver";
|
|
53
|
-
import StreamZip from "node-stream-zip";
|
|
54
|
-
import { parseEDNString } from "edn-data";
|
|
55
|
-
import { PackageURL } from "packageurl-js";
|
|
56
|
-
import { getTreeWithPlugin } from "./piptree.js";
|
|
57
|
-
import iconv from "iconv-lite";
|
|
58
69
|
|
|
59
70
|
const selfPJson = JSON.parse(readFileSync(join(dirNameStr, "package.json")));
|
|
60
71
|
const _version = selfPJson.version;
|
|
@@ -80,7 +91,7 @@ export const DEBUG_MODE =
|
|
|
80
91
|
const TIMEOUT_MS = parseInt(process.env.CDXGEN_TIMEOUT_MS) || 20 * 60 * 1000;
|
|
81
92
|
|
|
82
93
|
// Metadata cache
|
|
83
|
-
let metadata_cache = {};
|
|
94
|
+
export let metadata_cache = {};
|
|
84
95
|
|
|
85
96
|
// Whether test scope shall be included for java/maven projects; default, if unset shall be 'true'
|
|
86
97
|
export const includeMavenTestScope =
|
|
@@ -88,7 +99,7 @@ export const includeMavenTestScope =
|
|
|
88
99
|
["true", "1"].includes(process.env.CDX_MAVEN_INCLUDE_TEST_SCOPE);
|
|
89
100
|
|
|
90
101
|
// Whether license information should be fetched
|
|
91
|
-
const
|
|
102
|
+
export const FETCH_LICENSE =
|
|
92
103
|
process.env.FETCH_LICENSE &&
|
|
93
104
|
["true", "1"].includes(process.env.FETCH_LICENSE);
|
|
94
105
|
|
|
@@ -100,7 +111,7 @@ if (process.env.PYTHON_CMD) {
|
|
|
100
111
|
}
|
|
101
112
|
|
|
102
113
|
// Custom user-agent for cdxgen
|
|
103
|
-
const cdxgenAgent = got.extend({
|
|
114
|
+
export const cdxgenAgent = got.extend({
|
|
104
115
|
headers: {
|
|
105
116
|
"user-agent": `@CycloneDX/cdxgen ${_version}`
|
|
106
117
|
}
|
|
@@ -330,121 +341,6 @@ export const getNpmMetadata = async function (pkgList) {
|
|
|
330
341
|
return cdepList;
|
|
331
342
|
};
|
|
332
343
|
|
|
333
|
-
const _getDepPkgList = async function (
|
|
334
|
-
pkgLockFile,
|
|
335
|
-
pkgList,
|
|
336
|
-
depKeys,
|
|
337
|
-
pkg,
|
|
338
|
-
versionCache
|
|
339
|
-
) {
|
|
340
|
-
const pkgDependencies = {
|
|
341
|
-
...(pkg.packages || {}),
|
|
342
|
-
...(pkg.dependencies || {})
|
|
343
|
-
};
|
|
344
|
-
if (pkg.packages) {
|
|
345
|
-
for (const k in pkg.packages) {
|
|
346
|
-
if (k === "") {
|
|
347
|
-
continue;
|
|
348
|
-
}
|
|
349
|
-
const pl = pkg.packages[k];
|
|
350
|
-
versionCache[k] = pl.version;
|
|
351
|
-
versionCache[k.replaceAll("node_modules/", "")] = pl.version;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
if (pkg && pkgDependencies) {
|
|
355
|
-
const pkgKeys = Object.keys(pkgDependencies);
|
|
356
|
-
for (const k of pkgKeys) {
|
|
357
|
-
// Skip the root package in lockFileVersion 3 and above
|
|
358
|
-
if (k === "") {
|
|
359
|
-
continue;
|
|
360
|
-
}
|
|
361
|
-
const name = k;
|
|
362
|
-
let version = pkgDependencies[name].version;
|
|
363
|
-
if (!version && versionCache[k]) {
|
|
364
|
-
version = versionCache[k];
|
|
365
|
-
}
|
|
366
|
-
if (!version && pkgDependencies["node_modules/" + name]) {
|
|
367
|
-
version = pkgDependencies["node_modules/" + name].version;
|
|
368
|
-
}
|
|
369
|
-
const purl = new PackageURL(
|
|
370
|
-
"npm",
|
|
371
|
-
"",
|
|
372
|
-
name.replaceAll("node_modules/", ""),
|
|
373
|
-
version,
|
|
374
|
-
null,
|
|
375
|
-
null
|
|
376
|
-
);
|
|
377
|
-
const purlString = decodeURIComponent(purl.toString());
|
|
378
|
-
const scope = pkgDependencies[name].dev === true ? "optional" : undefined;
|
|
379
|
-
const apkg = {
|
|
380
|
-
name: name.replaceAll("node_modules/", ""),
|
|
381
|
-
version,
|
|
382
|
-
_integrity: pkgDependencies[name].integrity,
|
|
383
|
-
scope,
|
|
384
|
-
properties: [
|
|
385
|
-
{
|
|
386
|
-
name: "SrcFile",
|
|
387
|
-
value: pkgLockFile
|
|
388
|
-
}
|
|
389
|
-
],
|
|
390
|
-
evidence: {
|
|
391
|
-
identity: {
|
|
392
|
-
field: "purl",
|
|
393
|
-
confidence: 1,
|
|
394
|
-
methods: [
|
|
395
|
-
{
|
|
396
|
-
technique: "manifest-analysis",
|
|
397
|
-
confidence: 1,
|
|
398
|
-
value: pkgLockFile
|
|
399
|
-
}
|
|
400
|
-
]
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
};
|
|
404
|
-
pkgList.push(apkg);
|
|
405
|
-
if (pkgDependencies[name].dependencies) {
|
|
406
|
-
// Include child dependencies
|
|
407
|
-
const dependencies = pkgDependencies[name].dependencies;
|
|
408
|
-
const pkgDepKeys = Object.keys(dependencies);
|
|
409
|
-
const deplist = [];
|
|
410
|
-
for (const j in pkgDepKeys) {
|
|
411
|
-
const depName = pkgDepKeys[j];
|
|
412
|
-
const depVersion =
|
|
413
|
-
versionCache[depName] || dependencies[depName].version;
|
|
414
|
-
if (!depVersion) {
|
|
415
|
-
continue;
|
|
416
|
-
}
|
|
417
|
-
const deppurl = new PackageURL(
|
|
418
|
-
"npm",
|
|
419
|
-
"",
|
|
420
|
-
depName.replaceAll("node_modules/", ""),
|
|
421
|
-
depVersion,
|
|
422
|
-
null,
|
|
423
|
-
null
|
|
424
|
-
);
|
|
425
|
-
const deppurlString = decodeURIComponent(deppurl.toString());
|
|
426
|
-
deplist.push(deppurlString);
|
|
427
|
-
}
|
|
428
|
-
depKeys[purlString] = (depKeys[purlString] || []).concat(deplist);
|
|
429
|
-
if (pkg.lockfileVersion && pkg.lockfileVersion >= 3) {
|
|
430
|
-
// Do not recurse for lock file v3 and above
|
|
431
|
-
} else {
|
|
432
|
-
await _getDepPkgList(
|
|
433
|
-
pkgLockFile,
|
|
434
|
-
pkgList,
|
|
435
|
-
depKeys,
|
|
436
|
-
pkgDependencies[name],
|
|
437
|
-
versionCache
|
|
438
|
-
);
|
|
439
|
-
}
|
|
440
|
-
} else if (!depKeys[purlString]) {
|
|
441
|
-
depKeys[purlString] = [];
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
return pkgList;
|
|
446
|
-
};
|
|
447
|
-
|
|
448
344
|
/**
|
|
449
345
|
* Parse nodejs package json file
|
|
450
346
|
*
|
|
@@ -495,7 +391,7 @@ export const parsePkgJson = async (pkgJsonFile) => {
|
|
|
495
391
|
// continue regardless of error
|
|
496
392
|
}
|
|
497
393
|
}
|
|
498
|
-
if (
|
|
394
|
+
if (FETCH_LICENSE && pkgList && pkgList.length) {
|
|
499
395
|
if (DEBUG_MODE) {
|
|
500
396
|
console.log(
|
|
501
397
|
`About to fetch license information for ${pkgList.length} packages in parsePkgJson`
|
|
@@ -514,115 +410,247 @@ export const parsePkgJson = async (pkgJsonFile) => {
|
|
|
514
410
|
*/
|
|
515
411
|
export const parsePkgLock = async (pkgLockFile, options = {}) => {
|
|
516
412
|
let pkgList = [];
|
|
517
|
-
|
|
518
|
-
const depKeys = {};
|
|
519
|
-
let rootPkg = {};
|
|
520
|
-
const versionCache = {};
|
|
413
|
+
let dependenciesList = [];
|
|
521
414
|
if (!options) {
|
|
522
415
|
options = {};
|
|
523
416
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
417
|
+
|
|
418
|
+
if (!existsSync(pkgLockFile)) {
|
|
419
|
+
return {
|
|
420
|
+
pkgList,
|
|
421
|
+
dependenciesList
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const parseArboristNode = (
|
|
426
|
+
node,
|
|
427
|
+
rootNode,
|
|
428
|
+
parentRef = null,
|
|
429
|
+
visited = new Set(),
|
|
430
|
+
options = {}
|
|
431
|
+
) => {
|
|
432
|
+
if (visited.has(node)) {
|
|
433
|
+
return { pkgList: [], dependenciesList: [] };
|
|
434
|
+
}
|
|
435
|
+
visited.add(node);
|
|
436
|
+
let pkgList = [];
|
|
437
|
+
let dependenciesList = [];
|
|
438
|
+
|
|
439
|
+
// Create the package entry
|
|
440
|
+
const srcFilePath = node.path.includes(`${_sep}node_modules`)
|
|
441
|
+
? node.path.split(`${_sep}node_modules`)[0]
|
|
442
|
+
: node.path;
|
|
443
|
+
const scope = node.dev === true ? "optional" : undefined;
|
|
444
|
+
const integrity = node.integrity ? node.integrity : undefined;
|
|
445
|
+
|
|
446
|
+
let pkg = {};
|
|
447
|
+
let purlString = "";
|
|
448
|
+
if (node == rootNode) {
|
|
449
|
+
purlString = decodeURIComponent(
|
|
450
|
+
new PackageURL(
|
|
451
|
+
"npm",
|
|
452
|
+
options.projectGroup || "",
|
|
453
|
+
options.projectName || node.packageName,
|
|
454
|
+
options.projectVersion || node.version,
|
|
455
|
+
null,
|
|
456
|
+
null
|
|
457
|
+
).toString()
|
|
458
|
+
);
|
|
459
|
+
pkg = {
|
|
460
|
+
author: node.package.author,
|
|
531
461
|
group: options.projectGroup || "",
|
|
532
|
-
name: options.projectName ||
|
|
533
|
-
version: options.projectVersion ||
|
|
462
|
+
name: options.projectName || node.packageName,
|
|
463
|
+
version: options.projectVersion || node.version,
|
|
534
464
|
type: "application",
|
|
535
|
-
"bom-ref":
|
|
465
|
+
"bom-ref": purlString
|
|
466
|
+
};
|
|
467
|
+
} else {
|
|
468
|
+
purlString = decodeURIComponent(
|
|
469
|
+
new PackageURL(
|
|
470
|
+
"npm",
|
|
471
|
+
"",
|
|
472
|
+
node.packageName,
|
|
473
|
+
node.version,
|
|
474
|
+
null,
|
|
475
|
+
null
|
|
476
|
+
).toString()
|
|
477
|
+
);
|
|
478
|
+
const pkgLockFile = join(
|
|
479
|
+
srcFilePath.replace("/", _sep),
|
|
480
|
+
"package-lock.json"
|
|
481
|
+
);
|
|
482
|
+
pkg = {
|
|
483
|
+
group: "",
|
|
484
|
+
name: node.packageName,
|
|
485
|
+
version: node.version,
|
|
486
|
+
author: node.package.author,
|
|
487
|
+
scope: scope,
|
|
488
|
+
_integrity: integrity,
|
|
489
|
+
properties: [
|
|
490
|
+
{
|
|
491
|
+
name: "SrcFile",
|
|
492
|
+
value: pkgLockFile
|
|
493
|
+
}
|
|
494
|
+
],
|
|
495
|
+
evidence: {
|
|
496
|
+
identity: {
|
|
497
|
+
field: "purl",
|
|
498
|
+
confidence: 1,
|
|
499
|
+
methods: [
|
|
500
|
+
{
|
|
501
|
+
technique: "manifest-analysis",
|
|
502
|
+
confidence: 1,
|
|
503
|
+
value: pkgLockFile
|
|
504
|
+
}
|
|
505
|
+
]
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
type: parentRef ? "npm" : "application",
|
|
509
|
+
"bom-ref": purlString
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
pkgList.push(pkg);
|
|
513
|
+
|
|
514
|
+
// retrieve workspace node pkglists
|
|
515
|
+
let workspaceDependsOn = [];
|
|
516
|
+
if (node.fsChildren && node.fsChildren.size > 0) {
|
|
517
|
+
for (let workspaceNode of node.fsChildren) {
|
|
518
|
+
const {
|
|
519
|
+
pkgList: childPkgList,
|
|
520
|
+
dependenciesList: childDependenciesList
|
|
521
|
+
} = parseArboristNode(workspaceNode, rootNode, purlString, visited);
|
|
522
|
+
pkgList = pkgList.concat(childPkgList);
|
|
523
|
+
dependenciesList = dependenciesList.concat(childDependenciesList);
|
|
524
|
+
|
|
525
|
+
const depWorkspacePurlString = decodeURIComponent(
|
|
536
526
|
new PackageURL(
|
|
537
527
|
"npm",
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
528
|
+
"",
|
|
529
|
+
workspaceNode.name,
|
|
530
|
+
workspaceNode.version,
|
|
541
531
|
null,
|
|
542
532
|
null
|
|
543
533
|
).toString()
|
|
544
|
-
)
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
const tmpA = dirName.split(_sep);
|
|
549
|
-
dirName = tmpA[tmpA.length - 1];
|
|
550
|
-
// v1 lock file
|
|
551
|
-
rootPkg = {
|
|
552
|
-
group: options.projectGroup || "",
|
|
553
|
-
name: options.projectName || lockData.name || dirName,
|
|
554
|
-
version: options.projectVersion || lockData.version || "",
|
|
555
|
-
type: "npm"
|
|
556
|
-
};
|
|
534
|
+
);
|
|
535
|
+
|
|
536
|
+
workspaceDependsOn.push(depWorkspacePurlString);
|
|
537
|
+
}
|
|
557
538
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
539
|
+
|
|
540
|
+
// this handles the case when a node has ["dependencies"] key in a package-lock.json
|
|
541
|
+
// for a node. We exclude the root node because it's already been handled
|
|
542
|
+
let childrenDependsOn = [];
|
|
543
|
+
if (node != rootNode) {
|
|
544
|
+
for (const child of node.children) {
|
|
545
|
+
let childNode = child[1];
|
|
546
|
+
const {
|
|
547
|
+
pkgList: childPkgList,
|
|
548
|
+
dependenciesList: childDependenciesList
|
|
549
|
+
} = parseArboristNode(childNode, rootNode, purlString, visited);
|
|
550
|
+
pkgList = pkgList.concat(childPkgList);
|
|
551
|
+
dependenciesList = dependenciesList.concat(childDependenciesList);
|
|
552
|
+
|
|
553
|
+
const depChildString = decodeURIComponent(
|
|
554
|
+
new PackageURL(
|
|
555
|
+
"npm",
|
|
556
|
+
"",
|
|
557
|
+
childNode.name,
|
|
558
|
+
childNode.version,
|
|
559
|
+
null,
|
|
560
|
+
null
|
|
561
|
+
).toString()
|
|
562
|
+
);
|
|
563
|
+
childrenDependsOn.push(depChildString);
|
|
582
564
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// this handles the case when a node has a ["requires"] key
|
|
568
|
+
const pkgDependsOn = [];
|
|
569
|
+
for (const edge of node.edgesOut.values()) {
|
|
570
|
+
let targetVersion;
|
|
571
|
+
let targetName;
|
|
572
|
+
|
|
573
|
+
// if the edge doesn't have an integrity, it's likely a peer dependency
|
|
574
|
+
// which isn't installed
|
|
575
|
+
let edgeToIntegrity = edge.to ? edge.to.integrity : null;
|
|
576
|
+
// let packageName = node.packageName;
|
|
577
|
+
// let edgeName = edge.name;
|
|
578
|
+
if (!edgeToIntegrity) {
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// the edges don't actually contain a version, so we need to search the root node
|
|
583
|
+
// children to find the correct version. we check the node children first, then
|
|
584
|
+
// we check the root node children
|
|
585
|
+
let foundMatch = false;
|
|
586
|
+
for (const child of node.children) {
|
|
587
|
+
if (child[1].integrity == edgeToIntegrity) {
|
|
588
|
+
targetName = child[0].replace(/node_modules\//g, "");
|
|
589
|
+
targetVersion = child[1].version;
|
|
590
|
+
foundMatch = true;
|
|
591
|
+
break;
|
|
604
592
|
}
|
|
605
593
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
594
|
+
if (!foundMatch) {
|
|
595
|
+
for (const child of rootNode.children) {
|
|
596
|
+
if (child[1].integrity == edgeToIntegrity) {
|
|
597
|
+
targetName = child[0].replace(/node_modules\//g, "");
|
|
598
|
+
targetVersion = child[1].version;
|
|
599
|
+
break;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// if we can't find the version of the edge, continue
|
|
605
|
+
// it may be an optional peer dependency
|
|
606
|
+
if (!targetVersion || !targetName) {
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
const depPurlString = decodeURIComponent(
|
|
611
|
+
new PackageURL(
|
|
612
|
+
"npm",
|
|
613
|
+
"",
|
|
614
|
+
targetName,
|
|
615
|
+
targetVersion,
|
|
616
|
+
null,
|
|
617
|
+
null
|
|
618
|
+
).toString()
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
pkgDependsOn.push(depPurlString);
|
|
622
|
+
if (edge.to == null) continue;
|
|
623
|
+
const { pkgList: childPkgList, dependenciesList: childDependenciesList } =
|
|
624
|
+
parseArboristNode(edge.to, rootNode, purlString, visited);
|
|
625
|
+
pkgList = pkgList.concat(childPkgList);
|
|
626
|
+
dependenciesList = dependenciesList.concat(childDependenciesList);
|
|
610
627
|
}
|
|
611
|
-
|
|
612
|
-
pkgLockFile,
|
|
613
|
-
pkgList,
|
|
614
|
-
depKeys,
|
|
615
|
-
lockData,
|
|
616
|
-
versionCache
|
|
617
|
-
);
|
|
618
|
-
}
|
|
619
|
-
for (const dk of Object.keys(depKeys)) {
|
|
628
|
+
|
|
620
629
|
dependenciesList.push({
|
|
621
|
-
ref:
|
|
622
|
-
dependsOn:
|
|
630
|
+
ref: purlString,
|
|
631
|
+
dependsOn: workspaceDependsOn
|
|
632
|
+
.concat(childrenDependsOn)
|
|
633
|
+
.concat(pkgDependsOn)
|
|
623
634
|
});
|
|
624
|
-
|
|
625
|
-
|
|
635
|
+
|
|
636
|
+
return { pkgList, dependenciesList };
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
const arb = new Arborist({
|
|
640
|
+
path: path.dirname(pkgLockFile),
|
|
641
|
+
// legacyPeerDeps=false enables npm >v3 package dependency resolution
|
|
642
|
+
legacyPeerDeps: false
|
|
643
|
+
});
|
|
644
|
+
const tree = await arb.loadVirtual();
|
|
645
|
+
({ pkgList, dependenciesList } = parseArboristNode(
|
|
646
|
+
tree,
|
|
647
|
+
tree,
|
|
648
|
+
null,
|
|
649
|
+
new Set(),
|
|
650
|
+
options
|
|
651
|
+
));
|
|
652
|
+
|
|
653
|
+
if (FETCH_LICENSE && pkgList && pkgList.length) {
|
|
626
654
|
if (DEBUG_MODE) {
|
|
627
655
|
console.log(
|
|
628
656
|
`About to fetch license information for ${pkgList.length} packages in parsePkgLock`
|
|
@@ -841,7 +869,7 @@ export const parseYarnLock = async function (yarnLockFile) {
|
|
|
841
869
|
}
|
|
842
870
|
});
|
|
843
871
|
}
|
|
844
|
-
if (
|
|
872
|
+
if (FETCH_LICENSE && pkgList && pkgList.length) {
|
|
845
873
|
if (DEBUG_MODE) {
|
|
846
874
|
console.log(
|
|
847
875
|
`About to fetch license information for ${pkgList.length} packages in parseYarnLock`
|
|
@@ -918,7 +946,7 @@ export const parseNodeShrinkwrap = async function (swFile) {
|
|
|
918
946
|
}
|
|
919
947
|
}
|
|
920
948
|
}
|
|
921
|
-
if (
|
|
949
|
+
if (FETCH_LICENSE && pkgList && pkgList.length) {
|
|
922
950
|
if (DEBUG_MODE) {
|
|
923
951
|
console.log(
|
|
924
952
|
`About to fetch license information for ${pkgList.length} packages in parseNodeShrinkwrap`
|
|
@@ -1085,7 +1113,7 @@ export const parsePnpmLock = async function (pnpmLock, parentComponent = null) {
|
|
|
1085
1113
|
}
|
|
1086
1114
|
}
|
|
1087
1115
|
}
|
|
1088
|
-
if (
|
|
1116
|
+
if (FETCH_LICENSE && pkgList && pkgList.length) {
|
|
1089
1117
|
if (DEBUG_MODE) {
|
|
1090
1118
|
console.log(
|
|
1091
1119
|
`About to fetch license information for ${pkgList.length} packages in parsePnpmLock`
|
|
@@ -1144,7 +1172,7 @@ export const parseBowerJson = async (bowerJsonFile) => {
|
|
|
1144
1172
|
// continue regardless of error
|
|
1145
1173
|
}
|
|
1146
1174
|
}
|
|
1147
|
-
if (
|
|
1175
|
+
if (FETCH_LICENSE && pkgList && pkgList.length) {
|
|
1148
1176
|
if (DEBUG_MODE) {
|
|
1149
1177
|
console.log(
|
|
1150
1178
|
`About to fetch license information for ${pkgList.length} packages in parseBowerJson`
|
|
@@ -1230,7 +1258,7 @@ export const parseMinJs = async (minJsFile) => {
|
|
|
1230
1258
|
// continue regardless of error
|
|
1231
1259
|
}
|
|
1232
1260
|
}
|
|
1233
|
-
if (
|
|
1261
|
+
if (FETCH_LICENSE && pkgList && pkgList.length) {
|
|
1234
1262
|
if (DEBUG_MODE) {
|
|
1235
1263
|
console.log(
|
|
1236
1264
|
`About to fetch license information for ${pkgList.length} packages in parseMinJs`
|
|
@@ -2068,13 +2096,13 @@ export const getMvnMetadata = async function (pkgList) {
|
|
|
2068
2096
|
if (!pkgList || !pkgList.length) {
|
|
2069
2097
|
return pkgList;
|
|
2070
2098
|
}
|
|
2071
|
-
if (DEBUG_MODE &&
|
|
2099
|
+
if (DEBUG_MODE && FETCH_LICENSE) {
|
|
2072
2100
|
console.log(`About to query maven for ${pkgList.length} packages`);
|
|
2073
2101
|
}
|
|
2074
2102
|
for (const p of pkgList) {
|
|
2075
2103
|
let group = p.group || "";
|
|
2076
2104
|
// If the package already has key metadata skip querying maven
|
|
2077
|
-
if (group && p.name && p.version && !
|
|
2105
|
+
if (group && p.name && p.version && !FETCH_LICENSE) {
|
|
2078
2106
|
cdepList.push(p);
|
|
2079
2107
|
continue;
|
|
2080
2108
|
}
|
|
@@ -2208,7 +2236,7 @@ export const guessPypiMatchingVersion = (versionsList, versionSpecifiers) => {
|
|
|
2208
2236
|
* @param {Boolean} fetchDepsInfo Fetch dependencies info from pypi
|
|
2209
2237
|
*/
|
|
2210
2238
|
export const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
2211
|
-
if (!
|
|
2239
|
+
if (!FETCH_LICENSE && !fetchDepsInfo) {
|
|
2212
2240
|
return pkgList;
|
|
2213
2241
|
}
|
|
2214
2242
|
const PYPI_URL = "https://pypi.org/pypi/";
|
|
@@ -2879,7 +2907,7 @@ export const getGoPkgLicense = async function (repoMetadata) {
|
|
|
2879
2907
|
export const getGoPkgComponent = async function (group, name, version, hash) {
|
|
2880
2908
|
let pkg = {};
|
|
2881
2909
|
let license = undefined;
|
|
2882
|
-
if (
|
|
2910
|
+
if (FETCH_LICENSE) {
|
|
2883
2911
|
if (DEBUG_MODE) {
|
|
2884
2912
|
console.log(
|
|
2885
2913
|
`About to fetch go package license information for ${group}:${name}`
|
|
@@ -3060,7 +3088,7 @@ export const parseGosumData = async function (gosumData) {
|
|
|
3060
3088
|
const version = tmpA[1].replace("/go.mod", "");
|
|
3061
3089
|
const hash = tmpA[tmpA.length - 1].replace("h1:", "sha256-");
|
|
3062
3090
|
let license = undefined;
|
|
3063
|
-
if (
|
|
3091
|
+
if (FETCH_LICENSE) {
|
|
3064
3092
|
if (DEBUG_MODE) {
|
|
3065
3093
|
console.log(
|
|
3066
3094
|
`About to fetch go package license information for ${name}`
|
|
@@ -3112,7 +3140,7 @@ export const parseGopkgData = async function (gopkgData) {
|
|
|
3112
3140
|
case "name":
|
|
3113
3141
|
pkg.group = "";
|
|
3114
3142
|
pkg.name = value;
|
|
3115
|
-
if (
|
|
3143
|
+
if (FETCH_LICENSE) {
|
|
3116
3144
|
pkg.license = await getGoPkgLicense({
|
|
3117
3145
|
group: pkg.group,
|
|
3118
3146
|
name: pkg.name
|
|
@@ -3239,7 +3267,7 @@ export const parseGemspecData = async function (gemspecData) {
|
|
|
3239
3267
|
}
|
|
3240
3268
|
});
|
|
3241
3269
|
pkgList = [pkg];
|
|
3242
|
-
if (
|
|
3270
|
+
if (FETCH_LICENSE) {
|
|
3243
3271
|
return await getRubyGemsMetadata(pkgList);
|
|
3244
3272
|
} else {
|
|
3245
3273
|
return pkgList;
|
|
@@ -3288,7 +3316,7 @@ export const parseGemfileLockData = async function (gemLockData) {
|
|
|
3288
3316
|
specsFound = false;
|
|
3289
3317
|
}
|
|
3290
3318
|
});
|
|
3291
|
-
if (
|
|
3319
|
+
if (FETCH_LICENSE) {
|
|
3292
3320
|
return await getRubyGemsMetadata(pkgList);
|
|
3293
3321
|
} else {
|
|
3294
3322
|
return pkgList;
|
|
@@ -3458,7 +3486,7 @@ export const parseCargoTomlData = async function (cargoData) {
|
|
|
3458
3486
|
if (pkg) {
|
|
3459
3487
|
pkgList.push(pkg);
|
|
3460
3488
|
}
|
|
3461
|
-
if (
|
|
3489
|
+
if (FETCH_LICENSE) {
|
|
3462
3490
|
return await getCratesMetadata(pkgList);
|
|
3463
3491
|
} else {
|
|
3464
3492
|
return pkgList;
|
|
@@ -3506,7 +3534,7 @@ export const parseCargoData = async function (cargoData) {
|
|
|
3506
3534
|
}
|
|
3507
3535
|
}
|
|
3508
3536
|
});
|
|
3509
|
-
if (
|
|
3537
|
+
if (FETCH_LICENSE) {
|
|
3510
3538
|
return await getCratesMetadata(pkgList);
|
|
3511
3539
|
} else {
|
|
3512
3540
|
return pkgList;
|
|
@@ -3535,7 +3563,7 @@ export const parseCargoAuditableData = async function (cargoData) {
|
|
|
3535
3563
|
});
|
|
3536
3564
|
}
|
|
3537
3565
|
});
|
|
3538
|
-
if (
|
|
3566
|
+
if (FETCH_LICENSE) {
|
|
3539
3567
|
return await getCratesMetadata(pkgList);
|
|
3540
3568
|
} else {
|
|
3541
3569
|
return pkgList;
|
|
@@ -3575,7 +3603,7 @@ export const parsePubLockData = async function (pubLockData) {
|
|
|
3575
3603
|
}
|
|
3576
3604
|
}
|
|
3577
3605
|
});
|
|
3578
|
-
if (
|
|
3606
|
+
if (FETCH_LICENSE) {
|
|
3579
3607
|
return await getDartMetadata(pkgList);
|
|
3580
3608
|
} else {
|
|
3581
3609
|
return pkgList;
|
|
@@ -4280,11 +4308,7 @@ export const parseNuspecData = async function (nupkgFile, nuspecData) {
|
|
|
4280
4308
|
}
|
|
4281
4309
|
};
|
|
4282
4310
|
pkgList.push(pkg);
|
|
4283
|
-
|
|
4284
|
-
return await getNugetMetadata(pkgList);
|
|
4285
|
-
} else {
|
|
4286
|
-
return pkgList;
|
|
4287
|
-
}
|
|
4311
|
+
return pkgList;
|
|
4288
4312
|
};
|
|
4289
4313
|
|
|
4290
4314
|
export const parseCsPkgData = async function (pkgData) {
|
|
@@ -4311,11 +4335,7 @@ export const parseCsPkgData = async function (pkgData) {
|
|
|
4311
4335
|
pkg.version = p.version;
|
|
4312
4336
|
pkgList.push(pkg);
|
|
4313
4337
|
}
|
|
4314
|
-
|
|
4315
|
-
return await getNugetMetadata(pkgList);
|
|
4316
|
-
} else {
|
|
4317
|
-
return pkgList;
|
|
4318
|
-
}
|
|
4338
|
+
return pkgList;
|
|
4319
4339
|
};
|
|
4320
4340
|
|
|
4321
4341
|
export const parseCsProjData = async function (csProjData) {
|
|
@@ -4365,11 +4385,7 @@ export const parseCsProjData = async function (csProjData) {
|
|
|
4365
4385
|
}
|
|
4366
4386
|
}
|
|
4367
4387
|
}
|
|
4368
|
-
|
|
4369
|
-
return await getNugetMetadata(pkgList);
|
|
4370
|
-
} else {
|
|
4371
|
-
return pkgList;
|
|
4372
|
-
}
|
|
4388
|
+
return pkgList;
|
|
4373
4389
|
};
|
|
4374
4390
|
|
|
4375
4391
|
export const parseCsProjAssetsData = async function (csProjData) {
|
|
@@ -4516,14 +4532,10 @@ export const parseCsProjAssetsData = async function (csProjData) {
|
|
|
4516
4532
|
}
|
|
4517
4533
|
}
|
|
4518
4534
|
}
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
pkgList,
|
|
4524
|
-
dependenciesList
|
|
4525
|
-
};
|
|
4526
|
-
}
|
|
4535
|
+
return {
|
|
4536
|
+
pkgList,
|
|
4537
|
+
dependenciesList
|
|
4538
|
+
};
|
|
4527
4539
|
};
|
|
4528
4540
|
|
|
4529
4541
|
export const parseCsPkgLockData = async function (csLockData) {
|
|
@@ -4547,120 +4559,7 @@ export const parseCsPkgLockData = async function (csLockData) {
|
|
|
4547
4559
|
pkgList.push(pkg);
|
|
4548
4560
|
}
|
|
4549
4561
|
}
|
|
4550
|
-
|
|
4551
|
-
return await getNugetMetadata(pkgList);
|
|
4552
|
-
} else {
|
|
4553
|
-
return pkgList;
|
|
4554
|
-
}
|
|
4555
|
-
};
|
|
4556
|
-
|
|
4557
|
-
/**
|
|
4558
|
-
* Method to retrieve metadata for nuget packages
|
|
4559
|
-
*
|
|
4560
|
-
* @param {Array} pkgList Package list
|
|
4561
|
-
*/
|
|
4562
|
-
export const getNugetMetadata = async function (pkgList) {
|
|
4563
|
-
const NUGET_URL = "https://api.nuget.org/v3/registration3/";
|
|
4564
|
-
const cdepList = [];
|
|
4565
|
-
for (const p of pkgList) {
|
|
4566
|
-
let cacheKey = undefined;
|
|
4567
|
-
try {
|
|
4568
|
-
if (
|
|
4569
|
-
(p.group && p.group.toLowerCase() === "system") ||
|
|
4570
|
-
p.name.toLowerCase().startsWith("system")
|
|
4571
|
-
) {
|
|
4572
|
-
p.license = "http://go.microsoft.com/fwlink/?LinkId=329770";
|
|
4573
|
-
} else if (
|
|
4574
|
-
(p.group && p.group.toLowerCase() === "microsoft") ||
|
|
4575
|
-
p.name.toLowerCase().startsWith("microsoft")
|
|
4576
|
-
) {
|
|
4577
|
-
p.license =
|
|
4578
|
-
"http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm";
|
|
4579
|
-
} else if (
|
|
4580
|
-
(p.group && p.group.toLowerCase() === "nuget") ||
|
|
4581
|
-
p.name.toLowerCase().startsWith("nuget")
|
|
4582
|
-
) {
|
|
4583
|
-
p.license = "Apache-2.0";
|
|
4584
|
-
} else {
|
|
4585
|
-
// If there is a version, we can safely use the cache to retrieve the license
|
|
4586
|
-
// See: https://github.com/CycloneDX/cdxgen/issues/352
|
|
4587
|
-
const twoPartName = p.name.split(".").slice(0, 2).join(".");
|
|
4588
|
-
cacheKey = `${p.group}|${twoPartName}`;
|
|
4589
|
-
let body = metadata_cache[cacheKey];
|
|
4590
|
-
if (body && body.error) {
|
|
4591
|
-
cdepList.push(p);
|
|
4592
|
-
continue;
|
|
4593
|
-
}
|
|
4594
|
-
if (!body) {
|
|
4595
|
-
if (DEBUG_MODE) {
|
|
4596
|
-
console.log(`Querying nuget for ${p.name}`);
|
|
4597
|
-
}
|
|
4598
|
-
const res = await cdxgenAgent.get(
|
|
4599
|
-
NUGET_URL +
|
|
4600
|
-
p.group.toLowerCase() +
|
|
4601
|
-
(p.group !== "" ? "." : "") +
|
|
4602
|
-
p.name.toLowerCase() +
|
|
4603
|
-
"/index.json",
|
|
4604
|
-
{ responseType: "json" }
|
|
4605
|
-
);
|
|
4606
|
-
const items = res.body.items;
|
|
4607
|
-
if (!items || !items[0] || !items[0].items) {
|
|
4608
|
-
continue;
|
|
4609
|
-
}
|
|
4610
|
-
const firstItem = items[0];
|
|
4611
|
-
// Work backwards to find the body for the matching version
|
|
4612
|
-
body = firstItem.items[firstItem.items.length - 1];
|
|
4613
|
-
if (p.version) {
|
|
4614
|
-
const newBody = firstItem.items
|
|
4615
|
-
.reverse()
|
|
4616
|
-
.filter(
|
|
4617
|
-
(i) => i.catalogEntry && i.catalogEntry.version === p.version
|
|
4618
|
-
);
|
|
4619
|
-
if (newBody && newBody.length) {
|
|
4620
|
-
body = newBody[0];
|
|
4621
|
-
}
|
|
4622
|
-
}
|
|
4623
|
-
metadata_cache[cacheKey] = body;
|
|
4624
|
-
}
|
|
4625
|
-
// Set the latest version in case it is missing
|
|
4626
|
-
if (!p.version && body.catalogEntry.version) {
|
|
4627
|
-
p.version = body.catalogEntry.version;
|
|
4628
|
-
}
|
|
4629
|
-
p.description = body.catalogEntry.description;
|
|
4630
|
-
if (body.catalogEntry.authors) {
|
|
4631
|
-
p.author = body.catalogEntry.authors.trim();
|
|
4632
|
-
}
|
|
4633
|
-
if (
|
|
4634
|
-
body.catalogEntry.licenseExpression &&
|
|
4635
|
-
body.catalogEntry.licenseExpression !== ""
|
|
4636
|
-
) {
|
|
4637
|
-
p.license = findLicenseId(body.catalogEntry.licenseExpression);
|
|
4638
|
-
} else if (body.catalogEntry.licenseUrl) {
|
|
4639
|
-
p.license = findLicenseId(body.catalogEntry.licenseUrl);
|
|
4640
|
-
}
|
|
4641
|
-
if (body.catalogEntry.projectUrl) {
|
|
4642
|
-
p.repository = { url: body.catalogEntry.projectUrl };
|
|
4643
|
-
p.homepage = {
|
|
4644
|
-
url:
|
|
4645
|
-
"https://www.nuget.org/packages/" +
|
|
4646
|
-
p.group +
|
|
4647
|
-
(p.group !== "" ? "." : "") +
|
|
4648
|
-
p.name +
|
|
4649
|
-
"/" +
|
|
4650
|
-
p.version +
|
|
4651
|
-
"/"
|
|
4652
|
-
};
|
|
4653
|
-
}
|
|
4654
|
-
}
|
|
4655
|
-
cdepList.push(p);
|
|
4656
|
-
} catch (err) {
|
|
4657
|
-
if (cacheKey) {
|
|
4658
|
-
metadata_cache[cacheKey] = { error: err.code };
|
|
4659
|
-
}
|
|
4660
|
-
cdepList.push(p);
|
|
4661
|
-
}
|
|
4662
|
-
}
|
|
4663
|
-
return cdepList;
|
|
4562
|
+
return pkgList;
|
|
4664
4563
|
};
|
|
4665
4564
|
|
|
4666
4565
|
/**
|
|
@@ -7074,13 +6973,10 @@ export const getCppModules = (src, options, osPkgsList, epkgList) => {
|
|
|
7074
6973
|
});
|
|
7075
6974
|
if (options.usagesSlicesFile && existsSync(options.usagesSlicesFile)) {
|
|
7076
6975
|
sliceData = JSON.parse(readFileSync(options.usagesSlicesFile));
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
if (!options.deep) {
|
|
7080
|
-
console.log(
|
|
7081
|
-
"By default, cdxgen parses c/c++ header files only which might miss system libraries and dependencies used directly in code. Pass the argument --deep to parse both source and header files. Please refer to the instructions in https://github.com/CycloneDX/cdxgen/blob/master/ADVANCED.md"
|
|
7082
|
-
);
|
|
6976
|
+
if (DEBUG_MODE) {
|
|
6977
|
+
console.log("Re-using existing slices file", options.usagesSlicesFile);
|
|
7083
6978
|
}
|
|
6979
|
+
} else {
|
|
7084
6980
|
sliceData = findAppModules(
|
|
7085
6981
|
src,
|
|
7086
6982
|
options.deep ? "c" : "h",
|
|
@@ -7096,7 +6992,12 @@ export const getCppModules = (src, options, osPkgsList, epkgList) => {
|
|
|
7096
6992
|
}
|
|
7097
6993
|
let extn = extname(fileName);
|
|
7098
6994
|
let group = dirname(afile);
|
|
7099
|
-
if (
|
|
6995
|
+
if (
|
|
6996
|
+
group.startsWith(".") ||
|
|
6997
|
+
group.startsWith(_sep) ||
|
|
6998
|
+
existsSync(resolve(afile)) ||
|
|
6999
|
+
existsSync(resolve(src, afile))
|
|
7000
|
+
) {
|
|
7100
7001
|
group = "";
|
|
7101
7002
|
}
|
|
7102
7003
|
let version = "";
|
|
@@ -7230,3 +7131,206 @@ export const parseCUsageSlice = (sliceData) => {
|
|
|
7230
7131
|
}
|
|
7231
7132
|
return usageData;
|
|
7232
7133
|
};
|
|
7134
|
+
|
|
7135
|
+
async function getNugetUrl() {
|
|
7136
|
+
const req = "https://api.nuget.org/v3/index.json";
|
|
7137
|
+
const res = await cdxgenAgent.get(req, {
|
|
7138
|
+
responseType: "json"
|
|
7139
|
+
});
|
|
7140
|
+
const urls = res.body.resources;
|
|
7141
|
+
for (const resource of urls) {
|
|
7142
|
+
if (resource["@type"] === "RegistrationsBaseUrl/3.6.0") {
|
|
7143
|
+
return resource["@id"];
|
|
7144
|
+
}
|
|
7145
|
+
}
|
|
7146
|
+
return "https://api.nuget.org/v3/registration3/";
|
|
7147
|
+
}
|
|
7148
|
+
|
|
7149
|
+
async function queryNuget(p, NUGET_URL) {
|
|
7150
|
+
if (DEBUG_MODE) {
|
|
7151
|
+
console.log(`Querying nuget for ${p.name}`);
|
|
7152
|
+
}
|
|
7153
|
+
const np = JSON.parse(JSON.stringify(p));
|
|
7154
|
+
const body = [];
|
|
7155
|
+
const newBody = [];
|
|
7156
|
+
let res = await cdxgenAgent.get(
|
|
7157
|
+
NUGET_URL + np.name.toLowerCase() + "/index.json",
|
|
7158
|
+
{ responseType: "json" }
|
|
7159
|
+
);
|
|
7160
|
+
let items = res.body.items;
|
|
7161
|
+
if (!items || !items[0]) {
|
|
7162
|
+
return [np, newBody, body];
|
|
7163
|
+
}
|
|
7164
|
+
if (items[0] && !items[0].items) {
|
|
7165
|
+
if (!p.version || p.version === "0.0.0" || p.version === "latest") {
|
|
7166
|
+
const tmpVersion = parse(res.body.items[res.body.items.length - 1].upper);
|
|
7167
|
+
np.version =
|
|
7168
|
+
tmpVersion.major + "." + tmpVersion.minor + "." + tmpVersion.patch;
|
|
7169
|
+
if (
|
|
7170
|
+
compare(np.version, res.body.items[res.body.items.length - 1].upper) ===
|
|
7171
|
+
1
|
|
7172
|
+
) {
|
|
7173
|
+
if (tmpVersion.patch > 0) {
|
|
7174
|
+
np.version =
|
|
7175
|
+
tmpVersion.major +
|
|
7176
|
+
"." +
|
|
7177
|
+
tmpVersion.minor +
|
|
7178
|
+
"." +
|
|
7179
|
+
(tmpVersion.patch - 1).toString();
|
|
7180
|
+
}
|
|
7181
|
+
}
|
|
7182
|
+
}
|
|
7183
|
+
for (const item of items) {
|
|
7184
|
+
// if (!p.version || p.version === "0.0.0" || p.version === "latest") {
|
|
7185
|
+
// const tmpVersion = parse(res.body.items[res.body.items.length - 1].upper);
|
|
7186
|
+
// np.version = tmpVersion.major + "." + tmpVersion.minor + "." + tmpVersion.patch;
|
|
7187
|
+
//
|
|
7188
|
+
// }
|
|
7189
|
+
if (np.version && valid(np.version)) {
|
|
7190
|
+
let lower = compare(item.lower, np.version);
|
|
7191
|
+
let upper = compare(item.upper, np.version);
|
|
7192
|
+
if (lower !== 1 && upper !== -1) {
|
|
7193
|
+
res = await cdxgenAgent.get(item["@id"], { responseType: "json" });
|
|
7194
|
+
newBody.push(
|
|
7195
|
+
res.body.items
|
|
7196
|
+
.reverse()
|
|
7197
|
+
.filter(
|
|
7198
|
+
(i) => i.catalogEntry && i.catalogEntry.version === np.version
|
|
7199
|
+
)
|
|
7200
|
+
);
|
|
7201
|
+
break;
|
|
7202
|
+
}
|
|
7203
|
+
}
|
|
7204
|
+
}
|
|
7205
|
+
} else {
|
|
7206
|
+
if (!p.version || p.version === "0.0.0" || p.version === "latest") {
|
|
7207
|
+
const tmpVersion = parse(res.body.items[res.body.items.length - 1].upper);
|
|
7208
|
+
np.version =
|
|
7209
|
+
tmpVersion.major + "." + tmpVersion.minor + "." + tmpVersion.patch;
|
|
7210
|
+
}
|
|
7211
|
+
const firstItem = items[0];
|
|
7212
|
+
// Work backwards to find the body for the matching version
|
|
7213
|
+
// body.push(firstItem.items[firstItem.items.length - 1])
|
|
7214
|
+
if (np.version) {
|
|
7215
|
+
newBody.push(
|
|
7216
|
+
firstItem.items
|
|
7217
|
+
.reverse()
|
|
7218
|
+
.filter(
|
|
7219
|
+
(i) => i.catalogEntry && i.catalogEntry.version === np.version
|
|
7220
|
+
)
|
|
7221
|
+
);
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7224
|
+
return [np, newBody];
|
|
7225
|
+
}
|
|
7226
|
+
|
|
7227
|
+
/**
|
|
7228
|
+
* Method to retrieve metadata for nuget packages
|
|
7229
|
+
*
|
|
7230
|
+
* @param {Array} pkgList Package list
|
|
7231
|
+
*/
|
|
7232
|
+
export const getNugetMetadata = async function (
|
|
7233
|
+
pkgList,
|
|
7234
|
+
dependencies = undefined
|
|
7235
|
+
) {
|
|
7236
|
+
const NUGET_URL = await getNugetUrl();
|
|
7237
|
+
const cdepList = [];
|
|
7238
|
+
const depRepList = {};
|
|
7239
|
+
for (const p of pkgList) {
|
|
7240
|
+
let cacheKey = undefined;
|
|
7241
|
+
try {
|
|
7242
|
+
// If there is a version, we can safely use the cache to retrieve the license
|
|
7243
|
+
// See: https://github.com/CycloneDX/cdxgen/issues/352
|
|
7244
|
+
cacheKey = `${p.name}|${p.version}`;
|
|
7245
|
+
let body = metadata_cache[cacheKey];
|
|
7246
|
+
|
|
7247
|
+
if (body && body.error) {
|
|
7248
|
+
cdepList.push(p);
|
|
7249
|
+
continue;
|
|
7250
|
+
}
|
|
7251
|
+
if (!body) {
|
|
7252
|
+
let newBody = {};
|
|
7253
|
+
let np = {};
|
|
7254
|
+
[np, newBody] = await queryNuget(p, NUGET_URL);
|
|
7255
|
+
if (p.version !== np.version) {
|
|
7256
|
+
const oldRef = p["bom-ref"];
|
|
7257
|
+
p["bom-ref"] = decodeURIComponent(
|
|
7258
|
+
new PackageURL(
|
|
7259
|
+
"nuget",
|
|
7260
|
+
"",
|
|
7261
|
+
np.name,
|
|
7262
|
+
np.version,
|
|
7263
|
+
null,
|
|
7264
|
+
null
|
|
7265
|
+
).toString()
|
|
7266
|
+
);
|
|
7267
|
+
depRepList[oldRef] = p["bom-ref"];
|
|
7268
|
+
p.version = np.version;
|
|
7269
|
+
}
|
|
7270
|
+
if (newBody && newBody[0].length > 0) {
|
|
7271
|
+
body = newBody[0][0];
|
|
7272
|
+
}
|
|
7273
|
+
if (body) {
|
|
7274
|
+
metadata_cache[cacheKey] = body;
|
|
7275
|
+
// Set the latest version in case it is missing
|
|
7276
|
+
if (!p.version && body.catalogEntry.version) {
|
|
7277
|
+
p.version = body.catalogEntry.version;
|
|
7278
|
+
}
|
|
7279
|
+
p.description = body.catalogEntry.description;
|
|
7280
|
+
if (body.catalogEntry.authors) {
|
|
7281
|
+
p.author = body.catalogEntry.authors.trim();
|
|
7282
|
+
}
|
|
7283
|
+
if (
|
|
7284
|
+
body.catalogEntry.licenseExpression &&
|
|
7285
|
+
body.catalogEntry.licenseExpression !== ""
|
|
7286
|
+
) {
|
|
7287
|
+
p.license = findLicenseId(body.catalogEntry.licenseExpression);
|
|
7288
|
+
} else if (body.catalogEntry.licenseUrl) {
|
|
7289
|
+
p.license = findLicenseId(body.catalogEntry.licenseUrl);
|
|
7290
|
+
}
|
|
7291
|
+
if (body.catalogEntry.projectUrl) {
|
|
7292
|
+
p.repository = { url: body.catalogEntry.projectUrl };
|
|
7293
|
+
p.homepage = {
|
|
7294
|
+
url:
|
|
7295
|
+
"https://www.nuget.org/packages/" +
|
|
7296
|
+
p.name +
|
|
7297
|
+
"/" +
|
|
7298
|
+
p.version +
|
|
7299
|
+
"/"
|
|
7300
|
+
};
|
|
7301
|
+
}
|
|
7302
|
+
cdepList.push(p);
|
|
7303
|
+
}
|
|
7304
|
+
}
|
|
7305
|
+
} catch (err) {
|
|
7306
|
+
if (cacheKey) {
|
|
7307
|
+
metadata_cache[cacheKey] = { error: err.code };
|
|
7308
|
+
}
|
|
7309
|
+
cdepList.push(p);
|
|
7310
|
+
}
|
|
7311
|
+
}
|
|
7312
|
+
const newDependencies = [].concat(dependencies);
|
|
7313
|
+
if (depRepList && newDependencies.length) {
|
|
7314
|
+
const changed = Object.keys(depRepList);
|
|
7315
|
+
// if (!parentComponent.version || parentComponent.version === "latest" || parentComponent.version === "0.0.0"){
|
|
7316
|
+
// if (changed.includes(parentComponent["bom-ref"])) {
|
|
7317
|
+
// parentComponent["bom-ref"] = depRepList[parentComponent["bom-ref"]["ref"]];
|
|
7318
|
+
// }
|
|
7319
|
+
// }
|
|
7320
|
+
for (const d of newDependencies) {
|
|
7321
|
+
if (changed.length > 0 && changed.includes(d["ref"])) {
|
|
7322
|
+
d["ref"] = depRepList[d["ref"]];
|
|
7323
|
+
}
|
|
7324
|
+
for (const dd in d["dependsOn"]) {
|
|
7325
|
+
if (changed.includes(d["dependsOn"][dd])) {
|
|
7326
|
+
const replace = d["dependsOn"][dd];
|
|
7327
|
+
d["dependsOn"][dd] = depRepList[replace];
|
|
7328
|
+
}
|
|
7329
|
+
}
|
|
7330
|
+
}
|
|
7331
|
+
}
|
|
7332
|
+
return {
|
|
7333
|
+
pkgList: cdepList,
|
|
7334
|
+
dependencies: newDependencies
|
|
7335
|
+
};
|
|
7336
|
+
};
|