HintHandler.java
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.xml.hints;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.concurrent.NotThreadSafe;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.utils.XmlUtils;
import org.owasp.dependencycheck.xml.suppression.PropertyType;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* A handler to load hint rules.
*
* @author Jeremy Long
*/
@NotThreadSafe
public class HintHandler extends DefaultHandler {
/**
* Internal type to track the parent node state.
*/
enum ParentType {
/**
* Marks the add node.
*/
ADD,
/**
* Marks the given node.
*/
GIVEN,
/**
* Marks the remove node.
*/
REMOVE
}
//<editor-fold defaultstate="collapsed" desc="Element and attribute names">
/**
* Element name.
*/
private static final String HINT = "hint";
/**
* Element name.
*/
private static final String GIVEN = "given";
/**
* Element name.
*/
private static final String ADD = "add";
/**
* Element name.
*/
private static final String REMOVE = "remove";
/**
* Element name.
*/
private static final String EVIDENCE = "evidence";
/**
* Element name.
*/
private static final String FILE_NAME = "fileName";
/**
* Element name.
*/
private static final String VENDOR_DUPLICATING_RULE = "vendorDuplicatingHint";
/**
* Attribute name.
*/
private static final String DUPLICATE = "duplicate";
/**
* Attribute value.
*/
private static final String VENDOR = "vendor";
/**
* Attribute value.
*/
private static final String PRODUCT = "product";
/**
* Attribute value.
*/
private static final String VERSION = "version";
/**
* Attribute name.
*/
private static final String CONFIDENCE = "confidence";
/**
* Attribute name.
*/
private static final String VALUE = "value";
/**
* Attribute name.
*/
private static final String NAME = "name";
/**
* Attribute name.
*/
private static final String SOURCE = "source";
/**
* Attribute name.
*/
private static final String TYPE = "type";
/**
* Attribute name.
*/
private static final String CASE_SENSITIVE = "caseSensitive";
/**
* Attribute name.
*/
private static final String REGEX = "regex";
/**
* Attribute name.
*/
private static final String CONTAINS = "contains";
//</editor-fold>
/**
* The list of hint rules.
*/
private final List<HintRule> hintRules = new ArrayList<>();
/**
* The list of vendor duplicating hint rules.
*/
private final List<VendorDuplicatingHintRule> vendorDuplicatingHintRules = new ArrayList<>();
/**
* The current rule being read.
*/
private HintRule rule;
/**
* The current state of the parent node (to differentiate between 'add' and
* 'given').
*/
private ParentType nodeType = ParentType.GIVEN;
/**
* Returns the list of hint rules.
*
* @return the value of hintRules
*/
public List<HintRule> getHintRules() {
return hintRules;
}
/**
* Returns the list of vendor duplicating hint rules.
*
* @return the list of vendor duplicating hint rules
*/
public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() {
return vendorDuplicatingHintRules;
}
/**
* Handles the start element event.
*
* @param uri the URI of the element being processed
* @param localName the local name of the element being processed
* @param qName the qName of the element being processed
* @param attr the attributes of the element being processed
* @throws SAXException thrown if there is an exception processing
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException {
if (null != qName) {
switch (qName) {
case HINT:
rule = new HintRule();
break;
case ADD:
nodeType = ParentType.ADD;
break;
case GIVEN:
nodeType = ParentType.GIVEN;
break;
case REMOVE:
nodeType = ParentType.REMOVE;
break;
case EVIDENCE:
final String hintType = attr.getValue(TYPE);
if (null != hintType && null != nodeType) {
final String source = attr.getValue(SOURCE);
final String name = attr.getValue(NAME);
final String value = attr.getValue(VALUE);
final Confidence confidence;
final String confidenceAttribute = attr.getValue(CONFIDENCE);
if (confidenceAttribute == null) {
confidence = null;
} else {
confidence = Confidence.valueOf(confidenceAttribute);
}
final boolean regex;
final String regexAttribute = attr.getValue(REGEX);
if (regexAttribute == null) {
regex = false;
} else {
regex = XmlUtils.parseBoolean(regexAttribute);
}
switch (hintType) {
case VENDOR:
switch (nodeType) {
case ADD:
rule.addAddVendor(source, name, value, confidence);
break;
case REMOVE:
rule.addRemoveVendor(source, name, value, regex, confidence);
break;
case GIVEN:
rule.addGivenVendor(source, name, value, regex, confidence);
break;
default:
break;
}
break;
case PRODUCT:
switch (nodeType) {
case ADD:
rule.addAddProduct(source, name, value, confidence);
break;
case REMOVE:
rule.addRemoveProduct(source, name, value, regex, confidence);
break;
case GIVEN:
rule.addGivenProduct(source, name, value, regex, confidence);
break;
default:
break;
}
break;
case VERSION:
switch (nodeType) {
case ADD:
rule.addAddVersion(source, name, value, confidence);
break;
case REMOVE:
rule.addRemoveVersion(source, name, value, regex, confidence);
break;
case GIVEN:
rule.addGivenVersion(source, name, value, regex, confidence);
break;
default:
break;
}
break;
default:
break;
}
}
break;
case FILE_NAME:
final PropertyType pt = new PropertyType();
pt.setValue(attr.getValue(CONTAINS));
if (attr.getLength() > 0) {
final String regex = attr.getValue(REGEX);
if (regex != null) {
pt.setRegex(Boolean.parseBoolean(regex));
}
final String caseSensitive = attr.getValue(CASE_SENSITIVE);
if (caseSensitive != null) {
pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
}
}
rule.addFilename(pt);
break;
case VENDOR_DUPLICATING_RULE:
vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE)));
break;
default:
break;
}
}
}
/**
* Handles the end element event.
*
* @param uri the element's URI
* @param localName the local name
* @param qName the qualified name
* @throws SAXException thrown if there is an exception processing the
* element
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (HINT.equals(qName) && rule != null) {
hintRules.add(rule);
rule = null;
}
}
}