@cyclonedx/cdxgen 8.5.3 → 9.0.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 +55 -45
- package/analyzer.js +15 -19
- package/bin/{cdxgen → cdxgen.js} +76 -25
- package/binary.js +52 -52
- package/data/known-licenses.json +31 -0
- package/{lic-mapping.json → data/lic-mapping.json} +11 -39
- package/data/pypi-pkg-aliases.json +1165 -0
- package/data/python-stdlib.json +308 -0
- package/{queries.json → data/queries.json} +8 -8
- package/data/vendor-alias.json +10 -0
- package/docker.js +157 -127
- package/docker.test.js +18 -14
- package/index.js +529 -417
- package/jest.config.js +6 -180
- package/package.json +20 -22
- package/server.js +12 -12
- package/utils.js +793 -377
- package/utils.test.js +395 -301
- package/.eslintrc.js +0 -15
- package/known-licenses.json +0 -27
- package/vendor-alias.json +0 -10
- /package/{spdx-licenses.json → data/spdx-licenses.json} +0 -0
package/utils.js
CHANGED
|
@@ -1,22 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
import { globSync } from "glob";
|
|
2
|
+
import { tmpdir, platform, freemem } from "node:os";
|
|
3
|
+
import {
|
|
4
|
+
dirname,
|
|
5
|
+
sep as _sep,
|
|
6
|
+
basename,
|
|
7
|
+
join,
|
|
8
|
+
resolve,
|
|
9
|
+
delimiter as _delimiter
|
|
10
|
+
} from "node:path";
|
|
11
|
+
import {
|
|
12
|
+
existsSync,
|
|
13
|
+
readFileSync,
|
|
14
|
+
mkdtempSync,
|
|
15
|
+
rmSync,
|
|
16
|
+
copyFileSync,
|
|
17
|
+
constants,
|
|
18
|
+
writeFileSync,
|
|
19
|
+
unlinkSync,
|
|
20
|
+
chmodSync
|
|
21
|
+
} from "node:fs";
|
|
22
|
+
import got from "got";
|
|
23
|
+
import { xml2js } from "xml-js";
|
|
24
|
+
import { fileURLToPath } from "node:url";
|
|
25
|
+
let url = import.meta.url;
|
|
26
|
+
if (!url.startsWith("file://")) {
|
|
27
|
+
url = new URL(`file://${import.meta.url}`).toString();
|
|
28
|
+
}
|
|
29
|
+
const dirName = import.meta ? dirname(fileURLToPath(url)) : __dirname;
|
|
30
|
+
|
|
31
|
+
const licenseMapping = JSON.parse(
|
|
32
|
+
readFileSync(join(dirName, "data", "lic-mapping.json"))
|
|
33
|
+
);
|
|
34
|
+
const vendorAliases = JSON.parse(
|
|
35
|
+
readFileSync(join(dirName, "data", "vendor-alias.json"))
|
|
36
|
+
);
|
|
37
|
+
const spdxLicenses = JSON.parse(
|
|
38
|
+
readFileSync(join(dirName, "data", "spdx-licenses.json"))
|
|
39
|
+
);
|
|
40
|
+
const knownLicenses = JSON.parse(
|
|
41
|
+
readFileSync(join(dirName, "data", "known-licenses.json"))
|
|
42
|
+
);
|
|
43
|
+
import { load } from "cheerio";
|
|
44
|
+
import { load as _load } from "js-yaml";
|
|
45
|
+
import { spawnSync } from "node:child_process";
|
|
46
|
+
import propertiesReader from "properties-reader";
|
|
47
|
+
import { satisfies, coerce, maxSatisfying, clean, valid } from "semver";
|
|
48
|
+
import StreamZip from "node-stream-zip";
|
|
49
|
+
import { parseEDNString } from "edn-data";
|
|
50
|
+
import { PackageURL } from "packageurl-js";
|
|
51
|
+
|
|
52
|
+
const selfPJson = JSON.parse(readFileSync(join(dirName, "package.json")));
|
|
53
|
+
const _version = selfPJson.version;
|
|
54
|
+
|
|
55
|
+
// Refer to contrib/py-modules.py for a script to generate this list
|
|
56
|
+
// The script needs to be used once every few months to update this list
|
|
57
|
+
const PYTHON_STD_MODULES = JSON.parse(
|
|
58
|
+
readFileSync(join(dirName, "data", "python-stdlib.json"))
|
|
59
|
+
);
|
|
60
|
+
// Mapping between modules and package names
|
|
61
|
+
const PYPI_MODULE_PACKAGE_MAPPING = JSON.parse(
|
|
62
|
+
readFileSync(join(dirName, "data", "pypi-pkg-aliases.json"))
|
|
63
|
+
);
|
|
20
64
|
|
|
21
65
|
// Debug mode flag
|
|
22
66
|
const DEBUG_MODE =
|
|
@@ -24,14 +68,16 @@ const DEBUG_MODE =
|
|
|
24
68
|
process.env.SCAN_DEBUG_MODE === "debug" ||
|
|
25
69
|
process.env.SHIFTLEFT_LOGGING_LEVEL === "debug";
|
|
26
70
|
|
|
71
|
+
// Timeout milliseconds. Default 10 mins
|
|
72
|
+
const TIMEOUT_MS = parseInt(process.env.CDXGEN_TIMEOUT_MS) || 10 * 60 * 1000;
|
|
73
|
+
|
|
27
74
|
// Metadata cache
|
|
28
75
|
let metadata_cache = {};
|
|
29
76
|
|
|
30
77
|
// Whether test scope shall be included for java/maven projects; default, if unset shall be 'true'
|
|
31
|
-
const includeMavenTestScope =
|
|
78
|
+
export const includeMavenTestScope =
|
|
32
79
|
!process.env.CDX_MAVEN_INCLUDE_TEST_SCOPE ||
|
|
33
80
|
["true", "1"].includes(process.env.CDX_MAVEN_INCLUDE_TEST_SCOPE);
|
|
34
|
-
exports.includeMavenTestScope = includeMavenTestScope;
|
|
35
81
|
|
|
36
82
|
// Whether license information should be fetched
|
|
37
83
|
const fetchLicenses =
|
|
@@ -40,13 +86,25 @@ const fetchLicenses =
|
|
|
40
86
|
|
|
41
87
|
const MAX_LICENSE_ID_LENGTH = 100;
|
|
42
88
|
|
|
89
|
+
let PYTHON_CMD = "python";
|
|
90
|
+
if (process.env.PYTHON_CMD) {
|
|
91
|
+
PYTHON_CMD = process.env.PYTHON_CMD;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Custom user-agent for cdxgen
|
|
95
|
+
const cdxgenAgent = got.extend({
|
|
96
|
+
headers: {
|
|
97
|
+
"user-agent": `@CycloneDX/cdxgen ${_version}`
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
43
101
|
/**
|
|
44
102
|
* Method to get files matching a pattern
|
|
45
103
|
*
|
|
46
104
|
* @param {string} dirPath Root directory for search
|
|
47
105
|
* @param {string} pattern Glob pattern (eg: *.gradle)
|
|
48
106
|
*/
|
|
49
|
-
const getAllFiles = function (dirPath, pattern) {
|
|
107
|
+
export const getAllFiles = function (dirPath, pattern) {
|
|
50
108
|
try {
|
|
51
109
|
const ignoreList = [
|
|
52
110
|
"**/.hg/**",
|
|
@@ -60,9 +118,8 @@ const getAllFiles = function (dirPath, pattern) {
|
|
|
60
118
|
if (!pattern.includes("package.json")) {
|
|
61
119
|
ignoreList.push("**/node_modules/**");
|
|
62
120
|
}
|
|
63
|
-
return
|
|
121
|
+
return globSync(pattern, {
|
|
64
122
|
cwd: dirPath,
|
|
65
|
-
silent: true,
|
|
66
123
|
absolute: true,
|
|
67
124
|
nocase: true,
|
|
68
125
|
nodir: true,
|
|
@@ -78,7 +135,6 @@ const getAllFiles = function (dirPath, pattern) {
|
|
|
78
135
|
return [];
|
|
79
136
|
}
|
|
80
137
|
};
|
|
81
|
-
exports.getAllFiles = getAllFiles;
|
|
82
138
|
|
|
83
139
|
const toBase64 = (hexString) => {
|
|
84
140
|
return Buffer.from(hexString, "hex").toString("base64");
|
|
@@ -90,7 +146,7 @@ const toBase64 = (hexString) => {
|
|
|
90
146
|
* and url of the license object, otherwise, set the 'name' of the license
|
|
91
147
|
* object.
|
|
92
148
|
*/
|
|
93
|
-
function getLicenses(pkg, format = "xml") {
|
|
149
|
+
export function getLicenses(pkg, format = "xml") {
|
|
94
150
|
let license = pkg.license && (pkg.license.type || pkg.license);
|
|
95
151
|
if (license) {
|
|
96
152
|
if (!Array.isArray(license)) {
|
|
@@ -132,14 +188,13 @@ function getLicenses(pkg, format = "xml") {
|
|
|
132
188
|
}
|
|
133
189
|
return [];
|
|
134
190
|
}
|
|
135
|
-
exports.getLicenses = getLicenses;
|
|
136
191
|
|
|
137
192
|
/**
|
|
138
193
|
* Tries to find a file containing the license text based on commonly
|
|
139
194
|
* used naming and content types. If a candidate file is found, add
|
|
140
195
|
* the text to the license text object and stop.
|
|
141
196
|
*/
|
|
142
|
-
function addLicenseText(pkg, l, licenseContent, format = "xml") {
|
|
197
|
+
export function addLicenseText(pkg, l, licenseContent, format = "xml") {
|
|
143
198
|
let licenseFilenames = [
|
|
144
199
|
"LICENSE",
|
|
145
200
|
"License",
|
|
@@ -165,7 +220,7 @@ function addLicenseText(pkg, l, licenseContent, format = "xml") {
|
|
|
165
220
|
licenseContentTypes
|
|
166
221
|
)) {
|
|
167
222
|
let licenseFilepath = `${pkg.realPath}/${licenseFilename}${licenseName}${fileExtension}`;
|
|
168
|
-
if (
|
|
223
|
+
if (existsSync(licenseFilepath)) {
|
|
169
224
|
licenseContent.text = readLicenseText(
|
|
170
225
|
licenseFilepath,
|
|
171
226
|
licenseContentType,
|
|
@@ -182,8 +237,12 @@ function addLicenseText(pkg, l, licenseContent, format = "xml") {
|
|
|
182
237
|
* Read the file from the given path to the license text object and includes
|
|
183
238
|
* content-type attribute, if not default. Returns the license text object.
|
|
184
239
|
*/
|
|
185
|
-
function readLicenseText(
|
|
186
|
-
|
|
240
|
+
export function readLicenseText(
|
|
241
|
+
licenseFilepath,
|
|
242
|
+
licenseContentType,
|
|
243
|
+
format = "xml"
|
|
244
|
+
) {
|
|
245
|
+
let licenseText = readFileSync(licenseFilepath, "utf8");
|
|
187
246
|
if (licenseText) {
|
|
188
247
|
if (format === "xml") {
|
|
189
248
|
let licenseContentText = { "#cdata": licenseText };
|
|
@@ -207,7 +266,7 @@ function readLicenseText(licenseFilepath, licenseContentType, format = "xml") {
|
|
|
207
266
|
*
|
|
208
267
|
* @param {Array} pkgList Package list
|
|
209
268
|
*/
|
|
210
|
-
const getNpmMetadata = async function (pkgList) {
|
|
269
|
+
export const getNpmMetadata = async function (pkgList) {
|
|
211
270
|
const NPM_URL = "https://registry.npmjs.org/";
|
|
212
271
|
const cdepList = [];
|
|
213
272
|
for (const p of pkgList) {
|
|
@@ -224,7 +283,7 @@ const getNpmMetadata = async function (pkgList) {
|
|
|
224
283
|
if (metadata_cache[key]) {
|
|
225
284
|
body = metadata_cache[key];
|
|
226
285
|
} else {
|
|
227
|
-
const res = await
|
|
286
|
+
const res = await cdxgenAgent.get(NPM_URL + key, {
|
|
228
287
|
responseType: "json"
|
|
229
288
|
});
|
|
230
289
|
body = res.body;
|
|
@@ -248,7 +307,6 @@ const getNpmMetadata = async function (pkgList) {
|
|
|
248
307
|
}
|
|
249
308
|
return cdepList;
|
|
250
309
|
};
|
|
251
|
-
exports.getNpmMetadata = getNpmMetadata;
|
|
252
310
|
|
|
253
311
|
const _getDepPkgList = async function (
|
|
254
312
|
pkgLockFile,
|
|
@@ -349,11 +407,11 @@ const _getDepPkgList = async function (
|
|
|
349
407
|
*
|
|
350
408
|
* @param {string} pkgJsonFile package.json file
|
|
351
409
|
*/
|
|
352
|
-
const parsePkgJson = async (pkgJsonFile) => {
|
|
410
|
+
export const parsePkgJson = async (pkgJsonFile) => {
|
|
353
411
|
const pkgList = [];
|
|
354
|
-
if (
|
|
412
|
+
if (existsSync(pkgJsonFile)) {
|
|
355
413
|
try {
|
|
356
|
-
const pkgData = JSON.parse(
|
|
414
|
+
const pkgData = JSON.parse(readFileSync(pkgJsonFile, "utf8"));
|
|
357
415
|
const pkgIdentifier = parsePackageJsonName(pkgData.name);
|
|
358
416
|
pkgList.push({
|
|
359
417
|
name: pkgIdentifier.fullName || pkgData.name,
|
|
@@ -380,20 +438,19 @@ const parsePkgJson = async (pkgJsonFile) => {
|
|
|
380
438
|
}
|
|
381
439
|
return pkgList;
|
|
382
440
|
};
|
|
383
|
-
exports.parsePkgJson = parsePkgJson;
|
|
384
441
|
|
|
385
442
|
/**
|
|
386
443
|
* Parse nodejs package lock file
|
|
387
444
|
*
|
|
388
445
|
* @param {string} pkgLockFile package-lock.json file
|
|
389
446
|
*/
|
|
390
|
-
const parsePkgLock = async (pkgLockFile) => {
|
|
447
|
+
export const parsePkgLock = async (pkgLockFile) => {
|
|
391
448
|
let pkgList = [];
|
|
392
449
|
let dependenciesList = [];
|
|
393
450
|
let depKeys = {};
|
|
394
451
|
let rootPkg = {};
|
|
395
|
-
if (
|
|
396
|
-
const lockData = JSON.parse(
|
|
452
|
+
if (existsSync(pkgLockFile)) {
|
|
453
|
+
const lockData = JSON.parse(readFileSync(pkgLockFile, "utf8"));
|
|
397
454
|
rootPkg.name = lockData.name || "";
|
|
398
455
|
// lockfile v2 onwards
|
|
399
456
|
if (lockData.name && lockData.packages && lockData.packages[""]) {
|
|
@@ -405,8 +462,8 @@ const parsePkgLock = async (pkgLockFile) => {
|
|
|
405
462
|
type: "application"
|
|
406
463
|
};
|
|
407
464
|
} else if (lockData.lockfileVersion === 1) {
|
|
408
|
-
let dirName =
|
|
409
|
-
const tmpA = dirName.split(
|
|
465
|
+
let dirName = dirname(pkgLockFile);
|
|
466
|
+
const tmpA = dirName.split(_sep);
|
|
410
467
|
dirName = tmpA[tmpA.length - 1];
|
|
411
468
|
// v1 lock file
|
|
412
469
|
rootPkg = {
|
|
@@ -491,7 +548,6 @@ const parsePkgLock = async (pkgLockFile) => {
|
|
|
491
548
|
dependenciesList
|
|
492
549
|
};
|
|
493
550
|
};
|
|
494
|
-
exports.parsePkgLock = parsePkgLock;
|
|
495
551
|
|
|
496
552
|
/**
|
|
497
553
|
* Given a lock file this method would return an Object with the identiy as the key and parsed name and value
|
|
@@ -501,7 +557,7 @@ exports.parsePkgLock = parsePkgLock;
|
|
|
501
557
|
*
|
|
502
558
|
* @param {string} lockData Yarn Lockfile data
|
|
503
559
|
*/
|
|
504
|
-
const yarnLockToIdentMap = function (lockData) {
|
|
560
|
+
export const yarnLockToIdentMap = function (lockData) {
|
|
505
561
|
const identMap = {};
|
|
506
562
|
let currentIdents = [];
|
|
507
563
|
lockData.split("\n").forEach((l) => {
|
|
@@ -544,19 +600,18 @@ const yarnLockToIdentMap = function (lockData) {
|
|
|
544
600
|
});
|
|
545
601
|
return identMap;
|
|
546
602
|
};
|
|
547
|
-
exports.yarnLockToIdentMap = yarnLockToIdentMap;
|
|
548
603
|
|
|
549
604
|
/**
|
|
550
605
|
* Parse nodejs yarn lock file
|
|
551
606
|
*
|
|
552
607
|
* @param {string} yarnLockFile yarn.lock file
|
|
553
608
|
*/
|
|
554
|
-
const parseYarnLock = async function (yarnLockFile) {
|
|
609
|
+
export const parseYarnLock = async function (yarnLockFile) {
|
|
555
610
|
let pkgList = [];
|
|
556
611
|
const dependenciesList = [];
|
|
557
612
|
const depKeys = {};
|
|
558
|
-
if (
|
|
559
|
-
const lockData =
|
|
613
|
+
if (existsSync(yarnLockFile)) {
|
|
614
|
+
const lockData = readFileSync(yarnLockFile, "utf8");
|
|
560
615
|
let name = "";
|
|
561
616
|
let group = "";
|
|
562
617
|
let version = "";
|
|
@@ -700,17 +755,16 @@ const parseYarnLock = async function (yarnLockFile) {
|
|
|
700
755
|
dependenciesList
|
|
701
756
|
};
|
|
702
757
|
};
|
|
703
|
-
exports.parseYarnLock = parseYarnLock;
|
|
704
758
|
|
|
705
759
|
/**
|
|
706
760
|
* Parse nodejs shrinkwrap deps file
|
|
707
761
|
*
|
|
708
762
|
* @param {string} swFile shrinkwrap-deps.json file
|
|
709
763
|
*/
|
|
710
|
-
const parseNodeShrinkwrap = async function (swFile) {
|
|
764
|
+
export const parseNodeShrinkwrap = async function (swFile) {
|
|
711
765
|
const pkgList = [];
|
|
712
|
-
if (
|
|
713
|
-
const lockData = JSON.parse(
|
|
766
|
+
if (existsSync(swFile)) {
|
|
767
|
+
const lockData = JSON.parse(readFileSync(swFile, "utf8"));
|
|
714
768
|
const pkgKeys = Object.keys(lockData);
|
|
715
769
|
for (var k in pkgKeys) {
|
|
716
770
|
const fullName = pkgKeys[k];
|
|
@@ -760,14 +814,13 @@ const parseNodeShrinkwrap = async function (swFile) {
|
|
|
760
814
|
}
|
|
761
815
|
return pkgList;
|
|
762
816
|
};
|
|
763
|
-
exports.parseNodeShrinkwrap = parseNodeShrinkwrap;
|
|
764
817
|
|
|
765
818
|
/**
|
|
766
819
|
* Parse nodejs pnpm lock file
|
|
767
820
|
*
|
|
768
821
|
* @param {string} pnpmLock pnpm-lock.yaml file
|
|
769
822
|
*/
|
|
770
|
-
const parsePnpmLock = async function (pnpmLock, parentComponent = null) {
|
|
823
|
+
export const parsePnpmLock = async function (pnpmLock, parentComponent = null) {
|
|
771
824
|
let pkgList = [];
|
|
772
825
|
const dependenciesList = [];
|
|
773
826
|
let ppurl = "";
|
|
@@ -783,9 +836,9 @@ const parsePnpmLock = async function (pnpmLock, parentComponent = null) {
|
|
|
783
836
|
null
|
|
784
837
|
).toString();
|
|
785
838
|
}
|
|
786
|
-
if (
|
|
787
|
-
const lockData =
|
|
788
|
-
const yamlObj =
|
|
839
|
+
if (existsSync(pnpmLock)) {
|
|
840
|
+
const lockData = readFileSync(pnpmLock, "utf8");
|
|
841
|
+
const yamlObj = _load(lockData);
|
|
789
842
|
if (!yamlObj) {
|
|
790
843
|
return {};
|
|
791
844
|
}
|
|
@@ -922,18 +975,17 @@ const parsePnpmLock = async function (pnpmLock, parentComponent = null) {
|
|
|
922
975
|
dependenciesList
|
|
923
976
|
};
|
|
924
977
|
};
|
|
925
|
-
exports.parsePnpmLock = parsePnpmLock;
|
|
926
978
|
|
|
927
979
|
/**
|
|
928
980
|
* Parse bower json file
|
|
929
981
|
*
|
|
930
982
|
* @param {string} bowerJsonFile bower.json file
|
|
931
983
|
*/
|
|
932
|
-
const parseBowerJson = async (bowerJsonFile) => {
|
|
984
|
+
export const parseBowerJson = async (bowerJsonFile) => {
|
|
933
985
|
const pkgList = [];
|
|
934
|
-
if (
|
|
986
|
+
if (existsSync(bowerJsonFile)) {
|
|
935
987
|
try {
|
|
936
|
-
const pkgData = JSON.parse(
|
|
988
|
+
const pkgData = JSON.parse(readFileSync(bowerJsonFile, "utf8"));
|
|
937
989
|
const pkgIdentifier = parsePackageJsonName(pkgData.name);
|
|
938
990
|
pkgList.push({
|
|
939
991
|
name: pkgIdentifier.fullName || pkgData.name,
|
|
@@ -962,18 +1014,17 @@ const parseBowerJson = async (bowerJsonFile) => {
|
|
|
962
1014
|
}
|
|
963
1015
|
return pkgList;
|
|
964
1016
|
};
|
|
965
|
-
exports.parseBowerJson = parseBowerJson;
|
|
966
1017
|
|
|
967
1018
|
/**
|
|
968
1019
|
* Parse minified js file
|
|
969
1020
|
*
|
|
970
1021
|
* @param {string} minJsFile min.js file
|
|
971
1022
|
*/
|
|
972
|
-
const parseMinJs = async (minJsFile) => {
|
|
1023
|
+
export const parseMinJs = async (minJsFile) => {
|
|
973
1024
|
const pkgList = [];
|
|
974
|
-
if (
|
|
1025
|
+
if (existsSync(minJsFile)) {
|
|
975
1026
|
try {
|
|
976
|
-
const rawData =
|
|
1027
|
+
const rawData = readFileSync(minJsFile, { encoding: "utf-8" });
|
|
977
1028
|
const tmpA = rawData.split("\n");
|
|
978
1029
|
tmpA.forEach((l) => {
|
|
979
1030
|
if ((l.startsWith("/*!") || l.startsWith(" * ")) && l.length < 500) {
|
|
@@ -1036,17 +1087,16 @@ const parseMinJs = async (minJsFile) => {
|
|
|
1036
1087
|
}
|
|
1037
1088
|
return pkgList;
|
|
1038
1089
|
};
|
|
1039
|
-
exports.parseMinJs = parseMinJs;
|
|
1040
1090
|
|
|
1041
1091
|
/**
|
|
1042
1092
|
* Parse pom file
|
|
1043
1093
|
*
|
|
1044
1094
|
* @param {string} pom file to parse
|
|
1045
1095
|
*/
|
|
1046
|
-
const parsePom = function (pomFile) {
|
|
1096
|
+
export const parsePom = function (pomFile) {
|
|
1047
1097
|
const deps = [];
|
|
1048
|
-
const xmlData =
|
|
1049
|
-
const project =
|
|
1098
|
+
const xmlData = readFileSync(pomFile);
|
|
1099
|
+
const project = xml2js(xmlData, {
|
|
1050
1100
|
compact: true,
|
|
1051
1101
|
spaces: 4,
|
|
1052
1102
|
textKey: "_",
|
|
@@ -1084,13 +1134,12 @@ const parsePom = function (pomFile) {
|
|
|
1084
1134
|
}
|
|
1085
1135
|
return deps;
|
|
1086
1136
|
};
|
|
1087
|
-
exports.parsePom = parsePom;
|
|
1088
1137
|
|
|
1089
1138
|
/**
|
|
1090
1139
|
* Parse maven tree output
|
|
1091
1140
|
* @param {string} rawOutput Raw string output
|
|
1092
1141
|
*/
|
|
1093
|
-
const parseMavenTree = function (rawOutput) {
|
|
1142
|
+
export const parseMavenTree = function (rawOutput) {
|
|
1094
1143
|
if (!rawOutput) {
|
|
1095
1144
|
return {};
|
|
1096
1145
|
}
|
|
@@ -1176,7 +1225,6 @@ const parseMavenTree = function (rawOutput) {
|
|
|
1176
1225
|
dependenciesList
|
|
1177
1226
|
};
|
|
1178
1227
|
};
|
|
1179
|
-
exports.parseMavenTree = parseMavenTree;
|
|
1180
1228
|
|
|
1181
1229
|
/**
|
|
1182
1230
|
* Parse gradle dependencies output
|
|
@@ -1185,7 +1233,7 @@ exports.parseMavenTree = parseMavenTree;
|
|
|
1185
1233
|
* @param {string} rootProjectName Root project name
|
|
1186
1234
|
* @param {string} rootProjectVersion Root project version
|
|
1187
1235
|
*/
|
|
1188
|
-
const parseGradleDep = function (
|
|
1236
|
+
export const parseGradleDep = function (
|
|
1189
1237
|
rawOutput,
|
|
1190
1238
|
rootProjectGroup = "",
|
|
1191
1239
|
rootProjectName = "root",
|
|
@@ -1373,13 +1421,12 @@ const parseGradleDep = function (
|
|
|
1373
1421
|
}
|
|
1374
1422
|
return {};
|
|
1375
1423
|
};
|
|
1376
|
-
exports.parseGradleDep = parseGradleDep;
|
|
1377
1424
|
|
|
1378
1425
|
/**
|
|
1379
1426
|
* Parse clojure cli dependencies output
|
|
1380
1427
|
* @param {string} rawOutput Raw string output
|
|
1381
1428
|
*/
|
|
1382
|
-
const parseCljDep = function (rawOutput) {
|
|
1429
|
+
export const parseCljDep = function (rawOutput) {
|
|
1383
1430
|
if (typeof rawOutput === "string") {
|
|
1384
1431
|
const deps = [];
|
|
1385
1432
|
const keys_cache = {};
|
|
@@ -1392,11 +1439,11 @@ const parseCljDep = function (rawOutput) {
|
|
|
1392
1439
|
}
|
|
1393
1440
|
const tmpArr = l.split(" ");
|
|
1394
1441
|
if (tmpArr.length == 2) {
|
|
1395
|
-
let group =
|
|
1442
|
+
let group = dirname(tmpArr[0]);
|
|
1396
1443
|
if (group === ".") {
|
|
1397
1444
|
group = "";
|
|
1398
1445
|
}
|
|
1399
|
-
const name =
|
|
1446
|
+
const name = basename(tmpArr[0]);
|
|
1400
1447
|
const version = tmpArr[1];
|
|
1401
1448
|
const cacheKey = group + "-" + name + "-" + version;
|
|
1402
1449
|
if (!keys_cache[cacheKey]) {
|
|
@@ -1414,38 +1461,36 @@ const parseCljDep = function (rawOutput) {
|
|
|
1414
1461
|
}
|
|
1415
1462
|
return [];
|
|
1416
1463
|
};
|
|
1417
|
-
exports.parseCljDep = parseCljDep;
|
|
1418
1464
|
|
|
1419
1465
|
/**
|
|
1420
1466
|
* Parse lein dependency tree output
|
|
1421
1467
|
* @param {string} rawOutput Raw string output
|
|
1422
1468
|
*/
|
|
1423
|
-
const parseLeinDep = function (rawOutput) {
|
|
1469
|
+
export const parseLeinDep = function (rawOutput) {
|
|
1424
1470
|
if (typeof rawOutput === "string") {
|
|
1425
1471
|
const deps = [];
|
|
1426
1472
|
const keys_cache = {};
|
|
1427
1473
|
if (rawOutput.includes("{[") && !rawOutput.startsWith("{[")) {
|
|
1428
1474
|
rawOutput = "{[" + rawOutput.split("{[")[1];
|
|
1429
1475
|
}
|
|
1430
|
-
const ednData =
|
|
1476
|
+
const ednData = parseEDNString(rawOutput);
|
|
1431
1477
|
return parseLeinMap(ednData, keys_cache, deps);
|
|
1432
1478
|
}
|
|
1433
1479
|
return [];
|
|
1434
1480
|
};
|
|
1435
|
-
exports.parseLeinDep = parseLeinDep;
|
|
1436
1481
|
|
|
1437
|
-
const parseLeinMap = function (node, keys_cache, deps) {
|
|
1482
|
+
export const parseLeinMap = function (node, keys_cache, deps) {
|
|
1438
1483
|
if (node["map"]) {
|
|
1439
1484
|
for (let n of node["map"]) {
|
|
1440
1485
|
if (n.length === 2) {
|
|
1441
1486
|
const rootNode = n[0];
|
|
1442
1487
|
let psym = rootNode[0].sym;
|
|
1443
1488
|
let version = rootNode[1];
|
|
1444
|
-
let group =
|
|
1489
|
+
let group = dirname(psym);
|
|
1445
1490
|
if (group === ".") {
|
|
1446
1491
|
group = "";
|
|
1447
1492
|
}
|
|
1448
|
-
let name =
|
|
1493
|
+
let name = basename(psym);
|
|
1449
1494
|
let cacheKey = group + "-" + name + "-" + version;
|
|
1450
1495
|
if (!keys_cache[cacheKey]) {
|
|
1451
1496
|
keys_cache[cacheKey] = true;
|
|
@@ -1459,14 +1504,13 @@ const parseLeinMap = function (node, keys_cache, deps) {
|
|
|
1459
1504
|
}
|
|
1460
1505
|
return deps;
|
|
1461
1506
|
};
|
|
1462
|
-
exports.parseLeinMap = parseLeinMap;
|
|
1463
1507
|
|
|
1464
1508
|
/**
|
|
1465
1509
|
* Parse gradle projects output
|
|
1466
1510
|
*
|
|
1467
1511
|
* @param {string} rawOutput Raw string output
|
|
1468
1512
|
*/
|
|
1469
|
-
const parseGradleProjects = function (rawOutput) {
|
|
1513
|
+
export const parseGradleProjects = function (rawOutput) {
|
|
1470
1514
|
let rootProject = "root";
|
|
1471
1515
|
const projects = new Set();
|
|
1472
1516
|
if (typeof rawOutput === "string") {
|
|
@@ -1502,14 +1546,13 @@ const parseGradleProjects = function (rawOutput) {
|
|
|
1502
1546
|
projects: Array.from(projects)
|
|
1503
1547
|
};
|
|
1504
1548
|
};
|
|
1505
|
-
exports.parseGradleProjects = parseGradleProjects;
|
|
1506
1549
|
|
|
1507
1550
|
/**
|
|
1508
1551
|
* Parse gradle properties output
|
|
1509
1552
|
*
|
|
1510
1553
|
* @param {string} rawOutput Raw string output
|
|
1511
1554
|
*/
|
|
1512
|
-
const parseGradleProperties = function (rawOutput) {
|
|
1555
|
+
export const parseGradleProperties = function (rawOutput) {
|
|
1513
1556
|
let rootProject = "root";
|
|
1514
1557
|
let projects = new Set();
|
|
1515
1558
|
const metadata = { group: "", version: "latest", properties: [] };
|
|
@@ -1545,7 +1588,6 @@ const parseGradleProperties = function (rawOutput) {
|
|
|
1545
1588
|
metadata
|
|
1546
1589
|
};
|
|
1547
1590
|
};
|
|
1548
|
-
exports.parseGradleProperties = parseGradleProperties;
|
|
1549
1591
|
|
|
1550
1592
|
/**
|
|
1551
1593
|
* Execute gradle properties command and return parsed output
|
|
@@ -1554,7 +1596,7 @@ exports.parseGradleProperties = parseGradleProperties;
|
|
|
1554
1596
|
* @param {string} rootPath Root directory
|
|
1555
1597
|
* @param {string} subProject Sub project name
|
|
1556
1598
|
*/
|
|
1557
|
-
const executeGradleProperties = function (dir, rootPath, subProject) {
|
|
1599
|
+
export const executeGradleProperties = function (dir, rootPath, subProject) {
|
|
1558
1600
|
const defaultProps = {
|
|
1559
1601
|
rootProject: subProject,
|
|
1560
1602
|
projects: [],
|
|
@@ -1609,13 +1651,12 @@ const executeGradleProperties = function (dir, rootPath, subProject) {
|
|
|
1609
1651
|
}
|
|
1610
1652
|
return {};
|
|
1611
1653
|
};
|
|
1612
|
-
exports.executeGradleProperties = executeGradleProperties;
|
|
1613
1654
|
|
|
1614
1655
|
/**
|
|
1615
1656
|
* Parse bazel skyframe state output
|
|
1616
1657
|
* @param {string} rawOutput Raw string output
|
|
1617
1658
|
*/
|
|
1618
|
-
const parseBazelSkyframe = function (rawOutput) {
|
|
1659
|
+
export const parseBazelSkyframe = function (rawOutput) {
|
|
1619
1660
|
if (typeof rawOutput === "string") {
|
|
1620
1661
|
const deps = [];
|
|
1621
1662
|
const keys_cache = {};
|
|
@@ -1666,13 +1707,12 @@ const parseBazelSkyframe = function (rawOutput) {
|
|
|
1666
1707
|
}
|
|
1667
1708
|
return [];
|
|
1668
1709
|
};
|
|
1669
|
-
exports.parseBazelSkyframe = parseBazelSkyframe;
|
|
1670
1710
|
|
|
1671
1711
|
/**
|
|
1672
1712
|
* Parse bazel BUILD file
|
|
1673
1713
|
* @param {string} rawOutput Raw string output
|
|
1674
1714
|
*/
|
|
1675
|
-
const parseBazelBuild = function (rawOutput) {
|
|
1715
|
+
export const parseBazelBuild = function (rawOutput) {
|
|
1676
1716
|
if (typeof rawOutput === "string") {
|
|
1677
1717
|
const projs = [];
|
|
1678
1718
|
const tmpA = rawOutput.split("\n");
|
|
@@ -1688,12 +1728,11 @@ const parseBazelBuild = function (rawOutput) {
|
|
|
1688
1728
|
}
|
|
1689
1729
|
return [];
|
|
1690
1730
|
};
|
|
1691
|
-
exports.parseBazelBuild = parseBazelBuild;
|
|
1692
1731
|
|
|
1693
1732
|
/**
|
|
1694
1733
|
* Parse dependencies in Key:Value format
|
|
1695
1734
|
*/
|
|
1696
|
-
const parseKVDep = function (rawOutput) {
|
|
1735
|
+
export const parseKVDep = function (rawOutput) {
|
|
1697
1736
|
if (typeof rawOutput === "string") {
|
|
1698
1737
|
const deps = [];
|
|
1699
1738
|
rawOutput.split("\n").forEach((l) => {
|
|
@@ -1718,14 +1757,13 @@ const parseKVDep = function (rawOutput) {
|
|
|
1718
1757
|
}
|
|
1719
1758
|
return [];
|
|
1720
1759
|
};
|
|
1721
|
-
exports.parseKVDep = parseKVDep;
|
|
1722
1760
|
|
|
1723
1761
|
/**
|
|
1724
1762
|
* Method to find the spdx license id from name
|
|
1725
1763
|
*
|
|
1726
1764
|
* @param {string} name License full name
|
|
1727
1765
|
*/
|
|
1728
|
-
const findLicenseId = function (name) {
|
|
1766
|
+
export const findLicenseId = function (name) {
|
|
1729
1767
|
for (let l of licenseMapping) {
|
|
1730
1768
|
if (l.names.includes(name)) {
|
|
1731
1769
|
return l.exp;
|
|
@@ -1735,14 +1773,13 @@ const findLicenseId = function (name) {
|
|
|
1735
1773
|
? guessLicenseId(name)
|
|
1736
1774
|
: name;
|
|
1737
1775
|
};
|
|
1738
|
-
exports.findLicenseId = findLicenseId;
|
|
1739
1776
|
|
|
1740
1777
|
/**
|
|
1741
1778
|
* Method to guess the spdx license id from license contents
|
|
1742
1779
|
*
|
|
1743
1780
|
* @param {string} name License file contents
|
|
1744
1781
|
*/
|
|
1745
|
-
const guessLicenseId = function (content) {
|
|
1782
|
+
export const guessLicenseId = function (content) {
|
|
1746
1783
|
content = content.replace(/\n/g, " ");
|
|
1747
1784
|
for (let l of licenseMapping) {
|
|
1748
1785
|
for (let j in l.names) {
|
|
@@ -1753,14 +1790,13 @@ const guessLicenseId = function (content) {
|
|
|
1753
1790
|
}
|
|
1754
1791
|
return undefined;
|
|
1755
1792
|
};
|
|
1756
|
-
exports.guessLicenseId = guessLicenseId;
|
|
1757
1793
|
|
|
1758
1794
|
/**
|
|
1759
1795
|
* Method to retrieve metadata for maven packages by querying maven central
|
|
1760
1796
|
*
|
|
1761
1797
|
* @param {Array} pkgList Package list
|
|
1762
1798
|
*/
|
|
1763
|
-
const getMvnMetadata = async function (pkgList) {
|
|
1799
|
+
export const getMvnMetadata = async function (pkgList) {
|
|
1764
1800
|
const MAVEN_CENTRAL_URL = "https://repo1.maven.org/maven2/";
|
|
1765
1801
|
const ANDROID_MAVEN = "https://maven.google.com/";
|
|
1766
1802
|
const cdepList = [];
|
|
@@ -1803,8 +1839,8 @@ const getMvnMetadata = async function (pkgList) {
|
|
|
1803
1839
|
if (DEBUG_MODE) {
|
|
1804
1840
|
console.log(`Querying ${fullUrl}`);
|
|
1805
1841
|
}
|
|
1806
|
-
const res = await
|
|
1807
|
-
const bodyJson =
|
|
1842
|
+
const res = await cdxgenAgent.get(fullUrl);
|
|
1843
|
+
const bodyJson = xml2js(res.body, {
|
|
1808
1844
|
compact: true,
|
|
1809
1845
|
spaces: 4,
|
|
1810
1846
|
textKey: "_",
|
|
@@ -1845,14 +1881,13 @@ const getMvnMetadata = async function (pkgList) {
|
|
|
1845
1881
|
}
|
|
1846
1882
|
return cdepList;
|
|
1847
1883
|
};
|
|
1848
|
-
exports.getMvnMetadata = getMvnMetadata;
|
|
1849
1884
|
|
|
1850
1885
|
/**
|
|
1851
1886
|
* Method to parse python requires_dist attribute found in pypi setup.py
|
|
1852
1887
|
*
|
|
1853
1888
|
* @param requires_dist string
|
|
1854
1889
|
*/
|
|
1855
|
-
const parsePyRequiresDist = function (dist_string) {
|
|
1890
|
+
export const parsePyRequiresDist = function (dist_string) {
|
|
1856
1891
|
if (!dist_string) {
|
|
1857
1892
|
return undefined;
|
|
1858
1893
|
}
|
|
@@ -1873,7 +1908,25 @@ const parsePyRequiresDist = function (dist_string) {
|
|
|
1873
1908
|
version
|
|
1874
1909
|
};
|
|
1875
1910
|
};
|
|
1876
|
-
|
|
1911
|
+
|
|
1912
|
+
/**
|
|
1913
|
+
* Method to mimic pip version solver using node-semver
|
|
1914
|
+
*
|
|
1915
|
+
* @param {Array} versionsList List of version numbers available
|
|
1916
|
+
* @param {*} versionSpecifiers pip version specifier
|
|
1917
|
+
*/
|
|
1918
|
+
export const guessPypiMatchingVersion = (versionsList, versionSpecifiers) => {
|
|
1919
|
+
versionSpecifiers = versionSpecifiers.replace(/,/g, " ").split(";")[0];
|
|
1920
|
+
// Iterate in the reverse order
|
|
1921
|
+
for (let i = versionsList.length - 1; i > 0; i--) {
|
|
1922
|
+
let rv = versionsList[i];
|
|
1923
|
+
if (satisfies(coerce(rv), versionSpecifiers, true)) {
|
|
1924
|
+
return rv;
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
// Let's try to clean and have another go
|
|
1928
|
+
return maxSatisfying(versionsList, clean(versionSpecifiers, { loose: true }));
|
|
1929
|
+
};
|
|
1877
1930
|
|
|
1878
1931
|
/**
|
|
1879
1932
|
* Method to retrieve metadata for python packages by querying pypi
|
|
@@ -1881,7 +1934,7 @@ exports.parsePyRequiresDist = parsePyRequiresDist;
|
|
|
1881
1934
|
* @param {Array} pkgList Package list
|
|
1882
1935
|
* @param {Boolean} fetchDepsInfo Fetch dependencies info from pypi
|
|
1883
1936
|
*/
|
|
1884
|
-
const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
1937
|
+
export const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
1885
1938
|
if (!fetchLicenses && !fetchDepsInfo) {
|
|
1886
1939
|
return pkgList;
|
|
1887
1940
|
}
|
|
@@ -1892,7 +1945,8 @@ const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
|
1892
1945
|
continue;
|
|
1893
1946
|
}
|
|
1894
1947
|
try {
|
|
1895
|
-
|
|
1948
|
+
// If the package name has a url or already includes license and version skip it
|
|
1949
|
+
if (p.name.includes("https") || (p.license && p.version)) {
|
|
1896
1950
|
cdepList.push(p);
|
|
1897
1951
|
continue;
|
|
1898
1952
|
}
|
|
@@ -1900,10 +1954,22 @@ const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
|
1900
1954
|
if (p.name.includes("[")) {
|
|
1901
1955
|
p.name = p.name.split("[")[0];
|
|
1902
1956
|
}
|
|
1903
|
-
const res = await
|
|
1957
|
+
const res = await cdxgenAgent.get(PYPI_URL + p.name + "/json", {
|
|
1904
1958
|
responseType: "json"
|
|
1905
1959
|
});
|
|
1906
1960
|
const body = res.body;
|
|
1961
|
+
if (body.info.author && body.info.author.trim() !== "") {
|
|
1962
|
+
if (body.info.author_email && body.info.author_email.trim() !== "") {
|
|
1963
|
+
p.author = `${body.info.author.trim()} <${body.info.author_email.trim()}>`;
|
|
1964
|
+
} else {
|
|
1965
|
+
p.author = body.info.author.trim();
|
|
1966
|
+
}
|
|
1967
|
+
} else if (
|
|
1968
|
+
body.info.author_email &&
|
|
1969
|
+
body.info.author_email.trim() !== ""
|
|
1970
|
+
) {
|
|
1971
|
+
p.author = body.info.author_email.trim();
|
|
1972
|
+
}
|
|
1907
1973
|
p.description = body.info.summary;
|
|
1908
1974
|
p.license = findLicenseId(body.info.license);
|
|
1909
1975
|
if (body.info.home_page) {
|
|
@@ -1914,13 +1980,43 @@ const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
|
1914
1980
|
}
|
|
1915
1981
|
}
|
|
1916
1982
|
// Use the latest version if none specified
|
|
1917
|
-
if (
|
|
1918
|
-
|
|
1919
|
-
p.
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1983
|
+
if (!p.version || !p.version.trim().length) {
|
|
1984
|
+
let versionSpecifiers = undefined;
|
|
1985
|
+
if (p.properties && p.properties.length) {
|
|
1986
|
+
for (const pprop of p.properties) {
|
|
1987
|
+
if (pprop.name === "cdx:pypi:versionSpecifiers") {
|
|
1988
|
+
versionSpecifiers = pprop.value;
|
|
1989
|
+
break;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
} else if (
|
|
1993
|
+
p.version &&
|
|
1994
|
+
(p.version.includes("*") ||
|
|
1995
|
+
p.version.includes("<") ||
|
|
1996
|
+
p.version.includes(">") ||
|
|
1997
|
+
p.version.includes("!"))
|
|
1998
|
+
) {
|
|
1999
|
+
versionSpecifiers = p.version;
|
|
2000
|
+
}
|
|
2001
|
+
if (versionSpecifiers) {
|
|
2002
|
+
p.version = guessPypiMatchingVersion(
|
|
2003
|
+
Object.keys(body.releases || {}),
|
|
2004
|
+
versionSpecifiers
|
|
2005
|
+
);
|
|
2006
|
+
}
|
|
2007
|
+
// If we have reached here, it means we have not solved the version
|
|
2008
|
+
// So assume latest
|
|
2009
|
+
if (!p.version) {
|
|
2010
|
+
p.version = body.info.version;
|
|
2011
|
+
}
|
|
2012
|
+
} else if (p.version !== body.info.version) {
|
|
2013
|
+
if (!p.properties) {
|
|
2014
|
+
p.properties = [];
|
|
2015
|
+
}
|
|
2016
|
+
p.properties.push({
|
|
2017
|
+
name: "cdx:pypi:latest_version",
|
|
2018
|
+
value: body.info.version
|
|
2019
|
+
});
|
|
1924
2020
|
}
|
|
1925
2021
|
if (body.releases && body.releases[p.version]) {
|
|
1926
2022
|
const digest = body.releases[p.version][0].digests;
|
|
@@ -1932,22 +2028,44 @@ const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
|
1932
2028
|
}
|
|
1933
2029
|
cdepList.push(p);
|
|
1934
2030
|
} catch (err) {
|
|
1935
|
-
cdepList.push(p);
|
|
1936
2031
|
if (DEBUG_MODE) {
|
|
1937
|
-
console.error(p.name,
|
|
2032
|
+
console.error(p.name, "is not found on PyPI.");
|
|
2033
|
+
console.log(
|
|
2034
|
+
"If this package is available from PyPI or a registry, its name might be different to the module name. Raise a ticket at https://github.com/CycloneDX/cdxgen/issues so that this could be added to the mapping file pypi-pkg-aliases.json"
|
|
2035
|
+
);
|
|
2036
|
+
console.log(
|
|
2037
|
+
"Alternatively, if this is a package that gets installed directly in your environment and offers a python binding, then track such packages manually."
|
|
2038
|
+
);
|
|
1938
2039
|
}
|
|
2040
|
+
if (!p.version) {
|
|
2041
|
+
if (DEBUG_MODE) {
|
|
2042
|
+
console.log(
|
|
2043
|
+
`Assuming the version as latest for the package ${p.name}`
|
|
2044
|
+
);
|
|
2045
|
+
}
|
|
2046
|
+
p.version = "latest";
|
|
2047
|
+
}
|
|
2048
|
+
// Add a property to let the downstream tools know about this assumption
|
|
2049
|
+
// FIXME: Do this correctly with 1.5
|
|
2050
|
+
if (!p.properties) {
|
|
2051
|
+
p.properties = [];
|
|
2052
|
+
}
|
|
2053
|
+
p.properties.push({
|
|
2054
|
+
name: "cdx:pypi:pedigree",
|
|
2055
|
+
value: "unknown"
|
|
2056
|
+
});
|
|
2057
|
+
cdepList.push(p);
|
|
1939
2058
|
}
|
|
1940
2059
|
}
|
|
1941
2060
|
return cdepList;
|
|
1942
2061
|
};
|
|
1943
|
-
exports.getPyMetadata = getPyMetadata;
|
|
1944
2062
|
|
|
1945
2063
|
/**
|
|
1946
2064
|
* Method to parse bdist_wheel metadata
|
|
1947
2065
|
*
|
|
1948
2066
|
* @param {Object} mData bdist_wheel metadata
|
|
1949
2067
|
*/
|
|
1950
|
-
const parseBdistMetadata = function (mData) {
|
|
2068
|
+
export const parseBdistMetadata = function (mData) {
|
|
1951
2069
|
const pkg = {};
|
|
1952
2070
|
mData.split("\n").forEach((l) => {
|
|
1953
2071
|
if (l.indexOf("Name: ") > -1) {
|
|
@@ -1966,14 +2084,13 @@ const parseBdistMetadata = function (mData) {
|
|
|
1966
2084
|
});
|
|
1967
2085
|
return [pkg];
|
|
1968
2086
|
};
|
|
1969
|
-
exports.parseBdistMetadata = parseBdistMetadata;
|
|
1970
2087
|
|
|
1971
2088
|
/**
|
|
1972
2089
|
* Method to parse pipfile.lock data
|
|
1973
2090
|
*
|
|
1974
2091
|
* @param {Object} lockData JSON data from Pipfile.lock
|
|
1975
2092
|
*/
|
|
1976
|
-
const parsePiplockData = async function (lockData) {
|
|
2093
|
+
export const parsePiplockData = async function (lockData) {
|
|
1977
2094
|
const pkgList = [];
|
|
1978
2095
|
Object.keys(lockData)
|
|
1979
2096
|
.filter((i) => i !== "_meta")
|
|
@@ -1989,14 +2106,13 @@ const parsePiplockData = async function (lockData) {
|
|
|
1989
2106
|
});
|
|
1990
2107
|
return await getPyMetadata(pkgList, false);
|
|
1991
2108
|
};
|
|
1992
|
-
exports.parsePiplockData = parsePiplockData;
|
|
1993
2109
|
|
|
1994
2110
|
/**
|
|
1995
2111
|
* Method to parse poetry.lock data
|
|
1996
2112
|
*
|
|
1997
2113
|
* @param {Object} lockData JSON data from poetry.lock
|
|
1998
2114
|
*/
|
|
1999
|
-
const parsePoetrylockData = async function (lockData) {
|
|
2115
|
+
export const parsePoetrylockData = async function (lockData) {
|
|
2000
2116
|
const pkgList = [];
|
|
2001
2117
|
let pkg = null;
|
|
2002
2118
|
if (!lockData) {
|
|
@@ -2031,19 +2147,21 @@ const parsePoetrylockData = async function (lockData) {
|
|
|
2031
2147
|
});
|
|
2032
2148
|
return await getPyMetadata(pkgList, false);
|
|
2033
2149
|
};
|
|
2034
|
-
exports.parsePoetrylockData = parsePoetrylockData;
|
|
2035
2150
|
|
|
2036
2151
|
/**
|
|
2037
2152
|
* Method to parse requirements.txt data
|
|
2038
2153
|
*
|
|
2039
2154
|
* @param {Object} reqData Requirements.txt data
|
|
2040
|
-
* @param {Boolean}
|
|
2155
|
+
* @param {Boolean} fetchDepsInfo Fetch dependencies info from pypi
|
|
2041
2156
|
*/
|
|
2042
|
-
async function parseReqFile(reqData,
|
|
2157
|
+
export async function parseReqFile(reqData, fetchDepsInfo) {
|
|
2043
2158
|
const pkgList = [];
|
|
2044
2159
|
let compScope = undefined;
|
|
2045
2160
|
reqData.split("\n").forEach((l) => {
|
|
2046
2161
|
l = l.trim();
|
|
2162
|
+
if (l.startsWith("Skipping line") || l.startsWith("(add")) {
|
|
2163
|
+
return;
|
|
2164
|
+
}
|
|
2047
2165
|
if (l.includes("# Basic requirements")) {
|
|
2048
2166
|
compScope = "required";
|
|
2049
2167
|
} else if (l.includes("added by pip freeze")) {
|
|
@@ -2066,36 +2184,53 @@ async function parseReqFile(reqData, fetchIndirectDeps) {
|
|
|
2066
2184
|
versionStr = null;
|
|
2067
2185
|
}
|
|
2068
2186
|
if (!tmpA[0].includes("=") && !tmpA[0].trim().includes(" ")) {
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2187
|
+
let name = tmpA[0].trim().replace(";", "");
|
|
2188
|
+
if (!PYTHON_STD_MODULES.includes(name)) {
|
|
2189
|
+
pkgList.push({
|
|
2190
|
+
name,
|
|
2191
|
+
version: versionStr,
|
|
2192
|
+
scope: compScope
|
|
2193
|
+
});
|
|
2194
|
+
}
|
|
2074
2195
|
}
|
|
2075
2196
|
} else if (l.includes("<") && l.includes(">")) {
|
|
2076
2197
|
let tmpA = l.split(">");
|
|
2077
2198
|
let name = tmpA[0].trim().replace(";", "");
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2199
|
+
const versionSpecifiers = l.replace(name, "");
|
|
2200
|
+
if (!PYTHON_STD_MODULES.includes(name)) {
|
|
2201
|
+
pkgList.push({
|
|
2202
|
+
name,
|
|
2203
|
+
version: undefined,
|
|
2204
|
+
scope: compScope,
|
|
2205
|
+
properties: [
|
|
2206
|
+
{
|
|
2207
|
+
name: "cdx:pypi:versionSpecifiers",
|
|
2208
|
+
value: versionSpecifiers
|
|
2209
|
+
}
|
|
2210
|
+
]
|
|
2211
|
+
});
|
|
2082
2212
|
}
|
|
2083
|
-
pkgList.push({
|
|
2084
|
-
name,
|
|
2085
|
-
version,
|
|
2086
|
-
scope: compScope
|
|
2087
|
-
});
|
|
2088
2213
|
} else if (/[>|[|@]/.test(l)) {
|
|
2089
2214
|
let tmpA = l.split(/(>|\[|@)/);
|
|
2090
2215
|
if (tmpA.includes("#")) {
|
|
2091
2216
|
tmpA = tmpA.split("#")[0];
|
|
2092
2217
|
}
|
|
2093
2218
|
if (!tmpA[0].trim().includes(" ")) {
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2219
|
+
let name = tmpA[0].trim().replace(";", "");
|
|
2220
|
+
const versionSpecifiers = l.replace(name, "");
|
|
2221
|
+
if (!PYTHON_STD_MODULES.includes(name)) {
|
|
2222
|
+
pkgList.push({
|
|
2223
|
+
name,
|
|
2224
|
+
version: undefined,
|
|
2225
|
+
scope: compScope,
|
|
2226
|
+
properties: [
|
|
2227
|
+
{
|
|
2228
|
+
name: "cdx:pypi:versionSpecifiers",
|
|
2229
|
+
value: versionSpecifiers
|
|
2230
|
+
}
|
|
2231
|
+
]
|
|
2232
|
+
});
|
|
2233
|
+
}
|
|
2099
2234
|
}
|
|
2100
2235
|
} else if (l) {
|
|
2101
2236
|
if (l.includes("#")) {
|
|
@@ -2104,31 +2239,99 @@ async function parseReqFile(reqData, fetchIndirectDeps) {
|
|
|
2104
2239
|
l = l.trim();
|
|
2105
2240
|
let tmpA = l.split(/(<|>)/);
|
|
2106
2241
|
if (tmpA && tmpA.length === 3) {
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2242
|
+
let name = tmpA[0].trim().replace(";", "");
|
|
2243
|
+
const versionSpecifiers = l.replace(name, "");
|
|
2244
|
+
if (!PYTHON_STD_MODULES.includes(name)) {
|
|
2245
|
+
pkgList.push({
|
|
2246
|
+
name,
|
|
2247
|
+
version: undefined,
|
|
2248
|
+
scope: compScope,
|
|
2249
|
+
properties: [
|
|
2250
|
+
{
|
|
2251
|
+
name: "cdx:pypi:versionSpecifiers",
|
|
2252
|
+
value: versionSpecifiers
|
|
2253
|
+
}
|
|
2254
|
+
]
|
|
2255
|
+
});
|
|
2256
|
+
}
|
|
2112
2257
|
} else if (!l.includes(" ")) {
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2258
|
+
let name = l.replace(";", "");
|
|
2259
|
+
const versionSpecifiers = l.replace(name, "");
|
|
2260
|
+
if (!PYTHON_STD_MODULES.includes(name)) {
|
|
2261
|
+
pkgList.push({
|
|
2262
|
+
name,
|
|
2263
|
+
version: null,
|
|
2264
|
+
scope: compScope,
|
|
2265
|
+
properties: [
|
|
2266
|
+
{
|
|
2267
|
+
name: "cdx:pypi:versionSpecifiers",
|
|
2268
|
+
value: versionSpecifiers
|
|
2269
|
+
}
|
|
2270
|
+
]
|
|
2271
|
+
});
|
|
2272
|
+
}
|
|
2118
2273
|
}
|
|
2119
2274
|
}
|
|
2120
2275
|
}
|
|
2121
2276
|
});
|
|
2122
|
-
return await getPyMetadata(pkgList,
|
|
2277
|
+
return await getPyMetadata(pkgList, fetchDepsInfo);
|
|
2123
2278
|
}
|
|
2124
|
-
|
|
2279
|
+
|
|
2280
|
+
/**
|
|
2281
|
+
* Method to find python modules by parsing the imports and then checking with PyPI to obtain the latest version
|
|
2282
|
+
*
|
|
2283
|
+
* @param {string} src directory
|
|
2284
|
+
* @param {Array} epkgList Existing package list
|
|
2285
|
+
* @returns List of packages
|
|
2286
|
+
*/
|
|
2287
|
+
export const getPyModules = async (src, epkgList) => {
|
|
2288
|
+
const allImports = {};
|
|
2289
|
+
const modList = findAppModules(src, "python");
|
|
2290
|
+
const pyDefaultModules = new Set(PYTHON_STD_MODULES);
|
|
2291
|
+
const filteredModList = modList.filter(
|
|
2292
|
+
(x) =>
|
|
2293
|
+
!pyDefaultModules.has(x.name.toLowerCase()) &&
|
|
2294
|
+
!x.name.startsWith("_") &&
|
|
2295
|
+
!x.name.startsWith(".")
|
|
2296
|
+
);
|
|
2297
|
+
let pkgList = filteredModList.map((p) => {
|
|
2298
|
+
return {
|
|
2299
|
+
name:
|
|
2300
|
+
PYPI_MODULE_PACKAGE_MAPPING[p.name.toLowerCase()] ||
|
|
2301
|
+
p.name.replace(/_/g, "-"),
|
|
2302
|
+
version: p.version && p.version.trim().length ? p.version : undefined,
|
|
2303
|
+
scope: "required",
|
|
2304
|
+
properties: [
|
|
2305
|
+
{
|
|
2306
|
+
name: "cdx:pypi:versionSpecifiers",
|
|
2307
|
+
value: p.versionSpecifiers
|
|
2308
|
+
}
|
|
2309
|
+
]
|
|
2310
|
+
};
|
|
2311
|
+
});
|
|
2312
|
+
pkgList = pkgList.filter(
|
|
2313
|
+
(obj, index) => pkgList.findIndex((i) => i.name === obj.name) === index
|
|
2314
|
+
);
|
|
2315
|
+
// Populate the imports list
|
|
2316
|
+
if (pkgList && pkgList.length) {
|
|
2317
|
+
pkgList.forEach((p) => {
|
|
2318
|
+
allImports[p.name] = true;
|
|
2319
|
+
});
|
|
2320
|
+
}
|
|
2321
|
+
if (epkgList && epkgList.length) {
|
|
2322
|
+
const pkgMaps = epkgList.map((p) => p.name);
|
|
2323
|
+
pkgList = pkgList.filter((p) => !pkgMaps.includes(p.name));
|
|
2324
|
+
}
|
|
2325
|
+
pkgList = await getPyMetadata(pkgList, true);
|
|
2326
|
+
return { allImports, pkgList };
|
|
2327
|
+
};
|
|
2125
2328
|
|
|
2126
2329
|
/**
|
|
2127
2330
|
* Method to parse setup.py data
|
|
2128
2331
|
*
|
|
2129
2332
|
* @param {Object} setupPyData Contents of setup.py
|
|
2130
2333
|
*/
|
|
2131
|
-
const parseSetupPyFile = async function (setupPyData) {
|
|
2334
|
+
export const parseSetupPyFile = async function (setupPyData) {
|
|
2132
2335
|
let lines = [];
|
|
2133
2336
|
let requires_found = false;
|
|
2134
2337
|
let should_break = false;
|
|
@@ -2150,13 +2353,12 @@ const parseSetupPyFile = async function (setupPyData) {
|
|
|
2150
2353
|
});
|
|
2151
2354
|
return await parseReqFile(lines.join("\n"), false);
|
|
2152
2355
|
};
|
|
2153
|
-
exports.parseSetupPyFile = parseSetupPyFile;
|
|
2154
2356
|
|
|
2155
2357
|
/**
|
|
2156
2358
|
* Method to construct a github url for the given repo
|
|
2157
2359
|
* @param {Object} repoMetadata Repo metadata with group and name
|
|
2158
2360
|
*/
|
|
2159
|
-
const toGitHubUrl = function (repoMetadata) {
|
|
2361
|
+
export const toGitHubUrl = function (repoMetadata) {
|
|
2160
2362
|
if (repoMetadata) {
|
|
2161
2363
|
const group = repoMetadata.group;
|
|
2162
2364
|
const name = repoMetadata.name;
|
|
@@ -2170,7 +2372,6 @@ const toGitHubUrl = function (repoMetadata) {
|
|
|
2170
2372
|
return undefined;
|
|
2171
2373
|
}
|
|
2172
2374
|
};
|
|
2173
|
-
exports.toGitHubUrl = toGitHubUrl;
|
|
2174
2375
|
|
|
2175
2376
|
/**
|
|
2176
2377
|
* Method to retrieve repo license by querying github api
|
|
@@ -2179,7 +2380,7 @@ exports.toGitHubUrl = toGitHubUrl;
|
|
|
2179
2380
|
* @param {Object} repoMetadata Object containing group and package name strings
|
|
2180
2381
|
* @return {String} SPDX license id
|
|
2181
2382
|
*/
|
|
2182
|
-
const getRepoLicense = async function (repoUrl, repoMetadata) {
|
|
2383
|
+
export const getRepoLicense = async function (repoUrl, repoMetadata) {
|
|
2183
2384
|
if (!repoUrl) {
|
|
2184
2385
|
repoUrl = toGitHubUrl(repoMetadata);
|
|
2185
2386
|
}
|
|
@@ -2195,7 +2396,7 @@ const getRepoLicense = async function (repoUrl, repoMetadata) {
|
|
|
2195
2396
|
headers["Authorization"] = "Bearer " + process.env.GITHUB_TOKEN;
|
|
2196
2397
|
}
|
|
2197
2398
|
try {
|
|
2198
|
-
const res = await
|
|
2399
|
+
const res = await cdxgenAgent.get(apiUrl, {
|
|
2199
2400
|
responseType: "json",
|
|
2200
2401
|
headers: headers
|
|
2201
2402
|
});
|
|
@@ -2242,14 +2443,13 @@ const getRepoLicense = async function (repoUrl, repoMetadata) {
|
|
|
2242
2443
|
}
|
|
2243
2444
|
return undefined;
|
|
2244
2445
|
};
|
|
2245
|
-
exports.getRepoLicense = getRepoLicense;
|
|
2246
2446
|
|
|
2247
2447
|
/**
|
|
2248
2448
|
* Method to get go pkg license from go.dev site.
|
|
2249
2449
|
*
|
|
2250
2450
|
* @param {Object} repoMetadata Repo metadata
|
|
2251
2451
|
*/
|
|
2252
|
-
const getGoPkgLicense = async function (repoMetadata) {
|
|
2452
|
+
export const getGoPkgLicense = async function (repoMetadata) {
|
|
2253
2453
|
const group = repoMetadata.group;
|
|
2254
2454
|
const name = repoMetadata.name;
|
|
2255
2455
|
let pkgUrlPrefix = "https://pkg.go.dev/";
|
|
@@ -2262,9 +2462,9 @@ const getGoPkgLicense = async function (repoMetadata) {
|
|
|
2262
2462
|
return metadata_cache[pkgUrlPrefix];
|
|
2263
2463
|
}
|
|
2264
2464
|
try {
|
|
2265
|
-
const res = await
|
|
2465
|
+
const res = await cdxgenAgent.get(pkgUrlPrefix);
|
|
2266
2466
|
if (res && res.body) {
|
|
2267
|
-
const $ =
|
|
2467
|
+
const $ = load(res.body);
|
|
2268
2468
|
let licenses = $("#LICENSE > h2").text().trim();
|
|
2269
2469
|
if (licenses === "") {
|
|
2270
2470
|
licenses = $("section.License > h2").text().trim();
|
|
@@ -2289,9 +2489,8 @@ const getGoPkgLicense = async function (repoMetadata) {
|
|
|
2289
2489
|
}
|
|
2290
2490
|
return undefined;
|
|
2291
2491
|
};
|
|
2292
|
-
exports.getGoPkgLicense = getGoPkgLicense;
|
|
2293
2492
|
|
|
2294
|
-
const getGoPkgComponent = async function (group, name, version, hash) {
|
|
2493
|
+
export const getGoPkgComponent = async function (group, name, version, hash) {
|
|
2295
2494
|
let pkg = {};
|
|
2296
2495
|
let license = undefined;
|
|
2297
2496
|
if (fetchLicenses) {
|
|
@@ -2314,9 +2513,8 @@ const getGoPkgComponent = async function (group, name, version, hash) {
|
|
|
2314
2513
|
};
|
|
2315
2514
|
return pkg;
|
|
2316
2515
|
};
|
|
2317
|
-
exports.getGoPkgComponent = getGoPkgComponent;
|
|
2318
2516
|
|
|
2319
|
-
const parseGoModData = async function (goModData, gosumMap) {
|
|
2517
|
+
export const parseGoModData = async function (goModData, gosumMap) {
|
|
2320
2518
|
const pkgComponentsList = [];
|
|
2321
2519
|
let isModReplacement = false;
|
|
2322
2520
|
|
|
@@ -2380,7 +2578,6 @@ const parseGoModData = async function (goModData, gosumMap) {
|
|
|
2380
2578
|
metadata_cache = {};
|
|
2381
2579
|
return pkgComponentsList;
|
|
2382
2580
|
};
|
|
2383
|
-
exports.parseGoModData = parseGoModData;
|
|
2384
2581
|
|
|
2385
2582
|
/**
|
|
2386
2583
|
* Parse go list output
|
|
@@ -2388,7 +2585,7 @@ exports.parseGoModData = parseGoModData;
|
|
|
2388
2585
|
* @param {string} rawOutput Output from go list invocation
|
|
2389
2586
|
* @returns List of packages
|
|
2390
2587
|
*/
|
|
2391
|
-
const parseGoListDep = async function (rawOutput, gosumMap) {
|
|
2588
|
+
export const parseGoListDep = async function (rawOutput, gosumMap) {
|
|
2392
2589
|
if (typeof rawOutput === "string") {
|
|
2393
2590
|
const deps = [];
|
|
2394
2591
|
const keys_cache = {};
|
|
@@ -2432,14 +2629,13 @@ const parseGoListDep = async function (rawOutput, gosumMap) {
|
|
|
2432
2629
|
}
|
|
2433
2630
|
return [];
|
|
2434
2631
|
};
|
|
2435
|
-
exports.parseGoListDep = parseGoListDep;
|
|
2436
2632
|
|
|
2437
2633
|
/**
|
|
2438
2634
|
* Parse go mod why output
|
|
2439
2635
|
* @param {string} rawOutput Output from go mod why
|
|
2440
2636
|
* @returns package name or none
|
|
2441
2637
|
*/
|
|
2442
|
-
const parseGoModWhy = function (rawOutput) {
|
|
2638
|
+
export const parseGoModWhy = function (rawOutput) {
|
|
2443
2639
|
if (typeof rawOutput === "string") {
|
|
2444
2640
|
let pkg_name = undefined;
|
|
2445
2641
|
const tmpA = rawOutput.split("\n");
|
|
@@ -2452,9 +2648,8 @@ const parseGoModWhy = function (rawOutput) {
|
|
|
2452
2648
|
}
|
|
2453
2649
|
return undefined;
|
|
2454
2650
|
};
|
|
2455
|
-
exports.parseGoModWhy = parseGoModWhy;
|
|
2456
2651
|
|
|
2457
|
-
const parseGosumData = async function (gosumData) {
|
|
2652
|
+
export const parseGosumData = async function (gosumData) {
|
|
2458
2653
|
const pkgList = [];
|
|
2459
2654
|
if (!gosumData) {
|
|
2460
2655
|
return pkgList;
|
|
@@ -2490,9 +2685,8 @@ const parseGosumData = async function (gosumData) {
|
|
|
2490
2685
|
}
|
|
2491
2686
|
return pkgList;
|
|
2492
2687
|
};
|
|
2493
|
-
exports.parseGosumData = parseGosumData;
|
|
2494
2688
|
|
|
2495
|
-
const parseGopkgData = async function (gopkgData) {
|
|
2689
|
+
export const parseGopkgData = async function (gopkgData) {
|
|
2496
2690
|
const pkgList = [];
|
|
2497
2691
|
if (!gopkgData) {
|
|
2498
2692
|
return pkgList;
|
|
@@ -2540,9 +2734,8 @@ const parseGopkgData = async function (gopkgData) {
|
|
|
2540
2734
|
}
|
|
2541
2735
|
return pkgList;
|
|
2542
2736
|
};
|
|
2543
|
-
exports.parseGopkgData = parseGopkgData;
|
|
2544
2737
|
|
|
2545
|
-
const parseGoVersionData = async function (buildInfoData) {
|
|
2738
|
+
export const parseGoVersionData = async function (buildInfoData) {
|
|
2546
2739
|
const pkgList = [];
|
|
2547
2740
|
if (!buildInfoData) {
|
|
2548
2741
|
return pkgList;
|
|
@@ -2567,14 +2760,13 @@ const parseGoVersionData = async function (buildInfoData) {
|
|
|
2567
2760
|
}
|
|
2568
2761
|
return pkgList;
|
|
2569
2762
|
};
|
|
2570
|
-
exports.parseGoVersionData = parseGoVersionData;
|
|
2571
2763
|
|
|
2572
2764
|
/**
|
|
2573
2765
|
* Method to query rubygems api for gems details
|
|
2574
2766
|
*
|
|
2575
2767
|
* @param {*} pkgList List of packages with metadata
|
|
2576
2768
|
*/
|
|
2577
|
-
const getRubyGemsMetadata = async function (pkgList) {
|
|
2769
|
+
export const getRubyGemsMetadata = async function (pkgList) {
|
|
2578
2770
|
const RUBYGEMS_URL = "https://rubygems.org/api/v1/versions/";
|
|
2579
2771
|
const rdepList = [];
|
|
2580
2772
|
for (const p of pkgList) {
|
|
@@ -2582,7 +2774,7 @@ const getRubyGemsMetadata = async function (pkgList) {
|
|
|
2582
2774
|
if (DEBUG_MODE) {
|
|
2583
2775
|
console.log(`Querying rubygems.org for ${p.name}`);
|
|
2584
2776
|
}
|
|
2585
|
-
const res = await
|
|
2777
|
+
const res = await cdxgenAgent.get(RUBYGEMS_URL + p.name + ".json", {
|
|
2586
2778
|
responseType: "json"
|
|
2587
2779
|
});
|
|
2588
2780
|
let body = res.body;
|
|
@@ -2618,14 +2810,13 @@ const getRubyGemsMetadata = async function (pkgList) {
|
|
|
2618
2810
|
}
|
|
2619
2811
|
return rdepList;
|
|
2620
2812
|
};
|
|
2621
|
-
exports.getRubyGemsMetadata = getRubyGemsMetadata;
|
|
2622
2813
|
|
|
2623
2814
|
/**
|
|
2624
2815
|
* Method to parse Gemspec
|
|
2625
2816
|
*
|
|
2626
2817
|
* @param {*} gemspecData Gemspec data
|
|
2627
2818
|
*/
|
|
2628
|
-
const parseGemspecData = async function (gemspecData) {
|
|
2819
|
+
export const parseGemspecData = async function (gemspecData) {
|
|
2629
2820
|
let pkgList = [];
|
|
2630
2821
|
const pkg = {};
|
|
2631
2822
|
if (!gemspecData) {
|
|
@@ -2657,14 +2848,13 @@ const parseGemspecData = async function (gemspecData) {
|
|
|
2657
2848
|
return pkgList;
|
|
2658
2849
|
}
|
|
2659
2850
|
};
|
|
2660
|
-
exports.parseGemspecData = parseGemspecData;
|
|
2661
2851
|
|
|
2662
2852
|
/**
|
|
2663
2853
|
* Method to parse Gemfile.lock
|
|
2664
2854
|
*
|
|
2665
2855
|
* @param {*} gemLockData Gemfile.lock data
|
|
2666
2856
|
*/
|
|
2667
|
-
const parseGemfileLockData = async function (gemLockData) {
|
|
2857
|
+
export const parseGemfileLockData = async function (gemLockData) {
|
|
2668
2858
|
const pkgList = [];
|
|
2669
2859
|
const pkgnames = {};
|
|
2670
2860
|
if (!gemLockData) {
|
|
@@ -2706,14 +2896,13 @@ const parseGemfileLockData = async function (gemLockData) {
|
|
|
2706
2896
|
return pkgList;
|
|
2707
2897
|
}
|
|
2708
2898
|
};
|
|
2709
|
-
exports.parseGemfileLockData = parseGemfileLockData;
|
|
2710
2899
|
|
|
2711
2900
|
/**
|
|
2712
2901
|
* Method to retrieve metadata for rust packages by querying crates
|
|
2713
2902
|
*
|
|
2714
2903
|
* @param {Array} pkgList Package list
|
|
2715
2904
|
*/
|
|
2716
|
-
const getCratesMetadata = async function (pkgList) {
|
|
2905
|
+
export const getCratesMetadata = async function (pkgList) {
|
|
2717
2906
|
const CRATES_URL = "https://crates.io/api/v1/crates/";
|
|
2718
2907
|
const cdepList = [];
|
|
2719
2908
|
for (const p of pkgList) {
|
|
@@ -2721,7 +2910,9 @@ const getCratesMetadata = async function (pkgList) {
|
|
|
2721
2910
|
if (DEBUG_MODE) {
|
|
2722
2911
|
console.log(`Querying crates.io for ${p.name}`);
|
|
2723
2912
|
}
|
|
2724
|
-
const res = await
|
|
2913
|
+
const res = await cdxgenAgent.get(CRATES_URL + p.name, {
|
|
2914
|
+
responseType: "json"
|
|
2915
|
+
});
|
|
2725
2916
|
const body = res.body.crate;
|
|
2726
2917
|
p.description = body.description;
|
|
2727
2918
|
if (res.body.versions) {
|
|
@@ -2745,14 +2936,13 @@ const getCratesMetadata = async function (pkgList) {
|
|
|
2745
2936
|
}
|
|
2746
2937
|
return cdepList;
|
|
2747
2938
|
};
|
|
2748
|
-
exports.getCratesMetadata = getCratesMetadata;
|
|
2749
2939
|
|
|
2750
2940
|
/**
|
|
2751
2941
|
* Method to retrieve metadata for dart packages by querying pub.dev
|
|
2752
2942
|
*
|
|
2753
2943
|
* @param {Array} pkgList Package list
|
|
2754
2944
|
*/
|
|
2755
|
-
const getDartMetadata = async function (pkgList) {
|
|
2945
|
+
export const getDartMetadata = async function (pkgList) {
|
|
2756
2946
|
const PUB_DEV_URL = "https://pub.dev/api/packages/";
|
|
2757
2947
|
const cdepList = [];
|
|
2758
2948
|
for (const p of pkgList) {
|
|
@@ -2760,9 +2950,11 @@ const getDartMetadata = async function (pkgList) {
|
|
|
2760
2950
|
if (DEBUG_MODE) {
|
|
2761
2951
|
console.log(`Querying pub.dev for ${p.name}`);
|
|
2762
2952
|
}
|
|
2763
|
-
const res = await
|
|
2953
|
+
const res = await cdxgenAgent.get(PUB_DEV_URL + p.name, {
|
|
2764
2954
|
responseType: "json",
|
|
2765
|
-
|
|
2955
|
+
headers: {
|
|
2956
|
+
Accept: "application/vnd.pub.v2+json"
|
|
2957
|
+
}
|
|
2766
2958
|
});
|
|
2767
2959
|
if (res && res.body) {
|
|
2768
2960
|
const versions = res.body.versions;
|
|
@@ -2788,9 +2980,8 @@ const getDartMetadata = async function (pkgList) {
|
|
|
2788
2980
|
}
|
|
2789
2981
|
return cdepList;
|
|
2790
2982
|
};
|
|
2791
|
-
exports.getDartMetadata = getDartMetadata;
|
|
2792
2983
|
|
|
2793
|
-
const parseCargoTomlData = async function (cargoData) {
|
|
2984
|
+
export const parseCargoTomlData = async function (cargoData) {
|
|
2794
2985
|
let pkgList = [];
|
|
2795
2986
|
if (!cargoData) {
|
|
2796
2987
|
return pkgList;
|
|
@@ -2825,11 +3016,11 @@ const parseCargoTomlData = async function (cargoData) {
|
|
|
2825
3016
|
pkg._integrity = "sha384-" + value;
|
|
2826
3017
|
break;
|
|
2827
3018
|
case "name":
|
|
2828
|
-
pkg.group =
|
|
3019
|
+
pkg.group = dirname(value);
|
|
2829
3020
|
if (pkg.group === ".") {
|
|
2830
3021
|
pkg.group = "";
|
|
2831
3022
|
}
|
|
2832
|
-
pkg.name =
|
|
3023
|
+
pkg.name = basename(value);
|
|
2833
3024
|
break;
|
|
2834
3025
|
case "version":
|
|
2835
3026
|
pkg.version = value;
|
|
@@ -2873,9 +3064,8 @@ const parseCargoTomlData = async function (cargoData) {
|
|
|
2873
3064
|
return pkgList;
|
|
2874
3065
|
}
|
|
2875
3066
|
};
|
|
2876
|
-
exports.parseCargoTomlData = parseCargoTomlData;
|
|
2877
3067
|
|
|
2878
|
-
const parseCargoData = async function (cargoData) {
|
|
3068
|
+
export const parseCargoData = async function (cargoData) {
|
|
2879
3069
|
const pkgList = [];
|
|
2880
3070
|
if (!cargoData) {
|
|
2881
3071
|
return pkgList;
|
|
@@ -2903,11 +3093,11 @@ const parseCargoData = async function (cargoData) {
|
|
|
2903
3093
|
pkg._integrity = "sha384-" + value;
|
|
2904
3094
|
break;
|
|
2905
3095
|
case "name":
|
|
2906
|
-
pkg.group =
|
|
3096
|
+
pkg.group = dirname(value);
|
|
2907
3097
|
if (pkg.group === ".") {
|
|
2908
3098
|
pkg.group = "";
|
|
2909
3099
|
}
|
|
2910
|
-
pkg.name =
|
|
3100
|
+
pkg.name = basename(value);
|
|
2911
3101
|
break;
|
|
2912
3102
|
case "version":
|
|
2913
3103
|
pkg.version = value;
|
|
@@ -2921,9 +3111,8 @@ const parseCargoData = async function (cargoData) {
|
|
|
2921
3111
|
return pkgList;
|
|
2922
3112
|
}
|
|
2923
3113
|
};
|
|
2924
|
-
exports.parseCargoData = parseCargoData;
|
|
2925
3114
|
|
|
2926
|
-
const parseCargoAuditableData = async function (cargoData) {
|
|
3115
|
+
export const parseCargoAuditableData = async function (cargoData) {
|
|
2927
3116
|
const pkgList = [];
|
|
2928
3117
|
if (!cargoData) {
|
|
2929
3118
|
return pkgList;
|
|
@@ -2931,8 +3120,8 @@ const parseCargoAuditableData = async function (cargoData) {
|
|
|
2931
3120
|
cargoData.split("\n").forEach((l) => {
|
|
2932
3121
|
const tmpA = l.split("\t");
|
|
2933
3122
|
if (tmpA && tmpA.length > 2) {
|
|
2934
|
-
let group =
|
|
2935
|
-
const name =
|
|
3123
|
+
let group = dirname(tmpA[0].trim());
|
|
3124
|
+
const name = basename(tmpA[0].trim());
|
|
2936
3125
|
if (group === ".") {
|
|
2937
3126
|
group = "";
|
|
2938
3127
|
}
|
|
@@ -2950,9 +3139,8 @@ const parseCargoAuditableData = async function (cargoData) {
|
|
|
2950
3139
|
return pkgList;
|
|
2951
3140
|
}
|
|
2952
3141
|
};
|
|
2953
|
-
exports.parseCargoAuditableData = parseCargoAuditableData;
|
|
2954
3142
|
|
|
2955
|
-
const parsePubLockData = async function (pubLockData) {
|
|
3143
|
+
export const parsePubLockData = async function (pubLockData) {
|
|
2956
3144
|
const pkgList = [];
|
|
2957
3145
|
if (!pubLockData) {
|
|
2958
3146
|
return pkgList;
|
|
@@ -2990,13 +3178,12 @@ const parsePubLockData = async function (pubLockData) {
|
|
|
2990
3178
|
return pkgList;
|
|
2991
3179
|
}
|
|
2992
3180
|
};
|
|
2993
|
-
exports.parsePubLockData = parsePubLockData;
|
|
2994
3181
|
|
|
2995
|
-
const parsePubYamlData = async function (pubYamlData) {
|
|
3182
|
+
export const parsePubYamlData = async function (pubYamlData) {
|
|
2996
3183
|
const pkgList = [];
|
|
2997
3184
|
let yamlObj = undefined;
|
|
2998
3185
|
try {
|
|
2999
|
-
yamlObj =
|
|
3186
|
+
yamlObj = _load(pubYamlData);
|
|
3000
3187
|
} catch (err) {
|
|
3001
3188
|
// continue regardless of error
|
|
3002
3189
|
}
|
|
@@ -3011,13 +3198,12 @@ const parsePubYamlData = async function (pubYamlData) {
|
|
|
3011
3198
|
});
|
|
3012
3199
|
return pkgList;
|
|
3013
3200
|
};
|
|
3014
|
-
exports.parsePubYamlData = parsePubYamlData;
|
|
3015
3201
|
|
|
3016
|
-
const parseHelmYamlData = async function (helmData) {
|
|
3202
|
+
export const parseHelmYamlData = async function (helmData) {
|
|
3017
3203
|
const pkgList = [];
|
|
3018
3204
|
let yamlObj = undefined;
|
|
3019
3205
|
try {
|
|
3020
|
-
yamlObj =
|
|
3206
|
+
yamlObj = _load(helmData);
|
|
3021
3207
|
} catch (err) {
|
|
3022
3208
|
// continue regardless of error
|
|
3023
3209
|
}
|
|
@@ -3077,9 +3263,8 @@ const parseHelmYamlData = async function (helmData) {
|
|
|
3077
3263
|
}
|
|
3078
3264
|
return pkgList;
|
|
3079
3265
|
};
|
|
3080
|
-
exports.parseHelmYamlData = parseHelmYamlData;
|
|
3081
3266
|
|
|
3082
|
-
const recurseImageNameLookup = (keyValueObj, pkgList, imgList) => {
|
|
3267
|
+
export const recurseImageNameLookup = (keyValueObj, pkgList, imgList) => {
|
|
3083
3268
|
if (typeof keyValueObj === "string" || keyValueObj instanceof String) {
|
|
3084
3269
|
return imgList;
|
|
3085
3270
|
}
|
|
@@ -3141,9 +3326,8 @@ const recurseImageNameLookup = (keyValueObj, pkgList, imgList) => {
|
|
|
3141
3326
|
}
|
|
3142
3327
|
return imgList;
|
|
3143
3328
|
};
|
|
3144
|
-
exports.recurseImageNameLookup = recurseImageNameLookup;
|
|
3145
3329
|
|
|
3146
|
-
const parseContainerSpecData = async function (dcData) {
|
|
3330
|
+
export const parseContainerSpecData = async function (dcData) {
|
|
3147
3331
|
const pkgList = [];
|
|
3148
3332
|
const imgList = [];
|
|
3149
3333
|
if (!dcData.includes("image") && !dcData.includes("kind")) {
|
|
@@ -3156,7 +3340,7 @@ const parseContainerSpecData = async function (dcData) {
|
|
|
3156
3340
|
for (const dcData of dcDataList) {
|
|
3157
3341
|
let yamlObj = undefined;
|
|
3158
3342
|
try {
|
|
3159
|
-
yamlObj =
|
|
3343
|
+
yamlObj = _load(dcData);
|
|
3160
3344
|
} catch (err) {
|
|
3161
3345
|
// ignore errors
|
|
3162
3346
|
}
|
|
@@ -3209,9 +3393,8 @@ const parseContainerSpecData = async function (dcData) {
|
|
|
3209
3393
|
}
|
|
3210
3394
|
return pkgList;
|
|
3211
3395
|
};
|
|
3212
|
-
exports.parseContainerSpecData = parseContainerSpecData;
|
|
3213
3396
|
|
|
3214
|
-
const identifyFlow = function (processingObj) {
|
|
3397
|
+
export const identifyFlow = function (processingObj) {
|
|
3215
3398
|
let flow = "unknown";
|
|
3216
3399
|
if (processingObj.sinkId) {
|
|
3217
3400
|
let sinkId = processingObj.sinkId.toLowerCase();
|
|
@@ -3237,8 +3420,8 @@ const convertProcessing = function (processing_list) {
|
|
|
3237
3420
|
return data_list;
|
|
3238
3421
|
};
|
|
3239
3422
|
|
|
3240
|
-
const parsePrivadoFile = function (f) {
|
|
3241
|
-
const pData =
|
|
3423
|
+
export const parsePrivadoFile = function (f) {
|
|
3424
|
+
const pData = readFileSync(f, { encoding: "utf-8" });
|
|
3242
3425
|
const servlist = [];
|
|
3243
3426
|
if (!pData) {
|
|
3244
3427
|
return servlist;
|
|
@@ -3321,16 +3504,15 @@ const parsePrivadoFile = function (f) {
|
|
|
3321
3504
|
}
|
|
3322
3505
|
return servlist;
|
|
3323
3506
|
};
|
|
3324
|
-
exports.parsePrivadoFile = parsePrivadoFile;
|
|
3325
3507
|
|
|
3326
|
-
const parseOpenapiSpecData = async function (oaData) {
|
|
3508
|
+
export const parseOpenapiSpecData = async function (oaData) {
|
|
3327
3509
|
const servlist = [];
|
|
3328
3510
|
if (!oaData) {
|
|
3329
3511
|
return servlist;
|
|
3330
3512
|
}
|
|
3331
3513
|
try {
|
|
3332
3514
|
if (oaData.startsWith("openapi:")) {
|
|
3333
|
-
oaData =
|
|
3515
|
+
oaData = _load(oaData);
|
|
3334
3516
|
} else {
|
|
3335
3517
|
oaData = JSON.parse(oaData);
|
|
3336
3518
|
}
|
|
@@ -3372,9 +3554,8 @@ const parseOpenapiSpecData = async function (oaData) {
|
|
|
3372
3554
|
servlist.push(aservice);
|
|
3373
3555
|
return servlist;
|
|
3374
3556
|
};
|
|
3375
|
-
exports.parseOpenapiSpecData = parseOpenapiSpecData;
|
|
3376
3557
|
|
|
3377
|
-
const parseCabalData = async function (cabalData) {
|
|
3558
|
+
export const parseCabalData = async function (cabalData) {
|
|
3378
3559
|
const pkgList = [];
|
|
3379
3560
|
if (!cabalData) {
|
|
3380
3561
|
return pkgList;
|
|
@@ -3400,9 +3581,8 @@ const parseCabalData = async function (cabalData) {
|
|
|
3400
3581
|
});
|
|
3401
3582
|
return pkgList;
|
|
3402
3583
|
};
|
|
3403
|
-
exports.parseCabalData = parseCabalData;
|
|
3404
3584
|
|
|
3405
|
-
const parseMixLockData = async function (mixData) {
|
|
3585
|
+
export const parseMixLockData = async function (mixData) {
|
|
3406
3586
|
const pkgList = [];
|
|
3407
3587
|
if (!mixData) {
|
|
3408
3588
|
return pkgList;
|
|
@@ -3427,15 +3607,14 @@ const parseMixLockData = async function (mixData) {
|
|
|
3427
3607
|
});
|
|
3428
3608
|
return pkgList;
|
|
3429
3609
|
};
|
|
3430
|
-
exports.parseMixLockData = parseMixLockData;
|
|
3431
3610
|
|
|
3432
|
-
const parseGitHubWorkflowData = async function (ghwData) {
|
|
3611
|
+
export const parseGitHubWorkflowData = async function (ghwData) {
|
|
3433
3612
|
const pkgList = [];
|
|
3434
3613
|
const keys_cache = {};
|
|
3435
3614
|
if (!ghwData) {
|
|
3436
3615
|
return pkgList;
|
|
3437
3616
|
}
|
|
3438
|
-
const yamlObj =
|
|
3617
|
+
const yamlObj = _load(ghwData);
|
|
3439
3618
|
if (!yamlObj) {
|
|
3440
3619
|
return pkgList;
|
|
3441
3620
|
}
|
|
@@ -3470,15 +3649,14 @@ const parseGitHubWorkflowData = async function (ghwData) {
|
|
|
3470
3649
|
}
|
|
3471
3650
|
return pkgList;
|
|
3472
3651
|
};
|
|
3473
|
-
exports.parseGitHubWorkflowData = parseGitHubWorkflowData;
|
|
3474
3652
|
|
|
3475
|
-
const parseCloudBuildData = async function (cbwData) {
|
|
3653
|
+
export const parseCloudBuildData = async function (cbwData) {
|
|
3476
3654
|
const pkgList = [];
|
|
3477
3655
|
const keys_cache = {};
|
|
3478
3656
|
if (!cbwData) {
|
|
3479
3657
|
return pkgList;
|
|
3480
3658
|
}
|
|
3481
|
-
const yamlObj =
|
|
3659
|
+
const yamlObj = _load(cbwData);
|
|
3482
3660
|
if (!yamlObj) {
|
|
3483
3661
|
return pkgList;
|
|
3484
3662
|
}
|
|
@@ -3487,8 +3665,8 @@ const parseCloudBuildData = async function (cbwData) {
|
|
|
3487
3665
|
if (step.name) {
|
|
3488
3666
|
const tmpA = step.name.split(":");
|
|
3489
3667
|
if (tmpA.length === 2) {
|
|
3490
|
-
let group =
|
|
3491
|
-
let name =
|
|
3668
|
+
let group = dirname(tmpA[0]);
|
|
3669
|
+
let name = basename(tmpA[0]);
|
|
3492
3670
|
if (group === ".") {
|
|
3493
3671
|
group = "";
|
|
3494
3672
|
}
|
|
@@ -3508,9 +3686,8 @@ const parseCloudBuildData = async function (cbwData) {
|
|
|
3508
3686
|
}
|
|
3509
3687
|
return pkgList;
|
|
3510
3688
|
};
|
|
3511
|
-
exports.parseCloudBuildData = parseCloudBuildData;
|
|
3512
3689
|
|
|
3513
|
-
const parseConanLockData = async function (conanLockData) {
|
|
3690
|
+
export const parseConanLockData = async function (conanLockData) {
|
|
3514
3691
|
const pkgList = [];
|
|
3515
3692
|
if (!conanLockData) {
|
|
3516
3693
|
return pkgList;
|
|
@@ -3530,9 +3707,8 @@ const parseConanLockData = async function (conanLockData) {
|
|
|
3530
3707
|
}
|
|
3531
3708
|
return pkgList;
|
|
3532
3709
|
};
|
|
3533
|
-
exports.parseConanLockData = parseConanLockData;
|
|
3534
3710
|
|
|
3535
|
-
const parseConanData = async function (conanData) {
|
|
3711
|
+
export const parseConanData = async function (conanData) {
|
|
3536
3712
|
const pkgList = [];
|
|
3537
3713
|
if (!conanData) {
|
|
3538
3714
|
return pkgList;
|
|
@@ -3550,9 +3726,8 @@ const parseConanData = async function (conanData) {
|
|
|
3550
3726
|
});
|
|
3551
3727
|
return pkgList;
|
|
3552
3728
|
};
|
|
3553
|
-
exports.parseConanData = parseConanData;
|
|
3554
3729
|
|
|
3555
|
-
const parseLeiningenData = function (leinData) {
|
|
3730
|
+
export const parseLeiningenData = function (leinData) {
|
|
3556
3731
|
const pkgList = [];
|
|
3557
3732
|
if (!leinData) {
|
|
3558
3733
|
return pkgList;
|
|
@@ -3561,7 +3736,7 @@ const parseLeiningenData = function (leinData) {
|
|
|
3561
3736
|
if (tmpArr.length > 1) {
|
|
3562
3737
|
leinData = "(defproject" + tmpArr[1];
|
|
3563
3738
|
}
|
|
3564
|
-
const ednData =
|
|
3739
|
+
const ednData = parseEDNString(leinData);
|
|
3565
3740
|
for (let k of Object.keys(ednData)) {
|
|
3566
3741
|
if (k === "list") {
|
|
3567
3742
|
ednData[k].forEach((jk) => {
|
|
@@ -3570,11 +3745,11 @@ const parseLeiningenData = function (leinData) {
|
|
|
3570
3745
|
if (Array.isArray(pobjl) && pobjl.length > 1) {
|
|
3571
3746
|
const psym = pobjl[0].sym;
|
|
3572
3747
|
if (psym) {
|
|
3573
|
-
let group =
|
|
3748
|
+
let group = dirname(psym) || "";
|
|
3574
3749
|
if (group === ".") {
|
|
3575
3750
|
group = "";
|
|
3576
3751
|
}
|
|
3577
|
-
const name =
|
|
3752
|
+
const name = basename(psym);
|
|
3578
3753
|
pkgList.push({ group, name, version: pobjl[1] });
|
|
3579
3754
|
}
|
|
3580
3755
|
}
|
|
@@ -3585,14 +3760,13 @@ const parseLeiningenData = function (leinData) {
|
|
|
3585
3760
|
}
|
|
3586
3761
|
return pkgList;
|
|
3587
3762
|
};
|
|
3588
|
-
exports.parseLeiningenData = parseLeiningenData;
|
|
3589
3763
|
|
|
3590
|
-
const parseEdnData = function (rawEdnData) {
|
|
3764
|
+
export const parseEdnData = function (rawEdnData) {
|
|
3591
3765
|
const pkgList = [];
|
|
3592
3766
|
if (!rawEdnData) {
|
|
3593
3767
|
return pkgList;
|
|
3594
3768
|
}
|
|
3595
|
-
const ednData =
|
|
3769
|
+
const ednData = parseEDNString(rawEdnData);
|
|
3596
3770
|
const pkgCache = {};
|
|
3597
3771
|
for (let k of Object.keys(ednData)) {
|
|
3598
3772
|
if (k === "map") {
|
|
@@ -3613,11 +3787,11 @@ const parseEdnData = function (rawEdnData) {
|
|
|
3613
3787
|
if (e["map"]) {
|
|
3614
3788
|
if (e["map"][0].length > 1) {
|
|
3615
3789
|
const version = e["map"][0][1];
|
|
3616
|
-
let group =
|
|
3790
|
+
let group = dirname(psym) || "";
|
|
3617
3791
|
if (group === ".") {
|
|
3618
3792
|
group = "";
|
|
3619
3793
|
}
|
|
3620
|
-
const name =
|
|
3794
|
+
const name = basename(psym);
|
|
3621
3795
|
const cacheKey = group + "-" + name + "-" + version;
|
|
3622
3796
|
if (!pkgCache[cacheKey]) {
|
|
3623
3797
|
pkgList.push({ group, name, version });
|
|
@@ -3638,9 +3812,8 @@ const parseEdnData = function (rawEdnData) {
|
|
|
3638
3812
|
}
|
|
3639
3813
|
return pkgList;
|
|
3640
3814
|
};
|
|
3641
|
-
exports.parseEdnData = parseEdnData;
|
|
3642
3815
|
|
|
3643
|
-
const parseNupkg = async function (nupkgFile) {
|
|
3816
|
+
export const parseNupkg = async function (nupkgFile) {
|
|
3644
3817
|
const pkgList = [];
|
|
3645
3818
|
let pkg = { group: "" };
|
|
3646
3819
|
let nuspecData = await readZipEntry(nupkgFile, ".nuspec");
|
|
@@ -3650,7 +3823,7 @@ const parseNupkg = async function (nupkgFile) {
|
|
|
3650
3823
|
}
|
|
3651
3824
|
let npkg = undefined;
|
|
3652
3825
|
try {
|
|
3653
|
-
npkg =
|
|
3826
|
+
npkg = xml2js(nuspecData, {
|
|
3654
3827
|
compact: true,
|
|
3655
3828
|
alwaysArray: false,
|
|
3656
3829
|
spaces: 4,
|
|
@@ -3684,14 +3857,13 @@ const parseNupkg = async function (nupkgFile) {
|
|
|
3684
3857
|
return pkgList;
|
|
3685
3858
|
}
|
|
3686
3859
|
};
|
|
3687
|
-
exports.parseNupkg = parseNupkg;
|
|
3688
3860
|
|
|
3689
|
-
const parseCsPkgData = async function (pkgData) {
|
|
3861
|
+
export const parseCsPkgData = async function (pkgData) {
|
|
3690
3862
|
const pkgList = [];
|
|
3691
3863
|
if (!pkgData) {
|
|
3692
3864
|
return pkgList;
|
|
3693
3865
|
}
|
|
3694
|
-
let packages =
|
|
3866
|
+
let packages = xml2js(pkgData, {
|
|
3695
3867
|
compact: true,
|
|
3696
3868
|
alwaysArray: true,
|
|
3697
3869
|
spaces: 4,
|
|
@@ -3716,14 +3888,13 @@ const parseCsPkgData = async function (pkgData) {
|
|
|
3716
3888
|
return pkgList;
|
|
3717
3889
|
}
|
|
3718
3890
|
};
|
|
3719
|
-
exports.parseCsPkgData = parseCsPkgData;
|
|
3720
3891
|
|
|
3721
|
-
const parseCsProjData = async function (csProjData) {
|
|
3892
|
+
export const parseCsProjData = async function (csProjData) {
|
|
3722
3893
|
const pkgList = [];
|
|
3723
3894
|
if (!csProjData) {
|
|
3724
3895
|
return pkgList;
|
|
3725
3896
|
}
|
|
3726
|
-
const projects =
|
|
3897
|
+
const projects = xml2js(csProjData, {
|
|
3727
3898
|
compact: true,
|
|
3728
3899
|
alwaysArray: true,
|
|
3729
3900
|
spaces: 4,
|
|
@@ -3771,9 +3942,8 @@ const parseCsProjData = async function (csProjData) {
|
|
|
3771
3942
|
return pkgList;
|
|
3772
3943
|
}
|
|
3773
3944
|
};
|
|
3774
|
-
exports.parseCsProjData = parseCsProjData;
|
|
3775
3945
|
|
|
3776
|
-
const parseCsProjAssetsData = async function (csProjData) {
|
|
3946
|
+
export const parseCsProjAssetsData = async function (csProjData) {
|
|
3777
3947
|
const pkgList = [];
|
|
3778
3948
|
let pkg = null;
|
|
3779
3949
|
if (!csProjData) {
|
|
@@ -3811,9 +3981,8 @@ const parseCsProjAssetsData = async function (csProjData) {
|
|
|
3811
3981
|
return pkgList;
|
|
3812
3982
|
}
|
|
3813
3983
|
};
|
|
3814
|
-
exports.parseCsProjAssetsData = parseCsProjAssetsData;
|
|
3815
3984
|
|
|
3816
|
-
const parseCsPkgLockData = async function (csLockData) {
|
|
3985
|
+
export const parseCsPkgLockData = async function (csLockData) {
|
|
3817
3986
|
const pkgList = [];
|
|
3818
3987
|
let pkg = null;
|
|
3819
3988
|
if (!csLockData) {
|
|
@@ -3840,14 +4009,13 @@ const parseCsPkgLockData = async function (csLockData) {
|
|
|
3840
4009
|
return pkgList;
|
|
3841
4010
|
}
|
|
3842
4011
|
};
|
|
3843
|
-
exports.parseCsPkgLockData = parseCsPkgLockData;
|
|
3844
4012
|
|
|
3845
4013
|
/**
|
|
3846
4014
|
* Method to retrieve metadata for nuget packages
|
|
3847
4015
|
*
|
|
3848
4016
|
* @param {Array} pkgList Package list
|
|
3849
4017
|
*/
|
|
3850
|
-
const getNugetMetadata = async function (pkgList) {
|
|
4018
|
+
export const getNugetMetadata = async function (pkgList) {
|
|
3851
4019
|
const NUGET_URL = "https://api.nuget.org/v3/registration3/";
|
|
3852
4020
|
const cdepList = [];
|
|
3853
4021
|
for (const p of pkgList) {
|
|
@@ -3855,7 +4023,7 @@ const getNugetMetadata = async function (pkgList) {
|
|
|
3855
4023
|
if (DEBUG_MODE) {
|
|
3856
4024
|
console.log(`Querying nuget for ${p.name}`);
|
|
3857
4025
|
}
|
|
3858
|
-
const res = await
|
|
4026
|
+
const res = await cdxgenAgent.get(
|
|
3859
4027
|
NUGET_URL +
|
|
3860
4028
|
p.group.toLowerCase() +
|
|
3861
4029
|
(p.group !== "" ? "." : "") +
|
|
@@ -3902,19 +4070,18 @@ const getNugetMetadata = async function (pkgList) {
|
|
|
3902
4070
|
}
|
|
3903
4071
|
return cdepList;
|
|
3904
4072
|
};
|
|
3905
|
-
exports.getNugetMetadata = getNugetMetadata;
|
|
3906
4073
|
|
|
3907
4074
|
/**
|
|
3908
4075
|
* Parse composer lock file
|
|
3909
4076
|
*
|
|
3910
4077
|
* @param {string} pkgLockFile composer.lock file
|
|
3911
4078
|
*/
|
|
3912
|
-
const parseComposerLock = function (pkgLockFile) {
|
|
4079
|
+
export const parseComposerLock = function (pkgLockFile) {
|
|
3913
4080
|
const pkgList = [];
|
|
3914
|
-
if (
|
|
4081
|
+
if (existsSync(pkgLockFile)) {
|
|
3915
4082
|
let lockData = {};
|
|
3916
4083
|
try {
|
|
3917
|
-
lockData = JSON.parse(
|
|
4084
|
+
lockData = JSON.parse(readFileSync(pkgLockFile, "utf8"));
|
|
3918
4085
|
} catch (e) {
|
|
3919
4086
|
console.error("Invalid composer.lock file:", pkgLockFile);
|
|
3920
4087
|
return [];
|
|
@@ -3934,11 +4101,11 @@ const parseComposerLock = function (pkgLockFile) {
|
|
|
3934
4101
|
if (!pkg || !pkg.name || !pkg.version) {
|
|
3935
4102
|
continue;
|
|
3936
4103
|
}
|
|
3937
|
-
let group =
|
|
4104
|
+
let group = dirname(pkg.name);
|
|
3938
4105
|
if (group === ".") {
|
|
3939
4106
|
group = "";
|
|
3940
4107
|
}
|
|
3941
|
-
let name =
|
|
4108
|
+
let name = basename(pkg.name);
|
|
3942
4109
|
pkgList.push({
|
|
3943
4110
|
group: group,
|
|
3944
4111
|
name: name,
|
|
@@ -3964,17 +4131,16 @@ const parseComposerLock = function (pkgLockFile) {
|
|
|
3964
4131
|
}
|
|
3965
4132
|
return pkgList;
|
|
3966
4133
|
};
|
|
3967
|
-
exports.parseComposerLock = parseComposerLock;
|
|
3968
4134
|
|
|
3969
4135
|
/**
|
|
3970
4136
|
* Parse sbt lock file
|
|
3971
4137
|
*
|
|
3972
4138
|
* @param {string} pkgLockFile build.sbt.lock file
|
|
3973
4139
|
*/
|
|
3974
|
-
const parseSbtLock = function (pkgLockFile) {
|
|
4140
|
+
export const parseSbtLock = function (pkgLockFile) {
|
|
3975
4141
|
const pkgList = [];
|
|
3976
|
-
if (
|
|
3977
|
-
const lockData = JSON.parse(
|
|
4142
|
+
if (existsSync(pkgLockFile)) {
|
|
4143
|
+
const lockData = JSON.parse(readFileSync(pkgLockFile, "utf8"));
|
|
3978
4144
|
if (lockData && lockData.dependencies) {
|
|
3979
4145
|
for (let pkg of lockData.dependencies) {
|
|
3980
4146
|
const artifacts = pkg.artifacts || undefined;
|
|
@@ -4008,7 +4174,6 @@ const parseSbtLock = function (pkgLockFile) {
|
|
|
4008
4174
|
}
|
|
4009
4175
|
return pkgList;
|
|
4010
4176
|
};
|
|
4011
|
-
exports.parseSbtLock = parseSbtLock;
|
|
4012
4177
|
|
|
4013
4178
|
/**
|
|
4014
4179
|
* Convert OS query results
|
|
@@ -4016,7 +4181,11 @@ exports.parseSbtLock = parseSbtLock;
|
|
|
4016
4181
|
* @param {Object} queryObj Query Object from the queries.json configuration
|
|
4017
4182
|
* @param {Array} results Query Results
|
|
4018
4183
|
*/
|
|
4019
|
-
const convertOSQueryResults = function (
|
|
4184
|
+
export const convertOSQueryResults = function (
|
|
4185
|
+
queryCategory,
|
|
4186
|
+
queryObj,
|
|
4187
|
+
results
|
|
4188
|
+
) {
|
|
4020
4189
|
const pkgList = [];
|
|
4021
4190
|
if (results && results.length) {
|
|
4022
4191
|
for (const res of results) {
|
|
@@ -4068,9 +4237,13 @@ const convertOSQueryResults = function (queryCategory, queryObj, results) {
|
|
|
4068
4237
|
}
|
|
4069
4238
|
return pkgList;
|
|
4070
4239
|
};
|
|
4071
|
-
exports.convertOSQueryResults = convertOSQueryResults;
|
|
4072
4240
|
|
|
4073
|
-
const _swiftDepPkgList = (
|
|
4241
|
+
export const _swiftDepPkgList = (
|
|
4242
|
+
pkgList,
|
|
4243
|
+
dependenciesList,
|
|
4244
|
+
depKeys,
|
|
4245
|
+
jsonData
|
|
4246
|
+
) => {
|
|
4074
4247
|
if (jsonData && jsonData.dependencies) {
|
|
4075
4248
|
for (let adep of jsonData.dependencies) {
|
|
4076
4249
|
const urlOrPath = adep.url || adep.path;
|
|
@@ -4153,7 +4326,7 @@ const _swiftDepPkgList = (pkgList, dependenciesList, depKeys, jsonData) => {
|
|
|
4153
4326
|
* @param {string} rawOutput Swift dependencies json output
|
|
4154
4327
|
* @param {string} pkgFile Package.swift file
|
|
4155
4328
|
*/
|
|
4156
|
-
const parseSwiftJsonTree = (rawOutput, pkgFile) => {
|
|
4329
|
+
export const parseSwiftJsonTree = (rawOutput, pkgFile) => {
|
|
4157
4330
|
if (!rawOutput) {
|
|
4158
4331
|
return {};
|
|
4159
4332
|
}
|
|
@@ -4228,17 +4401,16 @@ const parseSwiftJsonTree = (rawOutput, pkgFile) => {
|
|
|
4228
4401
|
dependenciesList
|
|
4229
4402
|
};
|
|
4230
4403
|
};
|
|
4231
|
-
exports.parseSwiftJsonTree = parseSwiftJsonTree;
|
|
4232
4404
|
|
|
4233
4405
|
/**
|
|
4234
4406
|
* Parse swift package resolved file
|
|
4235
4407
|
* @param {string} resolvedFile Package.resolved file
|
|
4236
4408
|
*/
|
|
4237
|
-
const parseSwiftResolved = (resolvedFile) => {
|
|
4409
|
+
export const parseSwiftResolved = (resolvedFile) => {
|
|
4238
4410
|
const pkgList = [];
|
|
4239
|
-
if (
|
|
4411
|
+
if (existsSync(resolvedFile)) {
|
|
4240
4412
|
try {
|
|
4241
|
-
const pkgData = JSON.parse(
|
|
4413
|
+
const pkgData = JSON.parse(readFileSync(resolvedFile, "utf8"));
|
|
4242
4414
|
let resolvedList = [];
|
|
4243
4415
|
if (pkgData.pins) {
|
|
4244
4416
|
resolvedList = pkgData.pins;
|
|
@@ -4269,7 +4441,6 @@ const parseSwiftResolved = (resolvedFile) => {
|
|
|
4269
4441
|
}
|
|
4270
4442
|
return pkgList;
|
|
4271
4443
|
};
|
|
4272
|
-
exports.parseSwiftResolved = parseSwiftResolved;
|
|
4273
4444
|
|
|
4274
4445
|
/**
|
|
4275
4446
|
* Collect maven dependencies
|
|
@@ -4277,8 +4448,8 @@ exports.parseSwiftResolved = parseSwiftResolved;
|
|
|
4277
4448
|
* @param {string} mavenCmd Maven command to use
|
|
4278
4449
|
* @param {string} basePath Path to the maven project
|
|
4279
4450
|
*/
|
|
4280
|
-
const collectMvnDependencies = function (mavenCmd, basePath) {
|
|
4281
|
-
let tempDir =
|
|
4451
|
+
export const collectMvnDependencies = function (mavenCmd, basePath) {
|
|
4452
|
+
let tempDir = mkdtempSync(join(tmpdir(), "mvn-deps-"));
|
|
4282
4453
|
console.log(
|
|
4283
4454
|
`Executing 'mvn dependency:copy-dependencies -DoutputDirectory=${tempDir} -DexcludeTransitive=true -DincludeScope=runtime' in ${basePath}`
|
|
4284
4455
|
);
|
|
@@ -4314,13 +4485,12 @@ const collectMvnDependencies = function (mavenCmd, basePath) {
|
|
|
4314
4485
|
jarNSMapping = collectJarNS(tempDir);
|
|
4315
4486
|
}
|
|
4316
4487
|
// Clean up
|
|
4317
|
-
if (tempDir && tempDir.startsWith(
|
|
4488
|
+
if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
|
|
4318
4489
|
console.log(`Cleaning up ${tempDir}`);
|
|
4319
|
-
|
|
4490
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
4320
4491
|
}
|
|
4321
4492
|
return jarNSMapping;
|
|
4322
4493
|
};
|
|
4323
|
-
exports.collectMvnDependencies = collectMvnDependencies;
|
|
4324
4494
|
|
|
4325
4495
|
/**
|
|
4326
4496
|
* Method to collect class names from all jars in a directory
|
|
@@ -4329,7 +4499,7 @@ exports.collectMvnDependencies = collectMvnDependencies;
|
|
|
4329
4499
|
*
|
|
4330
4500
|
* @return object containing jar name and class list
|
|
4331
4501
|
*/
|
|
4332
|
-
const collectJarNS = function (jarPath) {
|
|
4502
|
+
export const collectJarNS = function (jarPath) {
|
|
4333
4503
|
const jarNSMapping = {};
|
|
4334
4504
|
console.log(
|
|
4335
4505
|
`About to identify class names for all jars in the path ${jarPath}`
|
|
@@ -4338,7 +4508,7 @@ const collectJarNS = function (jarPath) {
|
|
|
4338
4508
|
const jarFiles = getAllFiles(jarPath, "**/*.jar");
|
|
4339
4509
|
if (jarFiles && jarFiles.length) {
|
|
4340
4510
|
for (let jf of jarFiles) {
|
|
4341
|
-
const jarname =
|
|
4511
|
+
const jarname = basename(jf);
|
|
4342
4512
|
if (DEBUG_MODE) {
|
|
4343
4513
|
console.log(`Executing 'jar tf ${jf}'`);
|
|
4344
4514
|
}
|
|
@@ -4375,13 +4545,12 @@ const collectJarNS = function (jarPath) {
|
|
|
4375
4545
|
}
|
|
4376
4546
|
return jarNSMapping;
|
|
4377
4547
|
};
|
|
4378
|
-
exports.collectJarNS = collectJarNS;
|
|
4379
4548
|
|
|
4380
|
-
const parsePomXml = function (pomXmlData) {
|
|
4549
|
+
export const parsePomXml = function (pomXmlData) {
|
|
4381
4550
|
if (!pomXmlData) {
|
|
4382
4551
|
return undefined;
|
|
4383
4552
|
}
|
|
4384
|
-
const project =
|
|
4553
|
+
const project = xml2js(pomXmlData, {
|
|
4385
4554
|
compact: true,
|
|
4386
4555
|
spaces: 4,
|
|
4387
4556
|
textKey: "_",
|
|
@@ -4408,9 +4577,8 @@ const parsePomXml = function (pomXmlData) {
|
|
|
4408
4577
|
}
|
|
4409
4578
|
return undefined;
|
|
4410
4579
|
};
|
|
4411
|
-
exports.parsePomXml = parsePomXml;
|
|
4412
4580
|
|
|
4413
|
-
const parseJarManifest = function (jarMetadata) {
|
|
4581
|
+
export const parseJarManifest = function (jarMetadata) {
|
|
4414
4582
|
const metadata = {};
|
|
4415
4583
|
if (!jarMetadata) {
|
|
4416
4584
|
return metadata;
|
|
@@ -4425,14 +4593,14 @@ const parseJarManifest = function (jarMetadata) {
|
|
|
4425
4593
|
});
|
|
4426
4594
|
return metadata;
|
|
4427
4595
|
};
|
|
4428
|
-
exports.parseJarManifest = parseJarManifest;
|
|
4429
4596
|
|
|
4430
4597
|
const encodeForPurl = (s) => {
|
|
4431
4598
|
return s
|
|
4432
4599
|
? encodeURIComponent(s).replace(/%3A/g, ":").replace(/%2F/g, "/")
|
|
4433
4600
|
: s;
|
|
4434
4601
|
};
|
|
4435
|
-
|
|
4602
|
+
const _encodeForPurl = encodeForPurl;
|
|
4603
|
+
export { _encodeForPurl as encodeForPurl };
|
|
4436
4604
|
|
|
4437
4605
|
/**
|
|
4438
4606
|
* Method to extract a war or ear file
|
|
@@ -4442,27 +4610,23 @@ exports.encodeForPurl = encodeForPurl;
|
|
|
4442
4610
|
*
|
|
4443
4611
|
* @return pkgList Package list
|
|
4444
4612
|
*/
|
|
4445
|
-
const extractJarArchive = function (jarFile, tempDir) {
|
|
4613
|
+
export const extractJarArchive = function (jarFile, tempDir) {
|
|
4446
4614
|
let pkgList = [];
|
|
4447
4615
|
let jarFiles = [];
|
|
4448
|
-
const fname =
|
|
4616
|
+
const fname = basename(jarFile);
|
|
4449
4617
|
let pomname = undefined;
|
|
4450
4618
|
// If there is a pom file in the same directory, try to use it
|
|
4451
4619
|
if (jarFile.endsWith(".jar")) {
|
|
4452
4620
|
pomname = jarFile.replace(".jar", ".pom");
|
|
4453
4621
|
}
|
|
4454
|
-
if (pomname &&
|
|
4455
|
-
tempDir =
|
|
4456
|
-
} else if (!
|
|
4622
|
+
if (pomname && existsSync(pomname)) {
|
|
4623
|
+
tempDir = dirname(jarFile);
|
|
4624
|
+
} else if (!existsSync(join(tempDir, fname))) {
|
|
4457
4625
|
// Only copy if the file doesn't exist
|
|
4458
|
-
|
|
4459
|
-
jarFile,
|
|
4460
|
-
path.join(tempDir, fname),
|
|
4461
|
-
fs.constants.COPYFILE_FICLONE
|
|
4462
|
-
);
|
|
4626
|
+
copyFileSync(jarFile, join(tempDir, fname), constants.COPYFILE_FICLONE);
|
|
4463
4627
|
}
|
|
4464
4628
|
if (jarFile.endsWith(".war") || jarFile.endsWith(".hpi")) {
|
|
4465
|
-
let jarResult = spawnSync("jar", ["-xf",
|
|
4629
|
+
let jarResult = spawnSync("jar", ["-xf", join(tempDir, fname)], {
|
|
4466
4630
|
encoding: "utf-8",
|
|
4467
4631
|
cwd: tempDir
|
|
4468
4632
|
});
|
|
@@ -4473,17 +4637,17 @@ const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4473
4637
|
);
|
|
4474
4638
|
return pkgList;
|
|
4475
4639
|
}
|
|
4476
|
-
jarFiles = getAllFiles(
|
|
4640
|
+
jarFiles = getAllFiles(join(tempDir, "WEB-INF", "lib"), "**/*.jar");
|
|
4477
4641
|
if (jarFile.endsWith(".hpi")) {
|
|
4478
4642
|
jarFiles.push(jarFile);
|
|
4479
4643
|
}
|
|
4480
4644
|
} else {
|
|
4481
|
-
jarFiles = [
|
|
4645
|
+
jarFiles = [join(tempDir, fname)];
|
|
4482
4646
|
}
|
|
4483
4647
|
if (jarFiles && jarFiles.length) {
|
|
4484
4648
|
for (let jf of jarFiles) {
|
|
4485
4649
|
pomname = jf.replace(".jar", ".pom");
|
|
4486
|
-
const jarname =
|
|
4650
|
+
const jarname = basename(jf);
|
|
4487
4651
|
// Ignore test jars
|
|
4488
4652
|
if (
|
|
4489
4653
|
jarname.endsWith("-tests.jar") ||
|
|
@@ -4491,12 +4655,12 @@ const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4491
4655
|
) {
|
|
4492
4656
|
continue;
|
|
4493
4657
|
}
|
|
4494
|
-
let manifestDir =
|
|
4495
|
-
const manifestFile =
|
|
4658
|
+
let manifestDir = join(tempDir, "META-INF");
|
|
4659
|
+
const manifestFile = join(manifestDir, "MANIFEST.MF");
|
|
4496
4660
|
let jarResult = {
|
|
4497
4661
|
status: 1
|
|
4498
4662
|
};
|
|
4499
|
-
if (
|
|
4663
|
+
if (existsSync(pomname)) {
|
|
4500
4664
|
jarResult = { status: 0 };
|
|
4501
4665
|
} else {
|
|
4502
4666
|
jarResult = spawnSync("jar", ["-xf", jf], {
|
|
@@ -4507,9 +4671,9 @@ const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4507
4671
|
if (jarResult.status !== 0) {
|
|
4508
4672
|
console.error(jarResult.stdout, jarResult.stderr);
|
|
4509
4673
|
} else {
|
|
4510
|
-
if (
|
|
4674
|
+
if (existsSync(manifestFile)) {
|
|
4511
4675
|
const jarMetadata = parseJarManifest(
|
|
4512
|
-
|
|
4676
|
+
readFileSync(manifestFile, {
|
|
4513
4677
|
encoding: "utf-8"
|
|
4514
4678
|
})
|
|
4515
4679
|
);
|
|
@@ -4540,9 +4704,9 @@ const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4540
4704
|
version = version.split(" ")[0];
|
|
4541
4705
|
}
|
|
4542
4706
|
if (!name && group) {
|
|
4543
|
-
name =
|
|
4707
|
+
name = basename(group.replace(/\./g, "/"));
|
|
4544
4708
|
if (!group.startsWith("javax")) {
|
|
4545
|
-
group =
|
|
4709
|
+
group = dirname(group.replace(/\./g, "/"));
|
|
4546
4710
|
group = group.replace(/\//g, ".");
|
|
4547
4711
|
}
|
|
4548
4712
|
}
|
|
@@ -4602,9 +4766,9 @@ const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4602
4766
|
}
|
|
4603
4767
|
}
|
|
4604
4768
|
try {
|
|
4605
|
-
if (
|
|
4769
|
+
if (rmSync && existsSync(join(tempDir, "META-INF"))) {
|
|
4606
4770
|
// Clean up META-INF
|
|
4607
|
-
|
|
4771
|
+
rmSync(join(tempDir, "META-INF"), {
|
|
4608
4772
|
recursive: true,
|
|
4609
4773
|
force: true
|
|
4610
4774
|
});
|
|
@@ -4617,7 +4781,6 @@ const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4617
4781
|
} // if
|
|
4618
4782
|
return pkgList;
|
|
4619
4783
|
};
|
|
4620
|
-
exports.extractJarArchive = extractJarArchive;
|
|
4621
4784
|
|
|
4622
4785
|
/**
|
|
4623
4786
|
* Determine the version of SBT used in compilation of this project.
|
|
@@ -4627,18 +4790,17 @@ exports.extractJarArchive = extractJarArchive;
|
|
|
4627
4790
|
*
|
|
4628
4791
|
* @param {string} projectPath Path to the SBT project
|
|
4629
4792
|
*/
|
|
4630
|
-
const determineSbtVersion = function (projectPath) {
|
|
4631
|
-
const buildPropFile =
|
|
4632
|
-
if (
|
|
4793
|
+
export const determineSbtVersion = function (projectPath) {
|
|
4794
|
+
const buildPropFile = join(projectPath, "project", "build.properties");
|
|
4795
|
+
if (existsSync(buildPropFile)) {
|
|
4633
4796
|
let properties = propertiesReader(buildPropFile);
|
|
4634
4797
|
let property = properties.get("sbt.version");
|
|
4635
|
-
if (property != null &&
|
|
4798
|
+
if (property != null && valid(property)) {
|
|
4636
4799
|
return property;
|
|
4637
4800
|
}
|
|
4638
4801
|
}
|
|
4639
4802
|
return null;
|
|
4640
4803
|
};
|
|
4641
|
-
exports.determineSbtVersion = determineSbtVersion;
|
|
4642
4804
|
|
|
4643
4805
|
/**
|
|
4644
4806
|
* Adds a new plugin to the SBT project by amending its plugins list.
|
|
@@ -4652,22 +4814,17 @@ exports.determineSbtVersion = determineSbtVersion;
|
|
|
4652
4814
|
* @param {string} projectPath Path to the SBT project
|
|
4653
4815
|
* @param {string} plugin Name of the plugin to add
|
|
4654
4816
|
*/
|
|
4655
|
-
const addPlugin = function (projectPath, plugin) {
|
|
4817
|
+
export const addPlugin = function (projectPath, plugin) {
|
|
4656
4818
|
const pluginsFile = sbtPluginsPath(projectPath);
|
|
4657
4819
|
var originalPluginsFile = null;
|
|
4658
|
-
if (
|
|
4820
|
+
if (existsSync(pluginsFile)) {
|
|
4659
4821
|
originalPluginsFile = pluginsFile + ".cdxgen";
|
|
4660
|
-
|
|
4661
|
-
pluginsFile,
|
|
4662
|
-
originalPluginsFile,
|
|
4663
|
-
fs.constants.COPYFILE_FICLONE
|
|
4664
|
-
);
|
|
4822
|
+
copyFileSync(pluginsFile, originalPluginsFile, constants.COPYFILE_FICLONE);
|
|
4665
4823
|
}
|
|
4666
4824
|
|
|
4667
|
-
|
|
4825
|
+
writeFileSync(pluginsFile, plugin, { flag: "a" });
|
|
4668
4826
|
return originalPluginsFile;
|
|
4669
4827
|
};
|
|
4670
|
-
exports.addPlugin = addPlugin;
|
|
4671
4828
|
|
|
4672
4829
|
/**
|
|
4673
4830
|
* Cleans up modifications to the project's plugins' file made by the
|
|
@@ -4676,38 +4833,36 @@ exports.addPlugin = addPlugin;
|
|
|
4676
4833
|
* @param {string} projectPath Path to the SBT project
|
|
4677
4834
|
* @param {string} originalPluginsFile Location of the original plugins file, if any
|
|
4678
4835
|
*/
|
|
4679
|
-
const cleanupPlugin = function (projectPath, originalPluginsFile) {
|
|
4836
|
+
export const cleanupPlugin = function (projectPath, originalPluginsFile) {
|
|
4680
4837
|
const pluginsFile = sbtPluginsPath(projectPath);
|
|
4681
|
-
if (
|
|
4838
|
+
if (existsSync(pluginsFile)) {
|
|
4682
4839
|
if (!originalPluginsFile) {
|
|
4683
4840
|
// just remove the file, it was never there
|
|
4684
|
-
|
|
4685
|
-
return !
|
|
4841
|
+
unlinkSync(pluginsFile);
|
|
4842
|
+
return !existsSync(pluginsFile);
|
|
4686
4843
|
} else {
|
|
4687
4844
|
// Bring back the original file
|
|
4688
|
-
|
|
4845
|
+
copyFileSync(
|
|
4689
4846
|
originalPluginsFile,
|
|
4690
4847
|
pluginsFile,
|
|
4691
|
-
|
|
4848
|
+
constants.COPYFILE_FICLONE
|
|
4692
4849
|
);
|
|
4693
|
-
|
|
4850
|
+
unlinkSync(originalPluginsFile);
|
|
4694
4851
|
return true;
|
|
4695
4852
|
}
|
|
4696
4853
|
} else {
|
|
4697
4854
|
return false;
|
|
4698
4855
|
}
|
|
4699
4856
|
};
|
|
4700
|
-
exports.cleanupPlugin = cleanupPlugin;
|
|
4701
4857
|
|
|
4702
4858
|
/**
|
|
4703
4859
|
* Returns a default location of the plugins file.
|
|
4704
4860
|
*
|
|
4705
4861
|
* @param {string} projectPath Path to the SBT project
|
|
4706
4862
|
*/
|
|
4707
|
-
const sbtPluginsPath = function (projectPath) {
|
|
4708
|
-
return
|
|
4863
|
+
export const sbtPluginsPath = function (projectPath) {
|
|
4864
|
+
return join(projectPath, "project", "plugins.sbt");
|
|
4709
4865
|
};
|
|
4710
|
-
exports.sbtPluginsPath = sbtPluginsPath;
|
|
4711
4866
|
|
|
4712
4867
|
/**
|
|
4713
4868
|
* Method to read a single file entry from a zip file
|
|
@@ -4717,7 +4872,7 @@ exports.sbtPluginsPath = sbtPluginsPath;
|
|
|
4717
4872
|
*
|
|
4718
4873
|
* @returns File contents
|
|
4719
4874
|
*/
|
|
4720
|
-
const readZipEntry = async function (zipFile, filePattern) {
|
|
4875
|
+
export const readZipEntry = async function (zipFile, filePattern) {
|
|
4721
4876
|
let retData = undefined;
|
|
4722
4877
|
try {
|
|
4723
4878
|
const zip = new StreamZip.async({ file: zipFile });
|
|
@@ -4742,7 +4897,6 @@ const readZipEntry = async function (zipFile, filePattern) {
|
|
|
4742
4897
|
}
|
|
4743
4898
|
return retData;
|
|
4744
4899
|
};
|
|
4745
|
-
exports.readZipEntry = readZipEntry;
|
|
4746
4900
|
|
|
4747
4901
|
/**
|
|
4748
4902
|
* Method to return the gradle command to use.
|
|
@@ -4750,39 +4904,38 @@ exports.readZipEntry = readZipEntry;
|
|
|
4750
4904
|
* @param {string} srcPath Path to look for gradlew wrapper
|
|
4751
4905
|
* @param {string} rootPath Root directory to look for gradlew wrapper
|
|
4752
4906
|
*/
|
|
4753
|
-
const getGradleCommand = (srcPath, rootPath) => {
|
|
4907
|
+
export const getGradleCommand = (srcPath, rootPath) => {
|
|
4754
4908
|
let gradleCmd = "gradle";
|
|
4755
4909
|
|
|
4756
4910
|
let findGradleFile = "gradlew";
|
|
4757
|
-
if (
|
|
4911
|
+
if (platform() == "win32") {
|
|
4758
4912
|
findGradleFile = "gradlew.bat";
|
|
4759
4913
|
}
|
|
4760
4914
|
|
|
4761
|
-
if (
|
|
4915
|
+
if (existsSync(join(srcPath, findGradleFile))) {
|
|
4762
4916
|
// Use local gradle wrapper if available
|
|
4763
4917
|
// Enable execute permission
|
|
4764
4918
|
try {
|
|
4765
|
-
|
|
4919
|
+
chmodSync(join(srcPath, findGradleFile), 0o775);
|
|
4766
4920
|
} catch (e) {
|
|
4767
4921
|
// continue regardless of error
|
|
4768
4922
|
}
|
|
4769
|
-
gradleCmd =
|
|
4770
|
-
} else if (rootPath &&
|
|
4923
|
+
gradleCmd = resolve(join(srcPath, findGradleFile));
|
|
4924
|
+
} else if (rootPath && existsSync(join(rootPath, findGradleFile))) {
|
|
4771
4925
|
// Check if the root directory has a wrapper script
|
|
4772
4926
|
try {
|
|
4773
|
-
|
|
4927
|
+
chmodSync(join(rootPath, findGradleFile), 0o775);
|
|
4774
4928
|
} catch (e) {
|
|
4775
4929
|
// continue regardless of error
|
|
4776
4930
|
}
|
|
4777
|
-
gradleCmd =
|
|
4931
|
+
gradleCmd = resolve(join(rootPath, findGradleFile));
|
|
4778
4932
|
} else if (process.env.GRADLE_CMD) {
|
|
4779
4933
|
gradleCmd = process.env.GRADLE_CMD;
|
|
4780
4934
|
} else if (process.env.GRADLE_HOME) {
|
|
4781
|
-
gradleCmd =
|
|
4935
|
+
gradleCmd = join(process.env.GRADLE_HOME, "bin", "gradle");
|
|
4782
4936
|
}
|
|
4783
4937
|
return gradleCmd;
|
|
4784
4938
|
};
|
|
4785
|
-
exports.getGradleCommand = getGradleCommand;
|
|
4786
4939
|
|
|
4787
4940
|
/**
|
|
4788
4941
|
* Method to return the maven command to use.
|
|
@@ -4790,36 +4943,299 @@ exports.getGradleCommand = getGradleCommand;
|
|
|
4790
4943
|
* @param {string} srcPath Path to look for maven wrapper
|
|
4791
4944
|
* @param {string} rootPath Root directory to look for maven wrapper
|
|
4792
4945
|
*/
|
|
4793
|
-
const getMavenCommand = (srcPath, rootPath) => {
|
|
4946
|
+
export const getMavenCommand = (srcPath, rootPath) => {
|
|
4794
4947
|
let mavenCmd = "mvn";
|
|
4795
4948
|
|
|
4796
4949
|
let findMavenFile = "mvnw";
|
|
4797
|
-
if (
|
|
4950
|
+
if (platform() == "win32") {
|
|
4798
4951
|
findMavenFile = "mvnw.bat";
|
|
4799
4952
|
}
|
|
4800
4953
|
|
|
4801
|
-
if (
|
|
4954
|
+
if (existsSync(join(srcPath, findMavenFile))) {
|
|
4802
4955
|
// Use local maven wrapper if available
|
|
4803
4956
|
// Enable execute permission
|
|
4804
4957
|
try {
|
|
4805
|
-
|
|
4958
|
+
chmodSync(join(srcPath, findMavenFile), 0o775);
|
|
4806
4959
|
} catch (e) {
|
|
4807
4960
|
// continue regardless of error
|
|
4808
4961
|
}
|
|
4809
|
-
mavenCmd =
|
|
4810
|
-
} else if (rootPath &&
|
|
4962
|
+
mavenCmd = resolve(join(srcPath, findMavenFile));
|
|
4963
|
+
} else if (rootPath && existsSync(join(rootPath, findMavenFile))) {
|
|
4811
4964
|
// Check if the root directory has a wrapper script
|
|
4812
4965
|
try {
|
|
4813
|
-
|
|
4966
|
+
chmodSync(join(rootPath, findMavenFile), 0o775);
|
|
4814
4967
|
} catch (e) {
|
|
4815
4968
|
// continue regardless of error
|
|
4816
4969
|
}
|
|
4817
|
-
mavenCmd =
|
|
4970
|
+
mavenCmd = resolve(join(rootPath, findMavenFile));
|
|
4818
4971
|
} else if (process.env.MVN_CMD || process.env.MAVEN_CMD) {
|
|
4819
4972
|
mavenCmd = process.env.MVN_CMD || process.env.MAVEN_CMD;
|
|
4820
4973
|
} else if (process.env.MAVEN_HOME) {
|
|
4821
|
-
mavenCmd =
|
|
4974
|
+
mavenCmd = join(process.env.MAVEN_HOME, "bin", "mvn");
|
|
4822
4975
|
}
|
|
4823
4976
|
return mavenCmd;
|
|
4824
4977
|
};
|
|
4825
|
-
|
|
4978
|
+
|
|
4979
|
+
/**
|
|
4980
|
+
* Retrieves the atom command by referring to various environment variables
|
|
4981
|
+
*/
|
|
4982
|
+
export const getAtomCommand = () => {
|
|
4983
|
+
if (process.env.ATOM_CMD) {
|
|
4984
|
+
return process.env.ATOM_CMD;
|
|
4985
|
+
}
|
|
4986
|
+
if (process.env.ATOM_HOME) {
|
|
4987
|
+
return join(process.env.ATOM_HOME, "bin", "atom");
|
|
4988
|
+
}
|
|
4989
|
+
const NODE_CMD = process.env.NODE_CMD || "node";
|
|
4990
|
+
const localAtom = join(
|
|
4991
|
+
dirName,
|
|
4992
|
+
"node_modules",
|
|
4993
|
+
"@appthreat",
|
|
4994
|
+
"atom",
|
|
4995
|
+
"index.js"
|
|
4996
|
+
);
|
|
4997
|
+
if (existsSync(localAtom)) {
|
|
4998
|
+
return `${NODE_CMD} ${localAtom}`;
|
|
4999
|
+
}
|
|
5000
|
+
return "atom";
|
|
5001
|
+
};
|
|
5002
|
+
|
|
5003
|
+
export const executeAtom = (src, args) => {
|
|
5004
|
+
let ATOM_BIN = getAtomCommand();
|
|
5005
|
+
if (ATOM_BIN.includes(" ")) {
|
|
5006
|
+
const tmpA = ATOM_BIN.split(" ");
|
|
5007
|
+
if (tmpA && tmpA.length > 1) {
|
|
5008
|
+
ATOM_BIN = tmpA[0];
|
|
5009
|
+
args.unshift(tmpA[1]);
|
|
5010
|
+
}
|
|
5011
|
+
}
|
|
5012
|
+
const freeMemoryGB = Math.floor(freemem() / 1024 / 1024 / 1024);
|
|
5013
|
+
if (DEBUG_MODE) {
|
|
5014
|
+
console.log("Execuing", ATOM_BIN, args.join(" "));
|
|
5015
|
+
}
|
|
5016
|
+
const env = {
|
|
5017
|
+
...process.env,
|
|
5018
|
+
JAVA_OPTS: `-Xms${freeMemoryGB}G -Xmx${freeMemoryGB}G`
|
|
5019
|
+
};
|
|
5020
|
+
const result = spawnSync(ATOM_BIN, args, {
|
|
5021
|
+
cwd: src,
|
|
5022
|
+
encoding: "utf-8",
|
|
5023
|
+
timeout: TIMEOUT_MS,
|
|
5024
|
+
env
|
|
5025
|
+
});
|
|
5026
|
+
if (DEBUG_MODE) {
|
|
5027
|
+
if (result.stdout) {
|
|
5028
|
+
console.log(result.stdout);
|
|
5029
|
+
}
|
|
5030
|
+
if (result.stderr) {
|
|
5031
|
+
console.log(result.stderr);
|
|
5032
|
+
}
|
|
5033
|
+
}
|
|
5034
|
+
return true;
|
|
5035
|
+
};
|
|
5036
|
+
|
|
5037
|
+
/**
|
|
5038
|
+
* Find the imported modules in the application with atom parsedeps command
|
|
5039
|
+
*
|
|
5040
|
+
* @param {string} src
|
|
5041
|
+
* @param {string} language
|
|
5042
|
+
* @returns List of imported modules
|
|
5043
|
+
*/
|
|
5044
|
+
export const findAppModules = function (src, language) {
|
|
5045
|
+
const tempDir = mkdtempSync(join(tmpdir(), "atom-deps-"));
|
|
5046
|
+
const atomFile = join(tempDir, "app.atom");
|
|
5047
|
+
const slicesFile = join(tempDir, "slices.json");
|
|
5048
|
+
let retList = [];
|
|
5049
|
+
const args = [
|
|
5050
|
+
"parsedeps",
|
|
5051
|
+
"-l",
|
|
5052
|
+
language,
|
|
5053
|
+
"-o",
|
|
5054
|
+
resolve(atomFile),
|
|
5055
|
+
"--slice-outfile",
|
|
5056
|
+
resolve(slicesFile),
|
|
5057
|
+
resolve(src)
|
|
5058
|
+
];
|
|
5059
|
+
executeAtom(src, args);
|
|
5060
|
+
if (existsSync(slicesFile)) {
|
|
5061
|
+
const slicesData = JSON.parse(readFileSync(slicesFile), "utf8");
|
|
5062
|
+
if (slicesData && Object.keys(slicesData) && slicesData.modules) {
|
|
5063
|
+
retList = slicesData.modules;
|
|
5064
|
+
}
|
|
5065
|
+
}
|
|
5066
|
+
// Clean up
|
|
5067
|
+
if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
|
|
5068
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
5069
|
+
}
|
|
5070
|
+
return retList;
|
|
5071
|
+
};
|
|
5072
|
+
|
|
5073
|
+
/**
|
|
5074
|
+
* Execute pip freeze by creating a virtual env in a temp directory
|
|
5075
|
+
*
|
|
5076
|
+
* @param {string} basePath Base path
|
|
5077
|
+
* @param {string} reqOrSetupFile Requirements or setup.py file
|
|
5078
|
+
* @returns List of packages from the virtual env
|
|
5079
|
+
*/
|
|
5080
|
+
export const executePipFreezeInVenv = async (basePath, reqOrSetupFile) => {
|
|
5081
|
+
let pkgList = [];
|
|
5082
|
+
let result = undefined;
|
|
5083
|
+
const tempDir = mkdtempSync(join(tmpdir(), "cdxgen-venv-"));
|
|
5084
|
+
const env = {
|
|
5085
|
+
...process.env
|
|
5086
|
+
};
|
|
5087
|
+
/**
|
|
5088
|
+
* Let's start with an attempt to create a new temporary virtual environment in case we aren't in one
|
|
5089
|
+
*
|
|
5090
|
+
* By checking the environment variable "VIRTUAL_ENV" we decide whether to create an env or not
|
|
5091
|
+
*/
|
|
5092
|
+
if (!process.env.VIRTUAL_ENV) {
|
|
5093
|
+
result = spawnSync(PYTHON_CMD, ["-m", "venv", tempDir]);
|
|
5094
|
+
if (result.status !== 0 || result.error) {
|
|
5095
|
+
if (DEBUG_MODE) {
|
|
5096
|
+
console.log(result.stderr);
|
|
5097
|
+
}
|
|
5098
|
+
} else {
|
|
5099
|
+
env.VIRTUAL_ENV = tempDir;
|
|
5100
|
+
env.PATH = `${join(tempDir, "bin")}${_delimiter}${
|
|
5101
|
+
process.env.PATH || ""
|
|
5102
|
+
}`;
|
|
5103
|
+
}
|
|
5104
|
+
}
|
|
5105
|
+
/**
|
|
5106
|
+
* We now have a temporary virtual environment so we can attempt to install the project and perform
|
|
5107
|
+
* pip freeze to collect the packages that got installed.
|
|
5108
|
+
* This step is accurate but not reproducible since the resulting list could differ based on various factors
|
|
5109
|
+
* such as the version of python, pip, os, pypi.org availability (and weather?)
|
|
5110
|
+
*/
|
|
5111
|
+
if (tempDir === env.VIRTUAL_ENV) {
|
|
5112
|
+
let pipInstallArgs = [
|
|
5113
|
+
"-m",
|
|
5114
|
+
"pip",
|
|
5115
|
+
"install",
|
|
5116
|
+
"--disable-pip-version-check"
|
|
5117
|
+
];
|
|
5118
|
+
// Requirements.txt could be called with any name so best to check for not setup.py and not pyproject.toml
|
|
5119
|
+
if (
|
|
5120
|
+
!reqOrSetupFile.endsWith("setup.py") &&
|
|
5121
|
+
!reqOrSetupFile.endsWith("pyproject.toml")
|
|
5122
|
+
) {
|
|
5123
|
+
pipInstallArgs.push("-r");
|
|
5124
|
+
pipInstallArgs.push(resolve(reqOrSetupFile));
|
|
5125
|
+
} else {
|
|
5126
|
+
pipInstallArgs.push(resolve(basePath));
|
|
5127
|
+
}
|
|
5128
|
+
// Attempt to perform pip install
|
|
5129
|
+
result = spawnSync(PYTHON_CMD, pipInstallArgs, {
|
|
5130
|
+
cwd: basePath,
|
|
5131
|
+
encoding: "utf-8",
|
|
5132
|
+
timeout: TIMEOUT_MS,
|
|
5133
|
+
env
|
|
5134
|
+
});
|
|
5135
|
+
if (result.status !== 0 || result.error) {
|
|
5136
|
+
let versionRelatedError = false;
|
|
5137
|
+
if (
|
|
5138
|
+
result.stderr &&
|
|
5139
|
+
(result.stderr.includes(
|
|
5140
|
+
"Could not find a version that satisfies the requirement"
|
|
5141
|
+
) ||
|
|
5142
|
+
result.stderr.includes("No matching distribution found for"))
|
|
5143
|
+
) {
|
|
5144
|
+
versionRelatedError = true;
|
|
5145
|
+
console.log(
|
|
5146
|
+
"The version or the version specifiers used for a dependency is invalid. Resolve the below error to improve SBoM accuracy."
|
|
5147
|
+
);
|
|
5148
|
+
console.log(result.stderr);
|
|
5149
|
+
}
|
|
5150
|
+
if (!versionRelatedError && DEBUG_MODE) {
|
|
5151
|
+
console.log("args used:", pipInstallArgs);
|
|
5152
|
+
console.log(
|
|
5153
|
+
"Possible build errors detected. The resulting list in the SBoM would therefore be incomplete.\nTry installing any missing build tools or development libraries to improve the accuracy."
|
|
5154
|
+
);
|
|
5155
|
+
if (platform() == "win32") {
|
|
5156
|
+
console.log(
|
|
5157
|
+
"- Install the appropriate compilers and build tools on Windows by following this documentation - https://wiki.python.org/moin/WindowsCompilers"
|
|
5158
|
+
);
|
|
5159
|
+
} else {
|
|
5160
|
+
console.log(
|
|
5161
|
+
"- For example, you may have to install gcc, gcc-c++ compiler, make tools and additional development libraries using apt-get or yum package manager."
|
|
5162
|
+
);
|
|
5163
|
+
}
|
|
5164
|
+
console.log(
|
|
5165
|
+
"- Certain projects would only build with specific versions of python and OS. Data science and ML related projects might require a conda/anaconda distribution."
|
|
5166
|
+
);
|
|
5167
|
+
console.log("- Check if any git submodules have to be initialized.");
|
|
5168
|
+
}
|
|
5169
|
+
}
|
|
5170
|
+
/**
|
|
5171
|
+
* At this point, the previous attempt to do a pip install might have failed and we might have an unclean virtual environment with an incomplete list
|
|
5172
|
+
* The position taken by cdxgen is "Some SBoM is better than no SBoM", so we proceed to collecting the dependencies that got installed with pip freeze
|
|
5173
|
+
*/
|
|
5174
|
+
let pipFreezeArgs = [
|
|
5175
|
+
"-m",
|
|
5176
|
+
"pip",
|
|
5177
|
+
"freeze",
|
|
5178
|
+
"-l",
|
|
5179
|
+
"--exclude-editable",
|
|
5180
|
+
"--disable-pip-version-check"
|
|
5181
|
+
];
|
|
5182
|
+
if (
|
|
5183
|
+
!reqOrSetupFile.endsWith("setup.py") &&
|
|
5184
|
+
!reqOrSetupFile.endsWith("pyproject.toml")
|
|
5185
|
+
) {
|
|
5186
|
+
pipFreezeArgs.push("-r");
|
|
5187
|
+
pipFreezeArgs.push(resolve(reqOrSetupFile));
|
|
5188
|
+
}
|
|
5189
|
+
result = spawnSync(PYTHON_CMD, pipFreezeArgs, {
|
|
5190
|
+
cwd: basePath,
|
|
5191
|
+
encoding: "utf-8",
|
|
5192
|
+
timeout: TIMEOUT_MS,
|
|
5193
|
+
env
|
|
5194
|
+
});
|
|
5195
|
+
if (result.status === 0 && result.stdout) {
|
|
5196
|
+
// We now a list from pip freeze that could be parsed to obtain a list
|
|
5197
|
+
// We need to iterate that this list is not reproducible and could vary based on the environment
|
|
5198
|
+
const reqData = Buffer.from(result.stdout).toString();
|
|
5199
|
+
const dlist = await parseReqFile(reqData, false);
|
|
5200
|
+
if (dlist && dlist.length) {
|
|
5201
|
+
pkgList = pkgList.concat(dlist);
|
|
5202
|
+
}
|
|
5203
|
+
} else if (result.status !== 0 || result.error) {
|
|
5204
|
+
if (DEBUG_MODE) {
|
|
5205
|
+
console.log(result.stderr, "args used:", pipFreezeArgs);
|
|
5206
|
+
}
|
|
5207
|
+
}
|
|
5208
|
+
} else {
|
|
5209
|
+
if (DEBUG_MODE) {
|
|
5210
|
+
console.log(
|
|
5211
|
+
"NOTE: Setup and activate a python virtual environment for this project prior to invoking cdxgen to improve SBoM accuracy."
|
|
5212
|
+
);
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
5215
|
+
// Clean up
|
|
5216
|
+
if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
|
|
5217
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
5218
|
+
}
|
|
5219
|
+
return pkgList;
|
|
5220
|
+
};
|
|
5221
|
+
|
|
5222
|
+
// taken from a very old package https://github.com/keithamus/parse-packagejson-name/blob/master/index.js
|
|
5223
|
+
export const parsePackageJsonName = (name) => {
|
|
5224
|
+
const nameRegExp = /^(?:@([^/]+)\/)?(([^.]+)(?:\.(.*))?)$/;
|
|
5225
|
+
const returnObject = {
|
|
5226
|
+
scope: null,
|
|
5227
|
+
fullName: "",
|
|
5228
|
+
projectName: "",
|
|
5229
|
+
moduleName: ""
|
|
5230
|
+
};
|
|
5231
|
+
const match = (typeof name === "object" ? name.name || "" : name || "").match(
|
|
5232
|
+
nameRegExp
|
|
5233
|
+
);
|
|
5234
|
+
if (match) {
|
|
5235
|
+
returnObject.scope = match[1] || null;
|
|
5236
|
+
returnObject.fullName = match[2] || match[0];
|
|
5237
|
+
returnObject.projectName = match[3] === match[2] ? null : match[3];
|
|
5238
|
+
returnObject.moduleName = match[4] || match[2] || null;
|
|
5239
|
+
}
|
|
5240
|
+
return returnObject;
|
|
5241
|
+
};
|