1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.data.composer;
19
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 import jakarta.json.Json;
24 import jakarta.json.JsonArray;
25 import jakarta.json.JsonException;
26 import jakarta.json.JsonObject;
27 import jakarta.json.JsonReader;
28 import jakarta.json.stream.JsonParsingException;
29 import java.io.InputStream;
30 import java.util.ArrayList;
31 import java.util.List;
32 import javax.annotation.concurrent.NotThreadSafe;
33
34
35
36
37
38
39
40 @NotThreadSafe
41 public class ComposerLockParser {
42
43
44
45
46 private final JsonReader jsonReader;
47
48
49
50 private final List<ComposerDependency> composerDependencies;
51
52
53
54 private final boolean skipDev;
55
56
57
58 private static final Logger LOGGER = LoggerFactory.getLogger(ComposerLockParser.class);
59
60
61
62
63
64
65
66 public ComposerLockParser(InputStream inputStream, boolean skipDev) {
67 LOGGER.debug("Creating a ComposerLockParser");
68 this.jsonReader = Json.createReader(inputStream);
69 this.composerDependencies = new ArrayList<>();
70 this.skipDev = skipDev;
71 }
72
73
74
75
76 public void process() {
77 LOGGER.debug("Beginning Composer lock processing");
78 try {
79 final JsonObject composer = jsonReader.readObject();
80 if (composer.containsKey("packages")) {
81 LOGGER.debug("Found packages");
82 final JsonArray packages = composer.getJsonArray("packages");
83 for (JsonObject pkg : packages.getValuesAs(JsonObject.class)) {
84 processPackageEntry(pkg);
85 }
86 }
87 if (composer.containsKey("packages-dev") && !skipDev) {
88 LOGGER.debug("Found packages-dev");
89 final JsonArray devPackages = composer.getJsonArray("packages-dev");
90 for (JsonObject pkg : devPackages.getValuesAs(JsonObject.class)) {
91 processPackageEntry(pkg);
92 }
93 }
94 } catch (JsonParsingException jsonpe) {
95 throw new ComposerException("Error parsing stream", jsonpe);
96 } catch (JsonException jsone) {
97 throw new ComposerException("Error reading stream", jsone);
98 } catch (IllegalStateException ise) {
99 throw new ComposerException("Illegal state in composer stream", ise);
100 } catch (ClassCastException cce) {
101 throw new ComposerException("Not exactly composer lock", cce);
102 }
103 }
104
105 protected void processPackageEntry(JsonObject pkg) {
106 if (pkg.containsKey("name")) {
107 final String groupName = pkg.getString("name");
108 if (groupName.indexOf('/') >= 0 && groupName.indexOf('/') <= groupName.length() - 1) {
109 if (pkg.containsKey("version")) {
110 final String group = groupName.substring(0, groupName.indexOf('/'));
111 final String project = groupName.substring(groupName.indexOf('/') + 1);
112 String version = pkg.getString("version");
113
114 if (version.startsWith("v")) {
115 version = version.substring(1);
116 }
117 LOGGER.debug("Got package {}/{}/{}", group, project, version);
118 composerDependencies.add(new ComposerDependency(group, project, version));
119 } else {
120 LOGGER.debug("Group/package {} does not have a version", groupName);
121 }
122 } else {
123 LOGGER.debug("Got a dependency with no name");
124 }
125 }
126 }
127
128
129
130
131
132
133 public List<ComposerDependency> getDependencies() {
134 return composerDependencies;
135 }
136 }