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) 2013 Jeremy Long. All Rights Reserved.
17 */
18 package org.owasp.dependencycheck.suppression;
19
20 import java.util.ArrayList;
21 import java.util.List;
22 import org.xml.sax.Attributes;
23 import org.xml.sax.SAXException;
24 import org.xml.sax.helpers.DefaultHandler;
25
26 /**
27 * A handler to load suppression rules.
28 *
29 * @author Jeremy Long
30 */
31 public class SuppressionHandler extends DefaultHandler {
32
33 /**
34 * The suppress node, indicates the start of a new rule.
35 */
36 public static final String SUPPRESS = "suppress";
37 /**
38 * The file path element name.
39 */
40 public static final String FILE_PATH = "filePath";
41 /**
42 * The sha1 hash element name.
43 */
44 public static final String SHA1 = "sha1";
45 /**
46 * The CVE element name.
47 */
48 public static final String CVE = "cve";
49 /**
50 * The CPE element name.
51 */
52 public static final String CPE = "cpe";
53 /**
54 * The CWE element name.
55 */
56 public static final String CWE = "cwe";
57 /**
58 * The GAV element name.
59 */
60 public static final String GAV = "gav";
61 /**
62 * The cvssBelow element name.
63 */
64 public static final String CVSS_BELOW = "cvssBelow";
65 /**
66 * A list of suppression rules.
67 */
68 private final List<SuppressionRule> suppressionRules = new ArrayList<SuppressionRule>();
69
70 /**
71 * Get the value of suppressionRules.
72 *
73 * @return the value of suppressionRules
74 */
75 public List<SuppressionRule> getSuppressionRules() {
76 return suppressionRules;
77 }
78 /**
79 * The current rule being read.
80 */
81 private SuppressionRule rule;
82 /**
83 * The attributes of the node being read.
84 */
85 private Attributes currentAttributes;
86 /**
87 * The current node text being extracted from the element.
88 */
89 private StringBuilder currentText;
90
91 /**
92 * Handles the start element event.
93 *
94 * @param uri the uri of the element being processed
95 * @param localName the local name of the element being processed
96 * @param qName the qName of the element being processed
97 * @param attributes the attributes of the element being processed
98 * @throws SAXException thrown if there is an exception processing
99 */
100 @Override
101 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
102 currentAttributes = attributes;
103 currentText = new StringBuilder();
104 if (SUPPRESS.equals(qName)) {
105 rule = new SuppressionRule();
106 final String base = currentAttributes.getValue("base");
107 if (base != null) {
108 rule.setBase(Boolean.parseBoolean(base));
109 } else {
110 rule.setBase(false);
111 }
112 }
113 }
114
115 /**
116 * Handles the end element event.
117 *
118 * @param uri the URI of the element
119 * @param localName the local name of the element
120 * @param qName the qName of the element
121 * @throws SAXException thrown if there is an exception processing
122 */
123 @Override
124 public void endElement(String uri, String localName, String qName) throws SAXException {
125 if (SUPPRESS.equals(qName)) {
126 suppressionRules.add(rule);
127 rule = null;
128 } else if (FILE_PATH.equals(qName)) {
129 final PropertyType pt = processPropertyType();
130 rule.setFilePath(pt);
131 } else if (SHA1.equals(qName)) {
132 rule.setSha1(currentText.toString());
133 } else if (GAV.equals(qName)) {
134 final PropertyType pt = processPropertyType();
135 rule.setGav(pt);
136 } else if (CPE.equals(qName)) {
137 final PropertyType pt = processPropertyType();
138 rule.addCpe(pt);
139 } else if (CWE.equals(qName)) {
140 rule.addCwe(currentText.toString());
141 } else if (CVE.equals(qName)) {
142 rule.addCve(currentText.toString());
143 } else if (CVSS_BELOW.equals(qName)) {
144 final float cvss = Float.parseFloat(currentText.toString());
145 rule.addCvssBelow(cvss);
146 }
147 }
148
149 /**
150 * Collects the body text of the node being processed.
151 *
152 * @param ch the char array of text
153 * @param start the start position to copy text from in the char array
154 * @param length the number of characters to copy from the char array
155 * @throws SAXException thrown if there is a parsing exception
156 */
157 @Override
158 public void characters(char[] ch, int start, int length) throws SAXException {
159 currentText.append(ch, start, length);
160 }
161
162 /**
163 * Processes field members that have been collected during the characters and startElement method to construct a
164 * PropertyType object.
165 *
166 * @return a PropertyType object
167 */
168 private PropertyType processPropertyType() {
169 final PropertyType pt = new PropertyType();
170 pt.setValue(currentText.toString());
171 if (currentAttributes != null && currentAttributes.getLength() > 0) {
172 final String regex = currentAttributes.getValue("regex");
173 if (regex != null) {
174 pt.setRegex(Boolean.parseBoolean(regex));
175 }
176 final String caseSensitive = currentAttributes.getValue("caseSensitive");
177 if (caseSensitive != null) {
178 pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
179 }
180 }
181 return pt;
182 }
183 }