1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.xml.hints;
19
20 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.io.Reader;
27 import java.nio.charset.StandardCharsets;
28 import java.util.List;
29 import javax.annotation.concurrent.NotThreadSafe;
30 import javax.xml.parsers.ParserConfigurationException;
31
32 import org.apache.commons.io.ByteOrderMark;
33 import org.apache.commons.io.input.BOMInputStream;
34
35 import org.owasp.dependencycheck.utils.AutoCloseableInputSource;
36 import org.owasp.dependencycheck.utils.XmlUtils;
37
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40 import org.xml.sax.InputSource;
41 import org.xml.sax.SAXException;
42 import org.xml.sax.XMLReader;
43
44 import static org.owasp.dependencycheck.utils.AutoCloseableInputSource.fromResource;
45
46
47
48
49
50
51 @NotThreadSafe
52 public class HintParser {
53
54
55
56
57 private static final Logger LOGGER = LoggerFactory.getLogger(HintParser.class);
58
59
60
61
62 private static final String HINT_SCHEMA_1_2 = "schema/dependency-hint.1.2.xsd";
63
64
65
66
67 private static final String HINT_SCHEMA_1_1 = "schema/dependency-hint.1.1.xsd";
68
69
70
71
72 private static final String HINT_SCHEMA_1_3 = "schema/dependency-hint.1.3.xsd";
73
74
75
76
77 private static final String HINT_SCHEMA_1_4 = "schema/dependency-hint.1.4.xsd";
78
79
80
81
82 private List<HintRule> hintRules;
83
84
85
86 private List<VendorDuplicatingHintRule> vendorDuplicatingHintRules;
87
88
89
90
91
92
93 @SuppressWarnings({"EI_EXPOSE_REP", "EI_EXPOSE_REP2"})
94 public List<HintRule> getHintRules() {
95 return hintRules;
96 }
97
98
99
100
101
102
103 public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() {
104 return vendorDuplicatingHintRules;
105 }
106
107
108
109
110
111
112
113 @SuppressFBWarnings(justification = "try with resources will clean up the input stream", value = {"OBL_UNSATISFIED_OBLIGATION"})
114 public void parseHints(File file) throws HintParseException {
115 try (InputStream fis = new FileInputStream(file)) {
116 parseHints(fis);
117 } catch (SAXException | IOException ex) {
118 LOGGER.debug("", ex);
119 throw new HintParseException(ex);
120 }
121 }
122
123
124
125
126
127
128
129
130
131 public void parseHints(InputStream inputStream) throws HintParseException, SAXException {
132 try (AutoCloseableInputSource schemaStream14 = fromResource(HINT_SCHEMA_1_4);
133 AutoCloseableInputSource schemaStream13 = fromResource(HINT_SCHEMA_1_3);
134 AutoCloseableInputSource schemaStream12 = fromResource(HINT_SCHEMA_1_2);
135 AutoCloseableInputSource schemaStream11 = fromResource(HINT_SCHEMA_1_1)) {
136
137 final BOMInputStream bomStream = BOMInputStream.builder().setInputStream(inputStream).get();
138 final ByteOrderMark bom = bomStream.getBOM();
139 final String defaultEncoding = StandardCharsets.UTF_8.name();
140 final String charsetName = bom == null ? defaultEncoding : bom.getCharsetName();
141
142 final HintHandler handler = new HintHandler();
143 final XMLReader xmlReader = XmlUtils.buildSecureValidatingXmlReader(schemaStream14, schemaStream13, schemaStream12, schemaStream11);
144 xmlReader.setErrorHandler(new HintErrorHandler());
145 xmlReader.setContentHandler(handler);
146 try (Reader reader = new InputStreamReader(bomStream, charsetName)) {
147 final InputSource in = new InputSource(reader);
148 xmlReader.parse(in);
149 this.hintRules = handler.getHintRules();
150 this.vendorDuplicatingHintRules = handler.getVendorDuplicatingHintRules();
151 }
152 } catch (ParserConfigurationException | IOException ex) {
153 LOGGER.debug("", ex);
154 throw new HintParseException(ex);
155 } catch (SAXException ex) {
156 if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) {
157 throw ex;
158 } else {
159 LOGGER.debug("", ex);
160 throw new HintParseException(ex);
161 }
162 }
163 }
164 }