1 /*
2 * This file is part of dependency-check-core.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Copyright (c) 2016 Jeremy Long. All Rights Reserved.
17 */
18 package org.owasp.dependencycheck.xml.hints;
19
20 import java.util.ArrayList;
21 import java.util.List;
22 import javax.annotation.concurrent.NotThreadSafe;
23 import org.owasp.dependencycheck.dependency.Confidence;
24 import org.owasp.dependencycheck.utils.XmlUtils;
25 import org.owasp.dependencycheck.xml.suppression.PropertyType;
26 import org.xml.sax.Attributes;
27 import org.xml.sax.SAXException;
28 import org.xml.sax.helpers.DefaultHandler;
29
30 /**
31 * A handler to load hint rules.
32 *
33 * @author Jeremy Long
34 */
35 @NotThreadSafe
36 public class HintHandler extends DefaultHandler {
37
38 /**
39 * Internal type to track the parent node state.
40 */
41 enum ParentType {
42 /**
43 * Marks the add node.
44 */
45 ADD,
46 /**
47 * Marks the given node.
48 */
49 GIVEN,
50 /**
51 * Marks the remove node.
52 */
53 REMOVE
54 }
55
56 //<editor-fold defaultstate="collapsed" desc="Element and attribute names">
57 /**
58 * Element name.
59 */
60 private static final String HINT = "hint";
61 /**
62 * Element name.
63 */
64 private static final String GIVEN = "given";
65 /**
66 * Element name.
67 */
68 private static final String ADD = "add";
69 /**
70 * Element name.
71 */
72 private static final String REMOVE = "remove";
73
74 /**
75 * Element name.
76 */
77 private static final String EVIDENCE = "evidence";
78 /**
79 * Element name.
80 */
81 private static final String FILE_NAME = "fileName";
82 /**
83 * Element name.
84 */
85 private static final String VENDOR_DUPLICATING_RULE = "vendorDuplicatingHint";
86 /**
87 * Attribute name.
88 */
89 private static final String DUPLICATE = "duplicate";
90 /**
91 * Attribute value.
92 */
93 private static final String VENDOR = "vendor";
94 /**
95 * Attribute value.
96 */
97 private static final String PRODUCT = "product";
98 /**
99 * Attribute value.
100 */
101 private static final String VERSION = "version";
102 /**
103 * Attribute name.
104 */
105 private static final String CONFIDENCE = "confidence";
106 /**
107 * Attribute name.
108 */
109 private static final String VALUE = "value";
110 /**
111 * Attribute name.
112 */
113 private static final String NAME = "name";
114 /**
115 * Attribute name.
116 */
117 private static final String SOURCE = "source";
118 /**
119 * Attribute name.
120 */
121 private static final String TYPE = "type";
122 /**
123 * Attribute name.
124 */
125 private static final String CASE_SENSITIVE = "caseSensitive";
126 /**
127 * Attribute name.
128 */
129 private static final String REGEX = "regex";
130 /**
131 * Attribute name.
132 */
133 private static final String CONTAINS = "contains";
134 //</editor-fold>
135
136 /**
137 * The list of hint rules.
138 */
139 private final List<HintRule> hintRules = new ArrayList<>();
140
141 /**
142 * The list of vendor duplicating hint rules.
143 */
144 private final List<VendorDuplicatingHintRule> vendorDuplicatingHintRules = new ArrayList<>();
145 /**
146 * The current rule being read.
147 */
148 private HintRule rule;
149
150 /**
151 * The current state of the parent node (to differentiate between 'add' and
152 * 'given').
153 */
154 private ParentType nodeType = ParentType.GIVEN;
155
156 /**
157 * Returns the list of hint rules.
158 *
159 * @return the value of hintRules
160 */
161 public List<HintRule> getHintRules() {
162 return hintRules;
163 }
164
165 /**
166 * Returns the list of vendor duplicating hint rules.
167 *
168 * @return the list of vendor duplicating hint rules
169 */
170 public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() {
171 return vendorDuplicatingHintRules;
172 }
173
174 /**
175 * Handles the start element event.
176 *
177 * @param uri the URI of the element being processed
178 * @param localName the local name of the element being processed
179 * @param qName the qName of the element being processed
180 * @param attr the attributes of the element being processed
181 * @throws SAXException thrown if there is an exception processing
182 */
183 @Override
184 public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException {
185 if (null != qName) {
186 switch (qName) {
187 case HINT:
188 rule = new HintRule();
189 break;
190 case ADD:
191 nodeType = ParentType.ADD;
192 break;
193 case GIVEN:
194 nodeType = ParentType.GIVEN;
195 break;
196 case REMOVE:
197 nodeType = ParentType.REMOVE;
198 break;
199 case EVIDENCE:
200 final String hintType = attr.getValue(TYPE);
201 if (null != hintType && null != nodeType) {
202 final String source = attr.getValue(SOURCE);
203 final String name = attr.getValue(NAME);
204 final String value = attr.getValue(VALUE);
205 final Confidence confidence;
206 final String confidenceAttribute = attr.getValue(CONFIDENCE);
207 if (confidenceAttribute == null) {
208 confidence = null;
209 } else {
210 confidence = Confidence.valueOf(confidenceAttribute);
211 }
212 final boolean regex;
213 final String regexAttribute = attr.getValue(REGEX);
214 if (regexAttribute == null) {
215 regex = false;
216 } else {
217 regex = XmlUtils.parseBoolean(regexAttribute);
218 }
219 switch (hintType) {
220 case VENDOR:
221 switch (nodeType) {
222 case ADD:
223 rule.addAddVendor(source, name, value, confidence);
224 break;
225 case REMOVE:
226 rule.addRemoveVendor(source, name, value, regex, confidence);
227 break;
228 case GIVEN:
229 rule.addGivenVendor(source, name, value, regex, confidence);
230 break;
231 default:
232 break;
233 }
234 break;
235 case PRODUCT:
236 switch (nodeType) {
237 case ADD:
238 rule.addAddProduct(source, name, value, confidence);
239 break;
240 case REMOVE:
241 rule.addRemoveProduct(source, name, value, regex, confidence);
242 break;
243 case GIVEN:
244 rule.addGivenProduct(source, name, value, regex, confidence);
245 break;
246 default:
247 break;
248 }
249 break;
250 case VERSION:
251 switch (nodeType) {
252 case ADD:
253 rule.addAddVersion(source, name, value, confidence);
254 break;
255 case REMOVE:
256 rule.addRemoveVersion(source, name, value, regex, confidence);
257 break;
258 case GIVEN:
259 rule.addGivenVersion(source, name, value, regex, confidence);
260 break;
261 default:
262 break;
263 }
264 break;
265 default:
266 break;
267 }
268 }
269 break;
270 case FILE_NAME:
271 final PropertyType pt = new PropertyType();
272 pt.setValue(attr.getValue(CONTAINS));
273 if (attr.getLength() > 0) {
274 final String regex = attr.getValue(REGEX);
275 if (regex != null) {
276 pt.setRegex(Boolean.parseBoolean(regex));
277 }
278 final String caseSensitive = attr.getValue(CASE_SENSITIVE);
279 if (caseSensitive != null) {
280 pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
281 }
282 }
283 rule.addFilename(pt);
284 break;
285 case VENDOR_DUPLICATING_RULE:
286 vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE)));
287 break;
288 default:
289 break;
290 }
291 }
292 }
293
294 /**
295 * Handles the end element event.
296 *
297 * @param uri the element's URI
298 * @param localName the local name
299 * @param qName the qualified name
300 * @throws SAXException thrown if there is an exception processing the
301 * element
302 */
303 @Override
304 public void endElement(String uri, String localName, String qName) throws SAXException {
305 if (HINT.equals(qName) && rule != null) {
306 hintRules.add(rule);
307 rule = null;
308 }
309 }
310 }