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 import javax.xml.parsers.SAXParser;
32 import org.apache.commons.io.ByteOrderMark;
33 import org.apache.commons.io.input.BOMInputStream;
34
35 import org.owasp.dependencycheck.utils.FileUtils;
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
45
46
47
48
49 @NotThreadSafe
50 public class HintParser {
51
52
53
54
55 private static final Logger LOGGER = LoggerFactory.getLogger(HintParser.class);
56
57
58
59
60 public static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
61
62
63
64
65 public static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
66
67
68
69
70 public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
71
72
73
74
75 private static final String HINT_SCHEMA_1_2 = "schema/dependency-hint.1.2.xsd";
76
77
78
79
80 private static final String HINT_SCHEMA_1_1 = "schema/dependency-hint.1.1.xsd";
81
82
83
84
85 private static final String HINT_SCHEMA_1_3 = "schema/dependency-hint.1.3.xsd";
86
87
88
89
90 private static final String HINT_SCHEMA_1_4 = "schema/dependency-hint.1.4.xsd";
91
92
93
94
95 private List<HintRule> hintRules;
96
97
98
99 private List<VendorDuplicatingHintRule> vendorDuplicatingHintRules;
100
101
102
103
104
105
106 @SuppressWarnings({"EI_EXPOSE_REP", "EI_EXPOSE_REP2"})
107 public List<HintRule> getHintRules() {
108 return hintRules;
109 }
110
111
112
113
114
115
116 public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() {
117 return vendorDuplicatingHintRules;
118 }
119
120
121
122
123
124
125
126 @SuppressFBWarnings(justification = "try with resources will clean up the input stream", value = {"OBL_UNSATISFIED_OBLIGATION"})
127 public void parseHints(File file) throws HintParseException {
128 try (InputStream fis = new FileInputStream(file)) {
129 parseHints(fis);
130 } catch (SAXException | IOException ex) {
131 LOGGER.debug("", ex);
132 throw new HintParseException(ex);
133 }
134 }
135
136
137
138
139
140
141
142
143
144 public void parseHints(InputStream inputStream) throws HintParseException, SAXException {
145 try (
146 InputStream schemaStream14 = FileUtils.getResourceAsStream(HINT_SCHEMA_1_4);
147 InputStream schemaStream13 = FileUtils.getResourceAsStream(HINT_SCHEMA_1_3);
148 InputStream schemaStream12 = FileUtils.getResourceAsStream(HINT_SCHEMA_1_2);
149 InputStream schemaStream11 = FileUtils.getResourceAsStream(HINT_SCHEMA_1_1)) {
150
151 final BOMInputStream bomStream = BOMInputStream.builder().setInputStream(inputStream).get();
152 final ByteOrderMark bom = bomStream.getBOM();
153 final String defaultEncoding = StandardCharsets.UTF_8.name();
154 final String charsetName = bom == null ? defaultEncoding : bom.getCharsetName();
155
156 final HintHandler handler = new HintHandler();
157 final SAXParser saxParser = XmlUtils.buildSecureSaxParser(schemaStream14, schemaStream13, schemaStream12, schemaStream11);
158 final XMLReader xmlReader = saxParser.getXMLReader();
159 xmlReader.setErrorHandler(new HintErrorHandler());
160 xmlReader.setContentHandler(handler);
161 try (Reader reader = new InputStreamReader(bomStream, charsetName)) {
162 final InputSource in = new InputSource(reader);
163 xmlReader.parse(in);
164 this.hintRules = handler.getHintRules();
165 this.vendorDuplicatingHintRules = handler.getVendorDuplicatingHintRules();
166 }
167 } catch (ParserConfigurationException | IOException ex) {
168 LOGGER.debug("", ex);
169 throw new HintParseException(ex);
170 } catch (SAXException ex) {
171 if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) {
172 throw ex;
173 } else {
174 LOGGER.debug("", ex);
175 throw new HintParseException(ex);
176 }
177 }
178 }
179 }