View Javadoc
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 }