@cyclonedx/cdxgen 8.1.9 → 8.2.1
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 +1 -0
- package/binary.js +3 -1
- package/docker.js +21 -3
- package/index.js +146 -7
- package/package.json +1 -1
- package/server.js +1 -1
- package/utils.js +207 -5
- package/utils.test.js +266 -90
package/README.md
CHANGED
|
@@ -23,6 +23,7 @@ When used with plugins, cdxgen could generate an SBoM for Linux docker images an
|
|
|
23
23
|
| elixir | mix.lock | Yes |
|
|
24
24
|
| c/c++ | conan.lock, conanfile.txt | Yes only for conan.lock |
|
|
25
25
|
| clojure | Clojure CLI (deps.edn), Leiningen (project.clj) | Yes unless the files are parsed manually due to lack of clojure cli or leiningen command |
|
|
26
|
+
| swift | Package.resolved, Package.swift (swiftpm) | Yes |
|
|
26
27
|
| docker / oci image | All supported languages. Linux OS packages with plugins [4] | Best effort based on lock files |
|
|
27
28
|
| GitHub Actions | .github/workflows/\*.yml | N/A |
|
|
28
29
|
| Linux | All supported languages. Linux OS packages with plugins [5] | Best effort based on lock files |
|
package/binary.js
CHANGED
|
@@ -312,7 +312,9 @@ const getOSPackages = (src) => {
|
|
|
312
312
|
if (DEBUG_MODE) {
|
|
313
313
|
console.log(`Cleaning up ${tempDir}`);
|
|
314
314
|
}
|
|
315
|
-
fs.rmSync
|
|
315
|
+
if (fs.rmSync) {
|
|
316
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
317
|
+
}
|
|
316
318
|
}
|
|
317
319
|
if (tmpBom && tmpBom.components) {
|
|
318
320
|
for (const comp of tmpBom.components) {
|
package/docker.js
CHANGED
|
@@ -117,7 +117,11 @@ const getDefaultOptions = () => {
|
|
|
117
117
|
? "npipe//./pipe/docker_engine:"
|
|
118
118
|
: "unix:/var/run/docker.sock:";
|
|
119
119
|
*/
|
|
120
|
-
opts.prefixUrl = isWin
|
|
120
|
+
opts.prefixUrl = isWin
|
|
121
|
+
? WIN_LOCAL_TLS
|
|
122
|
+
: isDockerRootless
|
|
123
|
+
? `unix:${os.homedir()}/.docker/run/docker.sock:`
|
|
124
|
+
: "unix:/var/run/docker.sock:";
|
|
121
125
|
}
|
|
122
126
|
}
|
|
123
127
|
} else {
|
|
@@ -162,6 +166,18 @@ const getConnection = async (options) => {
|
|
|
162
166
|
}
|
|
163
167
|
} catch (err) {
|
|
164
168
|
// console.log(err, opts);
|
|
169
|
+
opts.prefixUrl = `unix:${os.homedir()}/.docker/run/docker.sock:`;
|
|
170
|
+
try {
|
|
171
|
+
await got.get("_ping", opts);
|
|
172
|
+
dockerConn = got.extend(opts);
|
|
173
|
+
isDockerRootless = true;
|
|
174
|
+
if (DEBUG_MODE) {
|
|
175
|
+
console.log("Docker service in rootless mode detected!");
|
|
176
|
+
}
|
|
177
|
+
return dockerConn;
|
|
178
|
+
} catch (err) {
|
|
179
|
+
// console.log(err, opts);
|
|
180
|
+
}
|
|
165
181
|
try {
|
|
166
182
|
if (isWin) {
|
|
167
183
|
opts.prefixUrl = WIN_LOCAL_TLS;
|
|
@@ -323,7 +339,7 @@ const getImage = async (fullImageName) => {
|
|
|
323
339
|
}
|
|
324
340
|
try {
|
|
325
341
|
localData = await makeRequest(`images/${repo}/json`);
|
|
326
|
-
if (DEBUG_MODE) {
|
|
342
|
+
if (DEBUG_MODE && localData) {
|
|
327
343
|
console.log(localData);
|
|
328
344
|
}
|
|
329
345
|
} catch (err) {
|
|
@@ -603,7 +619,9 @@ const exportImage = async (fullImageName) => {
|
|
|
603
619
|
if (DEBUG_MODE) {
|
|
604
620
|
console.log(`Cleaning up ${imageTarFile}`);
|
|
605
621
|
}
|
|
606
|
-
fs.rmSync
|
|
622
|
+
if (fs.rmSync) {
|
|
623
|
+
fs.rmSync(imageTarFile, { force: true });
|
|
624
|
+
}
|
|
607
625
|
}
|
|
608
626
|
} else {
|
|
609
627
|
let client = await getConnection();
|
package/index.js
CHANGED
|
@@ -44,6 +44,11 @@ if (process.env.PIP_CMD) {
|
|
|
44
44
|
PIP_CMD = process.env.PIP_CMD;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
let SWIFT_CMD = "swift";
|
|
48
|
+
if (process.env.SWIFT_CMD) {
|
|
49
|
+
SWIFT_CMD = process.env.SWIFT_CMD;
|
|
50
|
+
}
|
|
51
|
+
|
|
47
52
|
// Construct sbt cache directory
|
|
48
53
|
let SBT_CACHE_DIR =
|
|
49
54
|
process.env.SBT_CACHE_DIR || pathLib.join(os.homedir(), ".ivy2", "cache");
|
|
@@ -61,6 +66,29 @@ const HASH_PATTERN =
|
|
|
61
66
|
// Timeout milliseconds. Default 10 mins
|
|
62
67
|
const TIMEOUT_MS = parseInt(process.env.CDXGEN_TIMEOUT_MS) || 10 * 60 * 1000;
|
|
63
68
|
|
|
69
|
+
const createDefaultParentComponent = (path) => {
|
|
70
|
+
// Create a parent component based on the directory name
|
|
71
|
+
let dirName = pathLib.dirname(path);
|
|
72
|
+
const tmpA = dirName.split(pathLib.sep);
|
|
73
|
+
dirName = tmpA[tmpA.length - 1];
|
|
74
|
+
const parentComponent = {
|
|
75
|
+
group: "",
|
|
76
|
+
name: dirName,
|
|
77
|
+
type: "application"
|
|
78
|
+
};
|
|
79
|
+
const ppurl = new PackageURL(
|
|
80
|
+
"application",
|
|
81
|
+
parentComponent.group,
|
|
82
|
+
parentComponent.name,
|
|
83
|
+
parentComponent.version,
|
|
84
|
+
null,
|
|
85
|
+
null
|
|
86
|
+
).toString();
|
|
87
|
+
parentComponent["bom-ref"] = ppurl;
|
|
88
|
+
parentComponent["purl"] = ppurl;
|
|
89
|
+
return parentComponent;
|
|
90
|
+
};
|
|
91
|
+
|
|
64
92
|
const determineParentComponent = (options) => {
|
|
65
93
|
let parentComponent = undefined;
|
|
66
94
|
if (options.projectName && options.projectVersion) {
|
|
@@ -491,7 +519,10 @@ function addComponent(
|
|
|
491
519
|
// Skip @types package for npm
|
|
492
520
|
if (
|
|
493
521
|
ptype == "npm" &&
|
|
494
|
-
(group === "types" ||
|
|
522
|
+
(group === "types" ||
|
|
523
|
+
group === "@types" ||
|
|
524
|
+
!name ||
|
|
525
|
+
name.startsWith("@types"))
|
|
495
526
|
) {
|
|
496
527
|
return;
|
|
497
528
|
}
|
|
@@ -503,7 +534,14 @@ function addComponent(
|
|
|
503
534
|
|
|
504
535
|
let purl =
|
|
505
536
|
pkg.purl ||
|
|
506
|
-
new PackageURL(
|
|
537
|
+
new PackageURL(
|
|
538
|
+
ptype,
|
|
539
|
+
encodeURIComponent(group),
|
|
540
|
+
encodeURIComponent(name),
|
|
541
|
+
version,
|
|
542
|
+
pkg.qualifiers,
|
|
543
|
+
pkg.subpath
|
|
544
|
+
);
|
|
507
545
|
let purlString = purl.toString();
|
|
508
546
|
purlString = decodeURIComponent(purlString);
|
|
509
547
|
let description = { "#cdata": pkg.description };
|
|
@@ -1008,13 +1046,13 @@ const createJavaBom = async (path, options) => {
|
|
|
1008
1046
|
"Resolve the above maven error. This could be due to the following:\n"
|
|
1009
1047
|
);
|
|
1010
1048
|
console.log(
|
|
1011
|
-
"1. Java version requirement
|
|
1049
|
+
"1. Java version requirement: cdxgen container image bundles Java 17 with gradle 8 which might be incompatible."
|
|
1012
1050
|
);
|
|
1013
1051
|
console.log(
|
|
1014
|
-
"2. Private
|
|
1052
|
+
"2. Private dependencies cannot be downloaded: Check if any additional arguments must be passed to maven and set them via MVN_ARGS environment variable."
|
|
1015
1053
|
);
|
|
1016
1054
|
console.log(
|
|
1017
|
-
"3. Check if all required environment variables including any maven profile arguments are passed correctly to this tool"
|
|
1055
|
+
"3. Check if all required environment variables including any maven profile arguments are passed correctly to this tool."
|
|
1018
1056
|
);
|
|
1019
1057
|
// Do not fall back to methods that can produce incomplete results when failOnError is set
|
|
1020
1058
|
options.failOnError && process.exit(1);
|
|
@@ -1125,7 +1163,7 @@ const createJavaBom = async (path, options) => {
|
|
|
1125
1163
|
console.error(result.stdout, result.stderr);
|
|
1126
1164
|
}
|
|
1127
1165
|
console.log(
|
|
1128
|
-
"1. Check if the correct version of java and gradle are installed and available in PATH. For example, some project might require Java 11 with gradle 7."
|
|
1166
|
+
"1. Check if the correct version of java and gradle are installed and available in PATH. For example, some project might require Java 11 with gradle 7.\n cdxgen container image bundles Java 17 with gradle 8 which might be incompatible."
|
|
1129
1167
|
);
|
|
1130
1168
|
options.failOnError && process.exit(1);
|
|
1131
1169
|
}
|
|
@@ -1251,7 +1289,7 @@ const createJavaBom = async (path, options) => {
|
|
|
1251
1289
|
}
|
|
1252
1290
|
if (DEBUG_MODE || !result.stderr || options.failOnError) {
|
|
1253
1291
|
console.log(
|
|
1254
|
-
"1. Check if the correct version of java and gradle are installed and available in PATH. For example, some project might require Java 11 with gradle 7."
|
|
1292
|
+
"1. Check if the correct version of java and gradle are installed and available in PATH. For example, some project might require Java 11 with gradle 7.\n cdxgen container image bundles Java 17 with gradle 8 which might be incompatible."
|
|
1255
1293
|
);
|
|
1256
1294
|
console.log(
|
|
1257
1295
|
"2. When using tools such as sdkman, the init script must be invoked to set the PATH variables correctly."
|
|
@@ -2805,6 +2843,91 @@ const createHelmBom = async (path, options) => {
|
|
|
2805
2843
|
return {};
|
|
2806
2844
|
};
|
|
2807
2845
|
|
|
2846
|
+
/**
|
|
2847
|
+
* Function to create bom string for swift projects
|
|
2848
|
+
*
|
|
2849
|
+
* @param path to the project
|
|
2850
|
+
* @param options Parse options from the cli
|
|
2851
|
+
*/
|
|
2852
|
+
const createSwiftBom = async (path, options) => {
|
|
2853
|
+
const swiftFiles = utils.getAllFiles(
|
|
2854
|
+
path,
|
|
2855
|
+
(options.multiProject ? "**/" : "") + "Package*.swift"
|
|
2856
|
+
);
|
|
2857
|
+
const pkgResolvedFiles = utils.getAllFiles(
|
|
2858
|
+
path,
|
|
2859
|
+
(options.multiProject ? "**/" : "") + "Package.resolved"
|
|
2860
|
+
);
|
|
2861
|
+
let pkgList = [];
|
|
2862
|
+
let dependencies = [];
|
|
2863
|
+
let parentComponent = {};
|
|
2864
|
+
let completedPath = [];
|
|
2865
|
+
if (pkgResolvedFiles.length) {
|
|
2866
|
+
for (let f of pkgResolvedFiles) {
|
|
2867
|
+
if (!parentComponent || !Object.keys(parentComponent).length) {
|
|
2868
|
+
parentComponent = createDefaultParentComponent(f);
|
|
2869
|
+
}
|
|
2870
|
+
if (DEBUG_MODE) {
|
|
2871
|
+
console.log("Parsing", f);
|
|
2872
|
+
}
|
|
2873
|
+
const dlist = utils.parseSwiftResolved(f);
|
|
2874
|
+
if (dlist && dlist.length) {
|
|
2875
|
+
pkgList = pkgList.concat(dlist);
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
} else if (swiftFiles.length) {
|
|
2879
|
+
for (let f of swiftFiles) {
|
|
2880
|
+
const basePath = pathLib.dirname(f);
|
|
2881
|
+
if (completedPath.includes(basePath)) {
|
|
2882
|
+
continue;
|
|
2883
|
+
}
|
|
2884
|
+
let treeData = undefined;
|
|
2885
|
+
if (DEBUG_MODE) {
|
|
2886
|
+
console.log("Executing 'swift package show-dependencies' in", basePath);
|
|
2887
|
+
}
|
|
2888
|
+
const result = spawnSync(
|
|
2889
|
+
SWIFT_CMD,
|
|
2890
|
+
["package", "show-dependencies", "--format", "json"],
|
|
2891
|
+
{
|
|
2892
|
+
cwd: basePath,
|
|
2893
|
+
encoding: "utf-8",
|
|
2894
|
+
timeout: TIMEOUT_MS
|
|
2895
|
+
}
|
|
2896
|
+
);
|
|
2897
|
+
if (result.status === 0 && result.stdout) {
|
|
2898
|
+
completedPath.push(basePath);
|
|
2899
|
+
treeData = Buffer.from(result.stdout).toString();
|
|
2900
|
+
const retData = utils.parseSwiftJsonTree(treeData, f);
|
|
2901
|
+
if (retData.pkgList && retData.pkgList.length) {
|
|
2902
|
+
parentComponent = retData.pkgList.splice(0, 1)[0];
|
|
2903
|
+
parentComponent.type = "application";
|
|
2904
|
+
pkgList = pkgList.concat(retData.pkgList);
|
|
2905
|
+
}
|
|
2906
|
+
if (retData.dependenciesList) {
|
|
2907
|
+
dependencies = mergeDependencies(
|
|
2908
|
+
dependencies,
|
|
2909
|
+
retData.dependenciesList
|
|
2910
|
+
);
|
|
2911
|
+
}
|
|
2912
|
+
} else {
|
|
2913
|
+
if (DEBUG_MODE) {
|
|
2914
|
+
console.log(
|
|
2915
|
+
"Please install swift from https://www.swift.org/download/ or use the cdxgen container image"
|
|
2916
|
+
);
|
|
2917
|
+
}
|
|
2918
|
+
console.error(result.stderr);
|
|
2919
|
+
options.failOnError && process.exit(1);
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
return buildBomNSData(options, pkgList, "swift", {
|
|
2924
|
+
src: path,
|
|
2925
|
+
filename: swiftFiles.join(", "),
|
|
2926
|
+
parentComponent,
|
|
2927
|
+
dependencies
|
|
2928
|
+
});
|
|
2929
|
+
};
|
|
2930
|
+
|
|
2808
2931
|
/**
|
|
2809
2932
|
* Function to create bom string for docker compose
|
|
2810
2933
|
*
|
|
@@ -4041,6 +4164,19 @@ const createXBom = async (path, options) => {
|
|
|
4041
4164
|
if (cbFiles.length) {
|
|
4042
4165
|
return await createCloudBuildBom(path, options);
|
|
4043
4166
|
}
|
|
4167
|
+
|
|
4168
|
+
// Swift
|
|
4169
|
+
const swiftFiles = utils.getAllFiles(
|
|
4170
|
+
path,
|
|
4171
|
+
(options.multiProject ? "**/" : "") + "Package*.swift"
|
|
4172
|
+
);
|
|
4173
|
+
const pkgResolvedFiles = utils.getAllFiles(
|
|
4174
|
+
path,
|
|
4175
|
+
(options.multiProject ? "**/" : "") + "Package.resolved"
|
|
4176
|
+
);
|
|
4177
|
+
if (swiftFiles.length || pkgResolvedFiles.length) {
|
|
4178
|
+
return await createSwiftBom(path, options);
|
|
4179
|
+
}
|
|
4044
4180
|
};
|
|
4045
4181
|
|
|
4046
4182
|
/**
|
|
@@ -4287,6 +4423,9 @@ const createBom = async (path, options) => {
|
|
|
4287
4423
|
case "cloudbuild":
|
|
4288
4424
|
options.multiProject = true;
|
|
4289
4425
|
return await createCloudBuildBom(path, options);
|
|
4426
|
+
case "swift":
|
|
4427
|
+
options.multiProject = true;
|
|
4428
|
+
return await createSwiftBom(path, options);
|
|
4290
4429
|
default:
|
|
4291
4430
|
// In recurse mode return multi-language Bom
|
|
4292
4431
|
// https://github.com/cyclonedx/cdxgen/issues/95
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyclonedx/cdxgen",
|
|
3
|
-
"version": "8.1
|
|
3
|
+
"version": "8.2.1",
|
|
4
4
|
"description": "Creates CycloneDX Software Bill-of-Materials (SBOM) from source or container image",
|
|
5
5
|
"homepage": "http://github.com/cyclonedx/cdxgen",
|
|
6
6
|
"author": "Prabhu Subramanian <prabhu@appthreat.com>",
|
package/server.js
CHANGED
|
@@ -115,7 +115,7 @@ const start = async (options) => {
|
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
res.end("\n");
|
|
118
|
-
if (cleanup && srcDir && srcDir.startsWith(os.tmpdir())) {
|
|
118
|
+
if (cleanup && srcDir && srcDir.startsWith(os.tmpdir()) && fs.rmSync) {
|
|
119
119
|
console.log(`Cleaning up ${srcDir}`);
|
|
120
120
|
fs.rmSync(srcDir, { recursive: true, force: true });
|
|
121
121
|
}
|
package/utils.js
CHANGED
|
@@ -377,7 +377,7 @@ const parsePkgLock = async (pkgLockFile) => {
|
|
|
377
377
|
type: "application"
|
|
378
378
|
};
|
|
379
379
|
}
|
|
380
|
-
if (rootPkg) {
|
|
380
|
+
if (rootPkg && rootPkg.name) {
|
|
381
381
|
const purl = new PackageURL(
|
|
382
382
|
"application",
|
|
383
383
|
"",
|
|
@@ -1018,7 +1018,7 @@ exports.parsePom = parsePom;
|
|
|
1018
1018
|
*/
|
|
1019
1019
|
const parseMavenTree = function (rawOutput) {
|
|
1020
1020
|
if (!rawOutput) {
|
|
1021
|
-
return
|
|
1021
|
+
return {};
|
|
1022
1022
|
}
|
|
1023
1023
|
const deps = [];
|
|
1024
1024
|
const dependenciesList = [];
|
|
@@ -1128,7 +1128,7 @@ const parseGradleDep = function (rawOutput) {
|
|
|
1128
1128
|
level_trees[last_purl] = [];
|
|
1129
1129
|
let stack = [last_purl];
|
|
1130
1130
|
const depRegex =
|
|
1131
|
-
/^.*?--- +(?<group>[^\s:]+):(?<name>[^\s:]+)(?::(?:{strictly )?(?<versionspecified>[
|
|
1131
|
+
/^.*?--- +(?<group>[^\s:]+):(?<name>[^\s:]+)(?::(?:{strictly [[]?)?(?<versionspecified>[^,\s:}]+))?(?:})?(?:[^->]* +-> +(?<versionoverride>[^\s:]+))?/gm;
|
|
1132
1132
|
while ((match = depRegex.exec(rawOutput))) {
|
|
1133
1133
|
const [line, group, name, versionspecified, versionoverride] = match;
|
|
1134
1134
|
const version = versionoverride || versionspecified;
|
|
@@ -3773,6 +3773,207 @@ const convertOSQueryResults = function (queryCategory, queryObj, results) {
|
|
|
3773
3773
|
};
|
|
3774
3774
|
exports.convertOSQueryResults = convertOSQueryResults;
|
|
3775
3775
|
|
|
3776
|
+
const _swiftDepPkgList = (pkgList, dependenciesList, depKeys, jsonData) => {
|
|
3777
|
+
if (jsonData && jsonData.dependencies) {
|
|
3778
|
+
for (let adep of jsonData.dependencies) {
|
|
3779
|
+
const urlOrPath = adep.url || adep.path;
|
|
3780
|
+
const apkg = {
|
|
3781
|
+
group: adep.identity || "",
|
|
3782
|
+
name: adep.name,
|
|
3783
|
+
version: adep.version
|
|
3784
|
+
};
|
|
3785
|
+
const purl = new PackageURL(
|
|
3786
|
+
"swift",
|
|
3787
|
+
apkg.group,
|
|
3788
|
+
apkg.name,
|
|
3789
|
+
apkg.version,
|
|
3790
|
+
null,
|
|
3791
|
+
null
|
|
3792
|
+
);
|
|
3793
|
+
const purlString = decodeURIComponent(purl.toString());
|
|
3794
|
+
if (urlOrPath) {
|
|
3795
|
+
if (urlOrPath.startsWith("http")) {
|
|
3796
|
+
apkg.repository = { url: urlOrPath };
|
|
3797
|
+
if (apkg.path) {
|
|
3798
|
+
apkg.properties = [
|
|
3799
|
+
{
|
|
3800
|
+
name: "SrcPath",
|
|
3801
|
+
value: apkg.path
|
|
3802
|
+
}
|
|
3803
|
+
];
|
|
3804
|
+
}
|
|
3805
|
+
} else {
|
|
3806
|
+
apkg.properties = [
|
|
3807
|
+
{
|
|
3808
|
+
name: "SrcPath",
|
|
3809
|
+
value: urlOrPath
|
|
3810
|
+
}
|
|
3811
|
+
];
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
pkgList.push(apkg);
|
|
3815
|
+
// Handle the immediate dependencies before recursing
|
|
3816
|
+
if (adep.dependencies && adep.dependencies.length) {
|
|
3817
|
+
const deplist = [];
|
|
3818
|
+
for (let cdep of adep.dependencies) {
|
|
3819
|
+
const deppurl = new PackageURL(
|
|
3820
|
+
"swift",
|
|
3821
|
+
cdep.identity || "",
|
|
3822
|
+
cdep.name,
|
|
3823
|
+
cdep.version,
|
|
3824
|
+
null,
|
|
3825
|
+
null
|
|
3826
|
+
);
|
|
3827
|
+
const deppurlString = decodeURIComponent(deppurl.toString());
|
|
3828
|
+
deplist.push(deppurlString);
|
|
3829
|
+
}
|
|
3830
|
+
if (!depKeys[purlString]) {
|
|
3831
|
+
dependenciesList.push({
|
|
3832
|
+
ref: purlString,
|
|
3833
|
+
dependsOn: deplist
|
|
3834
|
+
});
|
|
3835
|
+
depKeys[purlString] = true;
|
|
3836
|
+
}
|
|
3837
|
+
if (adep.dependencies && adep.dependencies.length) {
|
|
3838
|
+
_swiftDepPkgList(pkgList, dependenciesList, depKeys, adep);
|
|
3839
|
+
}
|
|
3840
|
+
} else {
|
|
3841
|
+
if (!depKeys[purlString]) {
|
|
3842
|
+
dependenciesList.push({
|
|
3843
|
+
ref: purlString,
|
|
3844
|
+
dependsOn: []
|
|
3845
|
+
});
|
|
3846
|
+
depKeys[purlString] = true;
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
}
|
|
3851
|
+
return { pkgList, dependenciesList };
|
|
3852
|
+
};
|
|
3853
|
+
|
|
3854
|
+
/**
|
|
3855
|
+
* Parse swift dependency tree output
|
|
3856
|
+
* @param {string} rawOutput Swift dependencies json output
|
|
3857
|
+
* @param {string} pkgFile Package.swift file
|
|
3858
|
+
*/
|
|
3859
|
+
const parseSwiftJsonTree = (rawOutput, pkgFile) => {
|
|
3860
|
+
if (!rawOutput) {
|
|
3861
|
+
return {};
|
|
3862
|
+
}
|
|
3863
|
+
const pkgList = [];
|
|
3864
|
+
const dependenciesList = [];
|
|
3865
|
+
let depKeys = {};
|
|
3866
|
+
let rootPkg = {};
|
|
3867
|
+
let jsonData = {};
|
|
3868
|
+
try {
|
|
3869
|
+
jsonData = JSON.parse(rawOutput);
|
|
3870
|
+
if (jsonData && jsonData.name) {
|
|
3871
|
+
rootPkg = {
|
|
3872
|
+
group: jsonData.identity || "",
|
|
3873
|
+
name: jsonData.name,
|
|
3874
|
+
version: jsonData.version
|
|
3875
|
+
};
|
|
3876
|
+
const urlOrPath = jsonData.url || jsonData.path;
|
|
3877
|
+
if (urlOrPath) {
|
|
3878
|
+
if (urlOrPath.startsWith("http")) {
|
|
3879
|
+
rootPkg.repository = { url: urlOrPath };
|
|
3880
|
+
} else {
|
|
3881
|
+
rootPkg.properties = [
|
|
3882
|
+
{
|
|
3883
|
+
name: "SrcPath",
|
|
3884
|
+
value: urlOrPath
|
|
3885
|
+
},
|
|
3886
|
+
{
|
|
3887
|
+
name: "SrcFile",
|
|
3888
|
+
value: pkgFile
|
|
3889
|
+
}
|
|
3890
|
+
];
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
const purl = new PackageURL(
|
|
3894
|
+
"application",
|
|
3895
|
+
rootPkg.group,
|
|
3896
|
+
rootPkg.name,
|
|
3897
|
+
rootPkg.version,
|
|
3898
|
+
null,
|
|
3899
|
+
null
|
|
3900
|
+
);
|
|
3901
|
+
const purlString = decodeURIComponent(purl.toString());
|
|
3902
|
+
rootPkg["bom-ref"] = purlString;
|
|
3903
|
+
pkgList.push(rootPkg);
|
|
3904
|
+
const deplist = [];
|
|
3905
|
+
for (const rd of jsonData.dependencies) {
|
|
3906
|
+
const deppurl = new PackageURL(
|
|
3907
|
+
"swift",
|
|
3908
|
+
rd.identity || "",
|
|
3909
|
+
rd.name,
|
|
3910
|
+
rd.version,
|
|
3911
|
+
null,
|
|
3912
|
+
null
|
|
3913
|
+
);
|
|
3914
|
+
const deppurlString = decodeURIComponent(deppurl.toString());
|
|
3915
|
+
deplist.push(deppurlString);
|
|
3916
|
+
}
|
|
3917
|
+
dependenciesList.push({
|
|
3918
|
+
ref: purlString,
|
|
3919
|
+
dependsOn: deplist
|
|
3920
|
+
});
|
|
3921
|
+
_swiftDepPkgList(pkgList, dependenciesList, depKeys, jsonData);
|
|
3922
|
+
}
|
|
3923
|
+
} catch (e) {
|
|
3924
|
+
if (DEBUG_MODE) {
|
|
3925
|
+
console.log(e);
|
|
3926
|
+
}
|
|
3927
|
+
return {};
|
|
3928
|
+
}
|
|
3929
|
+
return {
|
|
3930
|
+
pkgList,
|
|
3931
|
+
dependenciesList
|
|
3932
|
+
};
|
|
3933
|
+
};
|
|
3934
|
+
exports.parseSwiftJsonTree = parseSwiftJsonTree;
|
|
3935
|
+
|
|
3936
|
+
/**
|
|
3937
|
+
* Parse swift package resolved file
|
|
3938
|
+
* @param {string} resolvedFile Package.resolved file
|
|
3939
|
+
*/
|
|
3940
|
+
const parseSwiftResolved = (resolvedFile) => {
|
|
3941
|
+
const pkgList = [];
|
|
3942
|
+
if (fs.existsSync(resolvedFile)) {
|
|
3943
|
+
try {
|
|
3944
|
+
const pkgData = JSON.parse(fs.readFileSync(resolvedFile, "utf8"));
|
|
3945
|
+
let resolvedList = [];
|
|
3946
|
+
if (pkgData.pins) {
|
|
3947
|
+
resolvedList = pkgData.pins;
|
|
3948
|
+
} else if (pkgData.object && pkgData.object.pins) {
|
|
3949
|
+
resolvedList = pkgData.object.pins;
|
|
3950
|
+
}
|
|
3951
|
+
for (const adep of resolvedList) {
|
|
3952
|
+
const apkg = {
|
|
3953
|
+
name: adep.package || adep.identity,
|
|
3954
|
+
group: "",
|
|
3955
|
+
version: adep.state.version || adep.state.revision,
|
|
3956
|
+
properties: [
|
|
3957
|
+
{
|
|
3958
|
+
name: "SrcFile",
|
|
3959
|
+
value: resolvedFile
|
|
3960
|
+
}
|
|
3961
|
+
]
|
|
3962
|
+
};
|
|
3963
|
+
const repLocation = adep.location || adep.repositoryURL;
|
|
3964
|
+
if (repLocation) {
|
|
3965
|
+
apkg.repository = { url: repLocation };
|
|
3966
|
+
}
|
|
3967
|
+
pkgList.push(apkg);
|
|
3968
|
+
}
|
|
3969
|
+
} catch (err) {
|
|
3970
|
+
// continue regardless of error
|
|
3971
|
+
}
|
|
3972
|
+
}
|
|
3973
|
+
return pkgList;
|
|
3974
|
+
};
|
|
3975
|
+
exports.parseSwiftResolved = parseSwiftResolved;
|
|
3976
|
+
|
|
3776
3977
|
/**
|
|
3777
3978
|
* Collect maven dependencies
|
|
3778
3979
|
*
|
|
@@ -4007,6 +4208,7 @@ const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4007
4208
|
jarMetadata["Extension-Name"] ||
|
|
4008
4209
|
jarMetadata["Implementation-Vendor-Id"] ||
|
|
4009
4210
|
jarMetadata["Bundle-SymbolicName"] ||
|
|
4211
|
+
jarMetadata["Bundle-Vendor"] ||
|
|
4010
4212
|
jarMetadata["Automatic-Module-Name"];
|
|
4011
4213
|
let name = "";
|
|
4012
4214
|
if (
|
|
@@ -4073,8 +4275,8 @@ const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4073
4275
|
}
|
|
4074
4276
|
if (name && version) {
|
|
4075
4277
|
pkgList.push({
|
|
4076
|
-
group: group === "." ? "" : group || "",
|
|
4077
|
-
name: name
|
|
4278
|
+
group: group === "." ? "" : encodeURIComponent(group) || "",
|
|
4279
|
+
name: name ? encodeURIComponent(name) : "",
|
|
4078
4280
|
version,
|
|
4079
4281
|
properties: [
|
|
4080
4282
|
{
|