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