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