The following table lists the configurable properties:
+
Configuration
+
The following properties can be set on the dependency-check-maven plugin.
@@ -185,7 +186,131 @@
Description
-
Requirement
+
Default Value
+
+
+
+
+
+
+
autoUpdate
+
+
Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false.
+
+
true
+
+
+
+
+
externalReport
+
+
When using as a Site plugin this parameter sets whether or not the external report format should be used.
+
+
false
+
+
+
+
+
outputDirectory
+
+
The location to write the report(s). Note, this is not used if generating the report as part of a mvn site build
+
+
‘target’
+
+
+
+
+
failBuildOnCVSS
+
+
Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail.
+
+
11
+
+
+
+
+
format
+
+
The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true.
+
+
HTML
+
+
+
+
+
logFile
+
+
The file path to write verbose logging information.
+
+
+
+
+
+
+
suppressionFile
+
+
The file path to the XML suppression file - used to suppress false positives
+
+
+
+
+
+
+
proxyUrl
+
+
The Proxy URL.
+
+
+
+
+
+
+
proxyPort
+
+
The Proxy Port.
+
+
+
+
+
+
+
proxyUsername
+
+
Defines the proxy user name.
+
+
+
+
+
+
+
proxyPassword
+
+
Defines the proxy password.
+
+
+
+
+
+
+
connectionTimeout
+
+
The URL Connection Timeout.
+
+
+
+
+
+
Analyzer Configuration
+
The following properties are used to configure the various file type analyzers. These properties can be used to turn off specific analyzers if it is not needed. Note, that specific analyzers will automatically disable themselves if no file types that they support are detected - so specifically disabling them may not be needed.
+
+
+
+
+
+
+
Property
+
+
Description
Default Value
@@ -194,245 +319,102 @@
-
applicationName
+
archiveAnalyzerEnabled
-
The name of the application to use in the generated report.
-
-
Required
-
-
-
-
-
-
-
reportFormat
-
-
The format of the report to be generated. Allowed values are: HTML, XML, VULN, or ALL. The default value is HTML.
-
-
Optional
-
-
HTML
-
-
-
-
-
reportOutputDirectory
-
-
The directory where dependency-check will store data used for analysis. Defaults to the current working directory.
-
-
Optional
-
-
-
-
-
-
-
failBuildOn
-
-
If set and a CVE is found that is greater then the specified value the build will fail. The default value is 11 which means that the build will not fail. Valid values are 0-11.
-
-
Optional
-
-
11
-
-
-
-
-
autoUpdate
-
-
If set to false the NVD CVE data is not automatically updated. Setting this to false could result in false negatives. However, this may be required in some environments.
-
-
Optional
+
Sets whether the Archive Analyzer will be used.
true
-
dataDirectory
-
-
The directory where dependency-check will store data used for analysis. Defaults to a folder called, called ‘dependency-check-data’, that is in the same directory as the dependency-check-ant jar file was installed in. It is not recommended to change this.
-
-
Optional
-
-
-
-
-
-
-
logFile
-
-
The file path to write verbose logging information.
-
-
Optional
-
-
-
-
-
-
-
suppressionFile
-
-
An XML file conforming to the suppression schema that suppresses findings; this is used to hide false positives.
-
-
Optional
-
-
-
-
-
-
-
proxyUrl
-
-
Defines the proxy used to connect to the Internet.
-
-
Optional
-
-
-
-
-
-
-
proxyPort
-
-
Defines the port for the proxy.
-
-
Optional
-
-
-
-
-
-
-
proxyUsername
-
-
Defines the proxy user name.
-
-
Optional
-
-
-
-
-
-
-
proxyPassword
-
-
Defines the proxy password.
-
-
Optional
-
-
-
-
-
-
-
connectionTimeout
-
-
The connection timeout used when downloading data files from the Internet.
-
-
Optional
-
-
-
-
-
-
-
nexusAnalyzerEnabled
-
-
The connection timeout used when downloading data files from the Internet.
-
-
Optional
-
-
-
-
-
-
-
nexusUrl
-
-
The connection timeout used when downloading data files from the Internet.
-
-
Optional
-
-
-
-
-
-
-
nexusUsesProxy
-
-
Whether or not the defined proxy should be used when connecting to Nexus.
-
-
Optional
-
-
true
-
-
-
-
-
databaseDriverName
-
-
The name of the database driver. Example: org.h2.Driver.
-
-
Optional
-
-
-
-
-
-
-
databaseDriverPath
-
-
The path to the database driver JAR file; only used if the driver is not in the class path.
-
-
Optional
-
-
-
-
-
-
-
connectionString
-
-
The connection string used to connect to the database.
-
-
Optional
-
-
-
-
-
-
-
databaseUser
-
-
The username used when connecting to the database.
-
-
Optional
-
-
dcuser
-
-
-
-
-
databasePassword
-
-
The password used when connecting to the database.
-
-
Optional
-
-
-
-
-
-
zipExtensions
A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed.
Whether or not the defined proxy should be used when connecting to Nexus.
+
+
true
+
+
+
+
+
nuspecAnalyzerEnabled
+
+
Sets whether or not the .NET Nuget Nuspec Analyzer will be used.
+
+
true
+
+
+
+
+
assemblyAnalyzerEnabled
+
+
Sets whether or not the .NET Assembly Analyzer should be used.
+
+
true
+
+
+
+
+
pathToMono
+
+
The path to Mono for .NET assembly analysis on non-windows systems
+
+
+
Advanced Configuration
+
The following properties can be configured in the plugin. However, they are less frequently changed. One exception may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment.
Download dependency-check-ant from bintray here. To install dependency-check-ant place the dependency-check-ant-1.1.3.jar into the lib directory of your Ant instalation directory. Once installed you can add the taskdef to you build.xml and add the task to a new or existing target.
+
Download dependency-check-ant from bintray here. To install dependency-check-ant place the dependency-check-ant-1.1.4.jar into the lib directory of your Ant instalation directory. Once installed you can add the taskdef to you build.xml and add the task to a new or existing target.
It is important to understand that the first time this task is executed it may take 20 minutes or more as it downloads and processes the data from the National Vulnerability Database (NVD) hosted by NIST: https://nvd.nist.gov
After the first batch download, as long as the task is executed at least once every seven days the update will only take a few seconds.
- Returns a list of supported file extensions. An example would be an analyzer that inspected java jar files. The
- getSupportedExtensions function would return a set with a single element "jar".
-
-
- Note: when implementing this the extensions returned MUST be lowercase.
-
Returns:
The file extensions supported by this analyzer.
-
-
- If the analyzer returns null it will not cause additional files to be analyzed but will be executed against every
- file loaded
Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted,
scanned, and added to the list of dependencies within the engine.
Exception - is thrown if there is an issue opening the index.
+
+
@@ -359,7 +391,7 @@ implements
-
+
analyze
public void analyze(Dependency dependency,
@@ -374,79 +406,6 @@ implements AnalysisException - is thrown if there is an issue analyzing the dependency.
Analyzer which will attempt to locate a dependency on a Nexus service by SHA-1 digest of the dependency.
There are two settings which govern this behavior:
@@ -157,8 +162,8 @@ extends
+
+ org.owasp.dependencycheck.analyzer
+
+
+ Analyzers are used to inspect the identified dependencies, collect Evidence,
+ and process the dependencies.
+
+ org.owasp.dependencycheck.analyzer
+
+
+ Analyzers are used to inspect the identified dependencies, collect Evidence,
+ and process the dependencies.
Returns the file name of the dependency with the backslash escaped for use in JavaScript. This is a complete hack
+ as I could not get the replace to work in the template itself.
+
Returns:
the file name of the dependency with the backslash escaped for use in JavaScript
+
+ org.owasp.dependencycheck.agent
+
+
+ The agent package holds an agent API that can be used by other applications that have information about dependencies;
+ but would rather implement something in their code directly rather then spawn a process to run the entire
+ dependency-check engine.
+
+ org.owasp.dependencycheck.agent
+
+
+ The agent package holds an agent API that can be used by other applications that have information about dependencies;
+ but would rather implement something in their code directly rather then spawn a process to run the entire
+ dependency-check engine.
+
+ org.owasp.dependencycheck.agent
+
+
+ The agent package holds an agent API that can be used by other applications that have information about dependencies;
+ but would rather implement something in their code directly rather then spawn a process to run the entire
+ dependency-check engine.
+
+ org.owasp.dependencycheck.agent
+
+
+ The agent package holds an agent API that can be used by other applications that have information about dependencies;
+ but would rather implement something in their code directly rather then spawn a process to run the entire
+ dependency-check engine.
+
+ org.owasp.dependencycheck.agent
+
+
+ The agent package holds an agent API that can be used by other applications that have information about dependencies;
+ but would rather implement something in their code directly rather then spawn a process to run the entire
+ dependency-check engine.
+
+ org.owasp.dependencycheck.agent
+
+
+ The agent package holds an agent API that can be used by other applications that have information about dependencies;
+ but would rather implement something in their code directly rather then spawn a process to run the entire
+ dependency-check engine.
public static void extractFiles(File archive,
@@ -303,6 +312,17 @@ public static ExtractionException - thrown if there is an error extracting the files
public static boolean getBoolean(String key)
@@ -483,6 +490,24 @@ extends InvalidSettingException - is thrown if there is an error retrieving the setting
Returns a boolean value from the properties file. If the value was specified as a system property or passed in
+ via the -Dprop=value argument this method will return the value from the system properties before
+ the values in the contained configuration file.
+
Parameters:
key - the key to lookup within the properties file
defaultValue - the default value to return if the setting does not exist
+
+ org.owasp.dependencycheck.agent
+
+
+ The agent package holds an agent API that can be used by other applications that have information about dependencies;
+ but would rather implement something in their code directly rather then spawn a process to run the entire
+ dependency-check engine.
Found reliance on default encoding in org.owasp.dependencycheck.analyzer.AssemblyAnalyzer.analyzeFileType(Dependency, Engine): new java.io.InputStreamReader(InputStream)
Found reliance on default encoding in org.owasp.dependencycheck.analyzer.AssemblyAnalyzer.initializeFileTypeAnalyzer(): new java.io.InputStreamReader(InputStream)
Possible null pointer dereference of nextVersion on branch that might be infeasible in org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer.removeSpuriousCPE(Dependency)
Found reliance on default encoding in org.owasp.dependencycheck.analyzer.JavaScriptAnalyzer.analyze(Dependency, Engine): new java.io.FileReader(File)
+
+
Found reliance on default encoding in org.owasp.dependencycheck.analyzer.JavaScriptAnalyzer.analyzeFileType(Dependency, Engine): new java.io.FileReader(File)
Statements for JavaNCSS are not statements as specified in the Java Language Specification but include all kinds of declarations too. Roughly spoken, NCSS is approximately equivalent to counting ';' and '{' characters in Java source files.
Not counted are empty statements, empty blocks or semicolons after closing brackets. Of course, comments don't get counted too. Closing brackets also never get counted, the same applies to blocks in general.
-
+
Examples
-
+
Package declaration
package java.lang;
-
+
Import declaration
import java.awt.*;
-
+
Class declaration
public class Foo {
public class Foo extends Bla {
-
+
Interface declaration
public interface Able ; {
-
+
Field declaration
int a;
int a, b, c = 5, d = 6;
-
+
Method declaration
public void cry();
public void gib() throws DeadException {
-
+
Constructor declaration
public Foo() {
-
+
Constructor invocation
this();
super();
-
+
Statement declaration
@@ -1075,7 +1077,7 @@
if (3 == 4);
if (4 == 4) { ;
} else {
-
+
Label declaration
fine :
In some cases consecutive semicolons are illegal according to the JLS but JavaNCSS still tolerates them (thought JavaNCSS is still more strict as 'javac'). Nevertheless they are never counted as two statements.
- can we utilize the pom's groupid and artifactId to filter??? most of these are due to low quality data. Other idea would be to say any CPE found based on LOW confidence evidence should have a different CPE type? (this might be a better solution then just removing the URL for "best-guess" matches).
+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) 2012 Jeremy Long. All Rights Reserved.
+17 */
+18package org.owasp.dependencycheck.analyzer;
+19
+20import java.util.Set;
+21import org.junit.After;
+22import org.junit.AfterClass;
+23importstatic org.junit.Assert.assertEquals;
+24importstatic org.junit.Assert.assertTrue;
+25import org.junit.Before;
+26import org.junit.BeforeClass;
+27import org.junit.Test;
+28
+29/**
+30 *
+31 * @author Jeremy Long <jeremy.long@owasp.org>
+32 */
+33publicclassAbstractFileTypeAnalyzerTest {
+34
+35publicAbstractFileTypeAnalyzerTest() {
+36 }
+37
+38 @BeforeClass
+39publicstaticvoid setUpClass() throws Exception {
+40 }
+41
+42 @AfterClass
+43publicstaticvoid tearDownClass() throws Exception {
+44 }
+45
+46 @Before
+47publicvoid setUp() {
+48 }
+49
+50 @After
+51publicvoid tearDown() {
+52 }
+53
+54/**
+55 * Test of newHashSet method, of class AbstractAnalyzer.
+56 */
+57 @Test
+58publicvoid testNewHashSet() {
+59 Set result = AbstractFileTypeAnalyzer.newHashSet("one", "two");
+60 assertEquals(2, result.size());
+61 assertTrue(result.contains("one"));
+62 assertTrue(result.contains("two"));
+63 }
+64 }
+
+
+
+
+
diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzerTest.html
index bd4ef12be..d9f06300b 100644
--- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzerTest.html
+++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzerTest.html
@@ -88,57 +88,45 @@
80 }
8182/**
-83 * Test of supportsExtension method, of class AbstractSuppressionAnalyzer.
+83 * Test of initialize method, of class AbstractSuppressionAnalyzer.84 */85 @Test
-86publicvoid testSupportsExtension() {
-87 String extension = "jar";
-88 AbstractSuppressionAnalyzer instance = newAbstractSuppressionAnalyzerImpl();
-89boolean expResult = true;
-90boolean result = instance.supportsExtension(extension);
-91 assertEquals(expResult, result);
-92 }
-93
-94/**
-95 * Test of initialize method, of class AbstractSuppressionAnalyzer.
-96 */
-97 @Test
-98publicvoid testInitialize() throws Exception {
-99 AbstractSuppressionAnalyzer instance = newAbstractSuppressionAnalyzerImpl();
-100 instance.initialize();
+86publicvoid testInitialize() throws Exception {
+87 AbstractSuppressionAnalyzer instance = newAbstractSuppressionAnalyzerImpl();
+88 instance.initialize();
+89 }
+90
+91/**
+92 * Test of getRules method, of class AbstractSuppressionAnalyzer.
+93 */
+94 @Test
+95publicvoid testGetRules() throws Exception {
+96 AbstractSuppressionAnalyzer instance = newAbstractSuppressionAnalyzerImpl();
+97 instance.initialize();
+98int expCount = 5;
+99 List<SuppressionRule> result = instance.getRules();
+100 assertEquals(expCount, result.size());
101 }
102
-103/**
-104 * Test of getRules method, of class AbstractSuppressionAnalyzer.
-105 */
-106 @Test
-107publicvoid testGetRules() throws Exception {
-108 AbstractSuppressionAnalyzer instance = newAbstractSuppressionAnalyzerImpl();
-109 instance.initialize();
-110int expCount = 5;
-111 List<SuppressionRule> result = instance.getRules();
-112 assertEquals(expCount, result.size());
-113 }
+103publicclassAbstractSuppressionAnalyzerImplextends AbstractSuppressionAnalyzer {
+104
+105 @Override
+106publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
+107thrownew UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+108 }
+109
+110 @Override
+111public String getName() {
+112thrownew UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+113 }
114
-115publicclassAbstractSuppressionAnalyzerImplextends AbstractSuppressionAnalyzer {
-116
-117 @Override
-118publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-119thrownew UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-120 }
-121
-122 @Override
-123public String getName() {
-124thrownew UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-125 }
-126
-127 @Override
-128public AnalysisPhase getAnalysisPhase() {
-129thrownew UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-130 }
-131 }
-132
-133 }
+115 @Override
+116public AnalysisPhase getAnalysisPhase() {
+117thrownew UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+118 }
+119 }
+120
+121 }
diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AnalyzerServiceTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AnalyzerServiceTest.html
index b8e64281d..ad10b55a4 100644
--- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AnalyzerServiceTest.html
+++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AnalyzerServiceTest.html
@@ -26,58 +26,56 @@
18package org.owasp.dependencycheck.analyzer;
1920import java.util.Iterator;
-21import java.util.Set;
-22import org.junit.After;
-23import org.junit.AfterClass;
-24importstatic org.junit.Assert.assertTrue;
-25import org.junit.Before;
-26import org.junit.BeforeClass;
-27import org.junit.Test;
-28
-29/**
-30 *
-31 * @author Jeremy Long <jeremy.long@owasp.org>
-32 */
-33publicclassAnalyzerServiceTest {
-34
-35publicAnalyzerServiceTest() {
-36 }
-37
-38 @BeforeClass
-39publicstaticvoid setUpClass() throws Exception {
-40 }
-41
-42 @AfterClass
-43publicstaticvoid tearDownClass() throws Exception {
-44 }
-45
-46 @Before
-47publicvoid setUp() {
-48 }
-49
-50 @After
-51publicvoid tearDown() {
-52 }
-53
-54/**
-55 * Test of getAnalyzers method, of class AnalyzerService.
-56 */
-57 @Test
-58publicvoid testGetAnalyzers() {
-59 AnalyzerService instance = AnalyzerService.getInstance();
-60 Iterator<Analyzer> result = instance.getAnalyzers();
-61
-62boolean found = false;
-63while (result.hasNext()) {
-64 Analyzer a = result.next();
-65 Set<String> e = a.getSupportedExtensions();
-66if (e != null && e.contains("jar")) {
-67 found = true;
-68 }
-69 }
-70 assertTrue("JarAnalyzer loaded", found);
-71 }
-72 }
+21import org.junit.After;
+22import org.junit.AfterClass;
+23importstatic org.junit.Assert.assertTrue;
+24import org.junit.Before;
+25import org.junit.BeforeClass;
+26import org.junit.Test;
+27
+28/**
+29 *
+30 * @author Jeremy Long <jeremy.long@owasp.org>
+31 */
+32publicclassAnalyzerServiceTest {
+33
+34publicAnalyzerServiceTest() {
+35 }
+36
+37 @BeforeClass
+38publicstaticvoid setUpClass() throws Exception {
+39 }
+40
+41 @AfterClass
+42publicstaticvoid tearDownClass() throws Exception {
+43 }
+44
+45 @Before
+46publicvoid setUp() {
+47 }
+48
+49 @After
+50publicvoid tearDown() {
+51 }
+52
+53/**
+54 * Test of getAnalyzers method, of class AnalyzerService.
+55 */
+56 @Test
+57publicvoid testGetAnalyzers() {
+58 AnalyzerService instance = AnalyzerService.getInstance();
+59 Iterator<Analyzer> result = instance.getAnalyzers();
+60
+61boolean found = false;
+62while (result.hasNext()) {
+63 Analyzer a = result.next();
+64if ("Jar Analyzer".equals(a.getName())) {
+65 found = true;
+66 }
+67 }
+68 assertTrue("JarAnalyzer loaded", found);
+69 }
+70 }
diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.html
index aa32d7692..ffca3d2e7 100644
--- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.html
+++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.html
@@ -34,7 +34,7 @@
26import org.junit.BeforeClass;
27import org.junit.Test;
28import org.owasp.dependencycheck.Engine;
-29import org.owasp.dependencycheck.data.cpe.BaseIndexTestCase;
+29import org.owasp.dependencycheck.data.cpe.AbstractDatabaseTestCase;
30import org.owasp.dependencycheck.dependency.Dependency;
31import org.owasp.dependencycheck.utils.Settings;
32
@@ -42,7 +42,7 @@
34 *35 * @author Jeremy Long <jeremy.long@owasp.org>36 */
-37publicclassArchiveAnalyzerTestextendsBaseIndexTestCase {
+37publicclassArchiveAnalyzerTestextendsAbstractDatabaseTestCase {
3839publicArchiveAnalyzerTest() {
40 }
@@ -155,161 +155,165 @@
147 @Test
148publicvoid testAnalyze() throws Exception {
149 ArchiveAnalyzer instance = new ArchiveAnalyzer();
-150try {
-151 instance.initialize();
-152
-153 File file = new File(this.getClass().getClassLoader().getResource("daytrader-ear-2.1.7.ear").getPath());
-154 Dependency dependency = new Dependency(file);
-155 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
-156 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
-157 Engine engine = new Engine();
-158
-159int initial_size = engine.getDependencies().size();
-160 instance.analyze(dependency, engine);
-161int ending_size = engine.getDependencies().size();
-162
-163 engine.cleanup();
+150//trick the analyzer into thinking it is active.
+151 instance.supportsExtension("ear");
+152try {
+153 instance.initialize();
+154
+155 File file = new File(this.getClass().getClassLoader().getResource("daytrader-ear-2.1.7.ear").getPath());
+156 Dependency dependency = new Dependency(file);
+157 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
+158 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
+159 Engine engine = new Engine();
+160
+161int initial_size = engine.getDependencies().size();
+162 instance.analyze(dependency, engine);
+163int ending_size = engine.getDependencies().size();
164
-165 assertTrue(initial_size < ending_size);
+165 engine.cleanup();
166
-167 } finally {
-168 instance.close();
-169 }
-170 }
-171
-172/**
-173 * Test of analyze method, of class ArchiveAnalyzer.
-174 */
-175 @Test
-176publicvoid testAnalyzeTar() throws Exception {
-177 ArchiveAnalyzer instance = new ArchiveAnalyzer();
-178try {
-179 instance.initialize();
-180
-181//File file = new File(this.getClass().getClassLoader().getResource("file.tar").getPath());
-182 File file = new File(this.getClass().getClassLoader().getResource("stagedhttp-modified.tar").getPath());
-183 Dependency dependency = new Dependency(file);
-184 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
-185 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
-186 Engine engine = new Engine();
-187
-188int initial_size = engine.getDependencies().size();
-189 instance.analyze(dependency, engine);
-190int ending_size = engine.getDependencies().size();
-191 engine.cleanup();
-192
-193 assertTrue(initial_size < ending_size);
-194
-195 } finally {
-196 instance.close();
-197 }
-198 }
-199
-200/**
-201 * Test of analyze method, of class ArchiveAnalyzer.
-202 */
-203 @Test
-204publicvoid testAnalyzeTarGz() throws Exception {
-205 ArchiveAnalyzer instance = new ArchiveAnalyzer();
-206try {
-207 instance.initialize();
-208
-209 File file = new File(this.getClass().getClassLoader().getResource("file.tar.gz").getPath());
-210//Dependency dependency = new Dependency(file);
-211 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
-212 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
-213 Engine engine = new Engine();
-214
-215int initial_size = engine.getDependencies().size();
-216//instance.analyze(dependency, engine);
-217 engine.scan(file);
-218 engine.analyzeDependencies();
-219int ending_size = engine.getDependencies().size();
-220 engine.cleanup();
-221 assertTrue(initial_size < ending_size);
-222
-223 } finally {
-224 instance.close();
-225 }
-226 }
-227
-228// /**
-229// * Test of analyze method, of class ArchiveAnalyzer.
-230// */
-231// @Test
-232// public void testNestedZipFolder() throws Exception {
-233// ArchiveAnalyzer instance = new ArchiveAnalyzer();
-234// try {
-235// instance.initialize();
-236//
-237// File file = new File(this.getClass().getClassLoader().getResource("nested.zip").getPath());
-238// Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
-239// Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
-240// Engine engine = new Engine();
-241//
-242// engine.scan(file);
-243// engine.analyzeDependencies();
-244//
-245// } finally {
-246// instance.close();
-247// }
-248// }
-249/**
-250 * Test of analyze method, of class ArchiveAnalyzer.
-251 */
-252 @Test
-253publicvoid testAnalyzeTgz() throws Exception {
-254 ArchiveAnalyzer instance = new ArchiveAnalyzer();
-255try {
-256 instance.initialize();
-257
-258 File file = new File(this.getClass().getClassLoader().getResource("file.tgz").getPath());
-259 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
-260 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
-261 Engine engine = new Engine();
-262
-263int initial_size = engine.getDependencies().size();
-264 engine.scan(file);
-265 engine.analyzeDependencies();
-266int ending_size = engine.getDependencies().size();
-267 engine.cleanup();
-268 assertTrue(initial_size < ending_size);
-269
-270 } finally {
-271 instance.close();
-272 }
-273 }
-274
-275/**
-276 * Test of analyze method, of class ArchiveAnalyzer.
-277 */
-278 @Test
-279publicvoid testAnalyze_badZip() throws Exception {
-280 ArchiveAnalyzer instance = new ArchiveAnalyzer();
-281try {
-282 instance.initialize();
-283
-284 File file = new File(this.getClass().getClassLoader().getResource("test.zip").getPath());
-285 Dependency dependency = new Dependency(file);
-286 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
-287 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
-288 Engine engine = new Engine();
-289int initial_size = engine.getDependencies().size();
-290// boolean failed = false;
-291// try {
-292 instance.analyze(dependency, engine);
-293// } catch (java.lang.UnsupportedClassVersionError ex) {
-294// failed = true;
-295// }
-296// assertTrue(failed);
-297int ending_size = engine.getDependencies().size();
-298 engine.cleanup();
-299 assertEquals(initial_size, ending_size);
-300 } finally {
-301 instance.close();
-302 }
-303 }
-304 }
+167 assertTrue(initial_size < ending_size);
+168
+169 } finally {
+170 instance.close();
+171 }
+172 }
+173
+174/**
+175 * Test of analyze method, of class ArchiveAnalyzer.
+176 */
+177 @Test
+178publicvoid testAnalyzeTar() throws Exception {
+179 ArchiveAnalyzer instance = new ArchiveAnalyzer();
+180//trick the analyzer into thinking it is active so that it will initialize
+181 instance.supportsExtension("tar");
+182try {
+183 instance.initialize();
+184
+185//File file = new File(this.getClass().getClassLoader().getResource("file.tar").getPath());
+186 File file = new File(this.getClass().getClassLoader().getResource("stagedhttp-modified.tar").getPath());
+187 Dependency dependency = new Dependency(file);
+188 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
+189 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
+190 Engine engine = new Engine();
+191
+192int initial_size = engine.getDependencies().size();
+193 instance.analyze(dependency, engine);
+194int ending_size = engine.getDependencies().size();
+195 engine.cleanup();
+196
+197 assertTrue(initial_size < ending_size);
+198
+199 } finally {
+200 instance.close();
+201 }
+202 }
+203
+204/**
+205 * Test of analyze method, of class ArchiveAnalyzer.
+206 */
+207 @Test
+208publicvoid testAnalyzeTarGz() throws Exception {
+209 ArchiveAnalyzer instance = new ArchiveAnalyzer();
+210try {
+211 instance.initialize();
+212
+213 File file = new File(this.getClass().getClassLoader().getResource("file.tar.gz").getPath());
+214//Dependency dependency = new Dependency(file);
+215 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
+216 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
+217 Engine engine = new Engine();
+218
+219int initial_size = engine.getDependencies().size();
+220//instance.analyze(dependency, engine);
+221 engine.scan(file);
+222 engine.analyzeDependencies();
+223int ending_size = engine.getDependencies().size();
+224 engine.cleanup();
+225 assertTrue(initial_size < ending_size);
+226
+227 } finally {
+228 instance.close();
+229 }
+230 }
+231
+232// /**
+233// * Test of analyze method, of class ArchiveAnalyzer.
+234// */
+235// @Test
+236// public void testNestedZipFolder() throws Exception {
+237// ArchiveAnalyzer instance = new ArchiveAnalyzer();
+238// try {
+239// instance.initialize();
+240//
+241// File file = new File(this.getClass().getClassLoader().getResource("nested.zip").getPath());
+242// Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
+243// Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
+244// Engine engine = new Engine();
+245//
+246// engine.scan(file);
+247// engine.analyzeDependencies();
+248//
+249// } finally {
+250// instance.close();
+251// }
+252// }
+253/**
+254 * Test of analyze method, of class ArchiveAnalyzer.
+255 */
+256 @Test
+257publicvoid testAnalyzeTgz() throws Exception {
+258 ArchiveAnalyzer instance = new ArchiveAnalyzer();
+259try {
+260 instance.initialize();
+261
+262 File file = new File(this.getClass().getClassLoader().getResource("file.tgz").getPath());
+263 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
+264 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
+265 Engine engine = new Engine();
+266
+267int initial_size = engine.getDependencies().size();
+268 engine.scan(file);
+269 engine.analyzeDependencies();
+270int ending_size = engine.getDependencies().size();
+271 engine.cleanup();
+272 assertTrue(initial_size < ending_size);
+273
+274 } finally {
+275 instance.close();
+276 }
+277 }
+278
+279/**
+280 * Test of analyze method, of class ArchiveAnalyzer.
+281 */
+282 @Test
+283publicvoid testAnalyze_badZip() throws Exception {
+284 ArchiveAnalyzer instance = new ArchiveAnalyzer();
+285try {
+286 instance.initialize();
+287
+288 File file = new File(this.getClass().getClassLoader().getResource("test.zip").getPath());
+289 Dependency dependency = new Dependency(file);
+290 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
+291 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
+292 Engine engine = new Engine();
+293int initial_size = engine.getDependencies().size();
+294// boolean failed = false;
+295// try {
+296 instance.analyze(dependency, engine);
+297// } catch (java.lang.UnsupportedClassVersionError ex) {
+298// failed = true;
+299// }
+300// assertTrue(failed);
+301int ending_size = engine.getDependencies().size();
+302 engine.cleanup();
+303 assertEquals(initial_size, ending_size);
+304 } finally {
+305 instance.close();
+306 }
+307 }
+308 }
diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html
index f3ee10d67..5a964fa74 100644
--- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html
+++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html
@@ -25,121 +25,162 @@
17 */18package org.owasp.dependencycheck.analyzer;
19
-20import java.io.File;
-21import java.util.logging.Level;
-22import java.util.logging.Logger;
-23import org.junit.After;
-24importstatic org.junit.Assert.assertEquals;
-25importstatic org.junit.Assert.assertTrue;
-26import org.junit.Assume;
-27importstatic org.junit.Assume.assumeFalse;
-28import org.junit.Before;
-29import org.junit.Test;
-30import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
-31import org.owasp.dependencycheck.dependency.Confidence;
-32import org.owasp.dependencycheck.dependency.Dependency;
-33import org.owasp.dependencycheck.dependency.Evidence;
-34import org.owasp.dependencycheck.utils.Settings;
-35
-36/**
-37 * Tests for the AssemblyAnalyzer.
-38 *
-39 * @author colezlaw
-40 *
-41 */
-42publicclassAssemblyAnalyzerTest {
-43
-44privatestaticfinal Logger LOGGER = Logger.getLogger(AssemblyAnalyzerTest.class.getName());
-45
-46 AssemblyAnalyzer analyzer;
-47
-48/**
-49 * Sets up the analyzer.
-50 *
-51 * @throws Exception if anything goes sideways
-52 */
-53 @Before
-54publicvoid setUp() {
-55try {
-56 analyzer = new AssemblyAnalyzer();
-57 analyzer.initialize();
-58 } catch (Exception e) {
-59 LOGGER.log(Level.WARNING, "Exception setting up AssemblyAnalyzer. Tests will be incomplete", e);
-60 Assume.assumeNoException("Is mono installed? TESTS WILL BE INCOMPLETE", e);
-61 }
-62 }
-63
-64/**
-65 * Tests to make sure the name is correct.
-66 */
-67 @Test
-68publicvoid testGetName() {
-69 assertEquals("Assembly Analyzer", analyzer.getName());
-70 }
-71
-72 @Test
-73publicvoid testAnalysis() throws Exception {
-74 File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("GrokAssembly.exe").getPath());
-75 Dependency d = new Dependency(f);
-76 analyzer.analyze(d, null);
-77 assertTrue(d.getVersionEvidence().getEvidence().contains(new Evidence("grokassembly", "version", "1.0.5176.23901", Confidence.HIGHEST)));
-78 }
-79
-80 @Test
-81publicvoid testLog4Net() throws Exception {
-82 File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath());
-83 Dependency d = new Dependency(f);
-84 analyzer.analyze(d, null);
-85 assertTrue(d.getVersionEvidence().getEvidence().contains(new Evidence("grokassembly", "version", "1.2.13.0", Confidence.HIGHEST)));
-86 assertTrue(d.getVendorEvidence().getEvidence().contains(new Evidence("grokassembly", "vendor", "The Apache Software Foundation", Confidence.HIGH)));
-87 assertTrue(d.getProductEvidence().getEvidence().contains(new Evidence("grokassembly", "product", "log4net", Confidence.HIGH)));
-88 }
-89
-90 @Test(expected = AnalysisException.class)
-91publicvoid testNonexistent() throws Exception {
-92 File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath());
-93 File test = new File(f.getParent(), "nonexistent.dll");
-94 Dependency d = new Dependency(test);
-95 analyzer.analyze(d, null);
+20importstatic org.junit.Assert.assertEquals;
+21importstatic org.junit.Assert.assertTrue;
+22importstatic org.junit.Assert.fail;
+23importstatic org.junit.Assume.assumeFalse;
+24
+25import java.io.File;
+26import java.util.logging.Level;
+27import java.util.logging.Logger;
+28
+29import org.junit.After;
+30import org.junit.Assume;
+31import org.junit.Before;
+32import org.junit.Test;
+33import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+34import org.owasp.dependencycheck.dependency.Confidence;
+35import org.owasp.dependencycheck.dependency.Dependency;
+36import org.owasp.dependencycheck.dependency.Evidence;
+37import org.owasp.dependencycheck.utils.Settings;
+38
+39/**
+40 * Tests for the AssemblyAnalyzer.
+41 *
+42 * @author colezlaw
+43 *
+44 */
+45publicclassAssemblyAnalyzerTest {
+46
+47privatestaticfinal Logger LOGGER = Logger.getLogger(AssemblyAnalyzerTest.class.getName());
+48
+49 AssemblyAnalyzer analyzer;
+50
+51/**
+52 * Sets up the analyzer.
+53 *
+54 * @throws Exception if anything goes sideways
+55 */
+56 @Before
+57publicvoid setUp() {
+58try {
+59 analyzer = new AssemblyAnalyzer();
+60 analyzer.supportsExtension("dll");
+61 analyzer.initialize();
+62 } catch (Exception e) {
+63 LOGGER.log(Level.WARNING, "Exception setting up AssemblyAnalyzer. Tests will be incomplete", e);
+64 Assume.assumeNoException("Is mono installed? TESTS WILL BE INCOMPLETE", e);
+65 }
+66 }
+67
+68/**
+69 * Tests to make sure the name is correct.
+70 */
+71 @Test
+72publicvoid testGetName() {
+73 assertEquals("Assembly Analyzer", analyzer.getName());
+74 }
+75
+76 @Test
+77publicvoid testAnalysis() throws Exception {
+78 File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("GrokAssembly.exe").getPath());
+79 Dependency d = new Dependency(f);
+80 analyzer.analyze(d, null);
+81boolean foundVendor = false;
+82for (Evidence e : d.getVendorEvidence().getEvidence("grokassembly", "vendor")) {
+83if ("OWASP".equals(e.getValue())) {
+84 foundVendor = true;
+85 }
+86 }
+87 assertTrue(foundVendor);
+88
+89boolean foundProduct = false;
+90for (Evidence e : d.getProductEvidence().getEvidence("grokassembly", "product")) {
+91if ("GrokAssembly".equals(e.getValue())) {
+92 foundProduct = true;
+93 }
+94 }
+95 assertTrue(foundProduct);
96 }
97
-98 @Test(expected = AnalysisException.class)
-99publicvoid testWithSettingMono() throws Exception {
-100
-101//This test doesn't work on Windows.
-102 assumeFalse(System.getProperty("os.name").startsWith("Windows"));
-103
-104 String oldValue = Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH);
-105// if oldValue is null, that means that neither the system property nor the setting has
-106// been set. If that's the case, then we have to make it such that when we recover,
-107// null still comes back. But you can't put a null value in a HashMap, so we have to set
-108// the system property rather than the setting.
-109if (oldValue == null) {
-110 System.setProperty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono");
-111 } else {
-112 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono");
-113 }
-114
-115try {
-116// Have to make a NEW analyzer because during setUp, it would have gotten the correct one
-117 AssemblyAnalyzer aanalyzer = new AssemblyAnalyzer();
-118 aanalyzer.initialize();
-119 } finally {
-120// Now recover the way we came in. If we had to set a System property, delete it. Otherwise,
-121// reset the old value
-122if (oldValue == null) {
-123 System.getProperties().remove(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH);
-124 } else {
-125 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, oldValue);
-126 }
+98 @Test
+99publicvoid testLog4Net() throws Exception {
+100 File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath());
+101 Dependency d = new Dependency(f);
+102 analyzer.analyze(d, null);
+103 assertTrue(d.getVersionEvidence().getEvidence().contains(new Evidence("grokassembly", "version", "1.2.13.0", Confidence.HIGHEST)));
+104 assertTrue(d.getVendorEvidence().getEvidence().contains(new Evidence("grokassembly", "vendor", "The Apache Software Foundation", Confidence.HIGH)));
+105 assertTrue(d.getProductEvidence().getEvidence().contains(new Evidence("grokassembly", "product", "log4net", Confidence.HIGH)));
+106 }
+107
+108 @Test
+109publicvoid testNonexistent() {
+110 Level oldLevel = Logger.getLogger(AssemblyAnalyzer.class.getName()).getLevel();
+111 Level oldDependency = Logger.getLogger(Dependency.class.getName()).getLevel();
+112// Tweak the log level so the warning doesn't show in the console
+113 Logger.getLogger(AssemblyAnalyzer.class.getName()).setLevel(Level.OFF);
+114 Logger.getLogger(Dependency.class.getName()).setLevel(Level.OFF);
+115 File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath());
+116 File test = new File(f.getParent(), "nonexistent.dll");
+117 Dependency d = new Dependency(test);
+118
+119try {
+120 analyzer.analyze(d, null);
+121 fail("Expected an AnalysisException");
+122 } catch (AnalysisException ae) {
+123 assertEquals("File does not exist", ae.getMessage());
+124 } finally {
+125 Logger.getLogger(AssemblyAnalyzer.class.getName()).setLevel(oldLevel);
+126 Logger.getLogger(Dependency.class.getName()).setLevel(oldDependency);
127 }
128 }
129
-130 @After
-131publicvoid tearDown() throws Exception {
-132 analyzer.close();
-133 }
-134 }
+130 @Test
+131publicvoid testWithSettingMono() throws Exception {
+132
+133//This test doesn't work on Windows.
+134 assumeFalse(System.getProperty("os.name").startsWith("Windows"));
+135
+136 String oldValue = Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH);
+137// if oldValue is null, that means that neither the system property nor the setting has
+138// been set. If that's the case, then we have to make it such that when we recover,
+139// null still comes back. But you can't put a null value in a HashMap, so we have to set
+140// the system property rather than the setting.
+141if (oldValue == null) {
+142 System.setProperty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono");
+143 } else {
+144 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono");
+145 }
+146
+147 Level oldLevel = Logger.getLogger(AssemblyAnalyzer.class.getName()).getLevel();
+148try {
+149// Tweak the logging to swallow the warning when testing
+150 Logger.getLogger(AssemblyAnalyzer.class.getName()).setLevel(Level.OFF);
+151// Have to make a NEW analyzer because during setUp, it would have gotten the correct one
+152 AssemblyAnalyzer aanalyzer = new AssemblyAnalyzer();
+153 aanalyzer.supportsExtension("dll");
+154 aanalyzer.initialize();
+155 fail("Expected an AnalysisException");
+156 } catch (AnalysisException ae) {
+157 assertEquals("An error occured with the .NET AssemblyAnalyzer", ae.getMessage());
+158 } finally {
+159// Recover the logger
+160 Logger.getLogger(AssemblyAnalyzer.class.getName()).setLevel(oldLevel);
+161// Now recover the way we came in. If we had to set a System property, delete it. Otherwise,
+162// reset the old value
+163if (oldValue == null) {
+164 System.getProperties().remove(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH);
+165 } else {
+166 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, oldValue);
+167 }
+168 }
+169 }
+170
+171 @After
+172publicvoid tearDown() throws Exception {
+173 analyzer.close();
+174 }
+175 }
diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerTest.html
index 1629b352f..f1244d14f 100644
--- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerTest.html
+++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerTest.html
@@ -38,7 +38,7 @@
30import org.junit.Before;
31import org.junit.BeforeClass;
32import org.junit.Test;
-33import org.owasp.dependencycheck.data.cpe.BaseIndexTestCase;
+33import org.owasp.dependencycheck.data.cpe.AbstractDatabaseTestCase;
34import org.owasp.dependencycheck.data.cpe.IndexEntry;
35import org.owasp.dependencycheck.dependency.Dependency;
36import org.owasp.dependencycheck.dependency.Identifier;
@@ -47,7 +47,7 @@
39 *40 * @author Jeremy Long <jeremy.long@owasp.org>41 */
-42publicclassCPEAnalyzerTestextendsBaseIndexTestCase {
+42publicclassCPEAnalyzerTestextendsAbstractDatabaseTestCase {
4344 @BeforeClass
45publicstaticvoid setUpClass() throws Exception {
diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.html
index cee6f927a..1e7f1efad 100644
--- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.html
+++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.html
@@ -25,122 +25,98 @@
17 */18package org.owasp.dependencycheck.analyzer;
19
-20import java.util.Set;
-21import org.junit.After;
-22import org.junit.AfterClass;
-23importstatic org.junit.Assert.assertEquals;
-24importstatic org.junit.Assert.assertNull;
-25import org.junit.Before;
-26import org.junit.BeforeClass;
-27import org.junit.Test;
-28import org.owasp.dependencycheck.dependency.Dependency;
-29
-30/**
-31 *
-32 * @author Jeremy Long <jeremy.long@owasp.org>
-33 */
-34publicclassDependencyBundlingAnalyzerTest {
-35
-36publicDependencyBundlingAnalyzerTest() {
-37 }
-38
-39 @BeforeClass
-40publicstaticvoid setUpClass() {
-41 }
-42
-43 @AfterClass
-44publicstaticvoid tearDownClass() {
-45 }
-46
-47 @Before
-48publicvoid setUp() {
-49 }
-50
-51 @After
-52publicvoid tearDown() {
-53 }
-54
-55/**
-56 * Test of getSupportedExtensions method, of class DependencyBundlingAnalyzer.
-57 */
-58 @Test
-59publicvoid testGetSupportedExtensions() {
-60 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
-61 Set<String> result = instance.getSupportedExtensions();
-62 assertNull(result);
-63 }
-64
-65/**
-66 * Test of getName method, of class DependencyBundlingAnalyzer.
-67 */
-68 @Test
-69publicvoid testGetName() {
-70 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
-71 String expResult = "Dependency Bundling Analyzer";
-72 String result = instance.getName();
-73 assertEquals(expResult, result);
-74 }
-75
-76/**
-77 * Test of supportsExtension method, of class DependencyBundlingAnalyzer.
-78 */
-79 @Test
-80publicvoid testSupportsExtension() {
-81 String extension = "jar";
-82 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
-83boolean expResult = true;
-84boolean result = instance.supportsExtension(extension);
-85 assertEquals(expResult, result);
+20import org.junit.After;
+21import org.junit.AfterClass;
+22importstatic org.junit.Assert.assertEquals;
+23import org.junit.Before;
+24import org.junit.BeforeClass;
+25import org.junit.Test;
+26import org.owasp.dependencycheck.dependency.Dependency;
+27
+28/**
+29 *
+30 * @author Jeremy Long <jeremy.long@owasp.org>
+31 */
+32publicclassDependencyBundlingAnalyzerTest {
+33
+34publicDependencyBundlingAnalyzerTest() {
+35 }
+36
+37 @BeforeClass
+38publicstaticvoid setUpClass() {
+39 }
+40
+41 @AfterClass
+42publicstaticvoid tearDownClass() {
+43 }
+44
+45 @Before
+46publicvoid setUp() {
+47 }
+48
+49 @After
+50publicvoid tearDown() {
+51 }
+52
+53/**
+54 * Test of getName method, of class DependencyBundlingAnalyzer.
+55 */
+56 @Test
+57publicvoid testGetName() {
+58 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
+59 String expResult = "Dependency Bundling Analyzer";
+60 String result = instance.getName();
+61 assertEquals(expResult, result);
+62 }
+63
+64/**
+65 * Test of getAnalysisPhase method, of class DependencyBundlingAnalyzer.
+66 */
+67 @Test
+68publicvoid testGetAnalysisPhase() {
+69 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
+70 AnalysisPhase expResult = AnalysisPhase.PRE_FINDING_ANALYSIS;
+71 AnalysisPhase result = instance.getAnalysisPhase();
+72 assertEquals(expResult, result);
+73 }
+74
+75/**
+76 * Test of analyze method, of class DependencyBundlingAnalyzer.
+77 */
+78 @Test
+79publicvoid testAnalyze() throws Exception {
+80// Dependency ignore = null;
+81// Engine engine = null;
+82// DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
+83// instance.analyze(ignore, engine);
+84// // TODO review the generated test code and remove the default call to fail.
+85// fail("The test case is a prototype.");86 }
8788/**
-89 * Test of getAnalysisPhase method, of class DependencyBundlingAnalyzer.
+89 * Test of isCore method, of class DependencyBundlingAnalyzer.90 */91 @Test
-92publicvoid testGetAnalysisPhase() {
-93 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
-94 AnalysisPhase expResult = AnalysisPhase.PRE_FINDING_ANALYSIS;
-95 AnalysisPhase result = instance.getAnalysisPhase();
-96 assertEquals(expResult, result);
-97 }
-98
-99/**
-100 * Test of analyze method, of class DependencyBundlingAnalyzer.
-101 */
-102 @Test
-103publicvoid testAnalyze() throws Exception {
-104// Dependency ignore = null;
-105// Engine engine = null;
-106// DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
-107// instance.analyze(ignore, engine);
-108// // TODO review the generated test code and remove the default call to fail.
-109// fail("The test case is a prototype.");
-110 }
-111
-112/**
-113 * Test of isCore method, of class DependencyBundlingAnalyzer.
-114 */
-115 @Test
-116publicvoid testIsCore() {
-117 Dependency left = new Dependency();
-118 Dependency right = new Dependency();
-119
-120 left.setFileName("axis2-kernel-1.4.1.jar");
-121 right.setFileName("axis2-adb-1.4.1.jar");
-122 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
-123boolean expResult = true;
-124boolean result = instance.isCore(left, right);
-125 assertEquals(expResult, result);
-126
-127 left.setFileName("struts-1.2.7.jar");
-128 right.setFileName("file.tar.gz\\file.tar\\struts.jar");
-129
-130 expResult = true;
-131 result = instance.isCore(left, right);
-132 assertEquals(expResult, result);
-133 }
-134
-135 }
+92publicvoid testIsCore() {
+93 Dependency left = new Dependency();
+94 Dependency right = new Dependency();
+95
+96 left.setFileName("axis2-kernel-1.4.1.jar");
+97 right.setFileName("axis2-adb-1.4.1.jar");
+98 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
+99boolean expResult = true;
+100boolean result = instance.isCore(left, right);
+101 assertEquals(expResult, result);
+102
+103 left.setFileName("struts-1.2.7.jar");
+104 right.setFileName("file.tar.gz\\file.tar\\struts.jar");
+105
+106 expResult = true;
+107 result = instance.isCore(left, right);
+108 assertEquals(expResult, result);
+109 }
+110
+111 }
diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzerTest.html
index a18be0771..c3645d231 100644
--- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzerTest.html
+++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzerTest.html
@@ -23,105 +23,80 @@
15 */16package org.owasp.dependencycheck.analyzer;
17
-18import java.util.Set;
-19import org.junit.After;
-20import org.junit.AfterClass;
-21importstatic org.junit.Assert.assertEquals;
-22importstatic org.junit.Assert.assertNull;
-23importstatic org.junit.Assert.assertTrue;
-24import org.junit.Before;
-25import org.junit.BeforeClass;
-26import org.junit.Test;
-27import org.owasp.dependencycheck.Engine;
-28import org.owasp.dependencycheck.dependency.Dependency;
-29
-30/**
-31 *
-32 * @author Jeremy Long <jeremy.long@owasp.org>
-33 */
-34publicclassFalsePositiveAnalyzerTest {
-35
-36publicFalsePositiveAnalyzerTest() {
-37 }
-38
-39 @BeforeClass
-40publicstaticvoid setUpClass() {
-41 }
-42
-43 @AfterClass
-44publicstaticvoid tearDownClass() {
-45 }
-46
-47 @Before
-48publicvoid setUp() {
-49 }
-50
-51 @After
-52publicvoid tearDown() {
-53 }
-54
-55/**
-56 * Test of getSupportedExtensions method, of class FalsePositiveAnalyzer.
-57 */
-58 @Test
-59publicvoid testGetSupportedExtensions() {
-60 FalsePositiveAnalyzer instance = new FalsePositiveAnalyzer();
-61 Set<String> result = instance.getSupportedExtensions();
-62 assertNull(result);
+18import org.junit.After;
+19import org.junit.AfterClass;
+20importstatic org.junit.Assert.assertEquals;
+21importstatic org.junit.Assert.assertTrue;
+22import org.junit.Before;
+23import org.junit.BeforeClass;
+24import org.junit.Test;
+25import org.owasp.dependencycheck.Engine;
+26import org.owasp.dependencycheck.dependency.Dependency;
+27
+28/**
+29 *
+30 * @author Jeremy Long <jeremy.long@owasp.org>
+31 */
+32publicclassFalsePositiveAnalyzerTest {
+33
+34publicFalsePositiveAnalyzerTest() {
+35 }
+36
+37 @BeforeClass
+38publicstaticvoid setUpClass() {
+39 }
+40
+41 @AfterClass
+42publicstaticvoid tearDownClass() {
+43 }
+44
+45 @Before
+46publicvoid setUp() {
+47 }
+48
+49 @After
+50publicvoid tearDown() {
+51 }
+52
+53/**
+54 * Test of getName method, of class FalsePositiveAnalyzer.
+55 */
+56 @Test
+57publicvoid testGetName() {
+58 FalsePositiveAnalyzer instance = new FalsePositiveAnalyzer();
+59 String expResult = "False Positive Analyzer";
+60 String result = instance.getName();
+61 assertEquals(expResult, result);
+62 }
63
-64 }
-65
-66/**
-67 * Test of getName method, of class FalsePositiveAnalyzer.
-68 */
-69 @Test
-70publicvoid testGetName() {
-71 FalsePositiveAnalyzer instance = new FalsePositiveAnalyzer();
-72 String expResult = "False Positive Analyzer";
-73 String result = instance.getName();
-74 assertEquals(expResult, result);
-75 }
-76
-77/**
-78 * Test of supportsExtension method, of class FalsePositiveAnalyzer.
-79 */
-80 @Test
-81publicvoid testSupportsExtension() {
-82 String extension = "any";
-83 FalsePositiveAnalyzer instance = new FalsePositiveAnalyzer();
-84boolean expResult = true;
-85boolean result = instance.supportsExtension(extension);
-86 assertEquals(expResult, result);
-87 }
-88
-89/**
-90 * Test of getAnalysisPhase method, of class FalsePositiveAnalyzer.
-91 */
-92 @Test
-93publicvoid testGetAnalysisPhase() {
-94 FalsePositiveAnalyzer instance = new FalsePositiveAnalyzer();
-95 AnalysisPhase expResult = AnalysisPhase.POST_IDENTIFIER_ANALYSIS;
-96 AnalysisPhase result = instance.getAnalysisPhase();
-97 assertEquals(expResult, result);
-98 }
-99
-100/**
-101 * Test of analyze method, of class FalsePositiveAnalyzer.
-102 */
-103 @Test
-104publicvoid testAnalyze() throws Exception {
-105 Dependency dependency = new Dependency();
-106 dependency.setFileName("pom.xml");
-107 dependency.addIdentifier("cpe", "cpe:/a:file:file:1.2.1", "http://some.org/url");
-108 Engine engine = null;
-109 FalsePositiveAnalyzer instance = new FalsePositiveAnalyzer();
-110int before = dependency.getIdentifiers().size();
-111 instance.analyze(dependency, engine);
-112int after = dependency.getIdentifiers().size();
-113 assertTrue(before > after);
-114 }
-115
-116 }
+64/**
+65 * Test of getAnalysisPhase method, of class FalsePositiveAnalyzer.
+66 */
+67 @Test
+68publicvoid testGetAnalysisPhase() {
+69 FalsePositiveAnalyzer instance = new FalsePositiveAnalyzer();
+70 AnalysisPhase expResult = AnalysisPhase.POST_IDENTIFIER_ANALYSIS;
+71 AnalysisPhase result = instance.getAnalysisPhase();
+72 assertEquals(expResult, result);
+73 }
+74
+75/**
+76 * Test of analyze method, of class FalsePositiveAnalyzer.
+77 */
+78 @Test
+79publicvoid testAnalyze() throws Exception {
+80 Dependency dependency = new Dependency();
+81 dependency.setFileName("pom.xml");
+82 dependency.addIdentifier("cpe", "cpe:/a:file:file:1.2.1", "http://some.org/url");
+83 Engine engine = null;
+84 FalsePositiveAnalyzer instance = new FalsePositiveAnalyzer();
+85int before = dependency.getIdentifiers().size();
+86 instance.analyze(dependency, engine);
+87int after = dependency.getIdentifiers().size();
+88 assertTrue(before > after);
+89 }
+90
+91 }
diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/FileNameAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/FileNameAnalyzerTest.html
index d36042a02..8152d5296 100644
--- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/FileNameAnalyzerTest.html
+++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/FileNameAnalyzerTest.html
@@ -26,124 +26,100 @@
18package org.owasp.dependencycheck.analyzer;
1920import java.io.File;
-21import java.util.Set;
-22import org.junit.After;
-23import org.junit.AfterClass;
-24importstatic org.junit.Assert.assertEquals;
-25importstatic org.junit.Assert.assertTrue;
-26import org.junit.Before;
-27import org.junit.BeforeClass;
-28import org.junit.Test;
-29import org.owasp.dependencycheck.dependency.Dependency;
-30
-31/**
-32 *
-33 * @author Jeremy Long <jeremy.long@owasp.org>
-34 */
-35publicclassFileNameAnalyzerTest {
-36
-37publicFileNameAnalyzerTest() {
-38 }
-39
-40 @BeforeClass
-41publicstaticvoid setUpClass() throws Exception {
-42 }
-43
-44 @AfterClass
-45publicstaticvoid tearDownClass() throws Exception {
-46 }
-47
-48 @Before
-49publicvoid setUp() {
-50 }
-51
-52 @After
-53publicvoid tearDown() {
-54 }
-55
-56/**
-57 * Test of getSupportedExtensions method, of class FileNameAnalyzer.
-58 */
-59 @Test
-60publicvoid testGetSupportedExtensions() {
-61 FileNameAnalyzer instance = new FileNameAnalyzer();
-62 Set expResult = null;
-63 Set result = instance.getSupportedExtensions();
-64 assertEquals(expResult, result);
-65 }
-66
-67/**
-68 * Test of getName method, of class FileNameAnalyzer.
-69 */
-70 @Test
-71publicvoid testGetName() {
-72 FileNameAnalyzer instance = new FileNameAnalyzer();
-73 String expResult = "File Name Analyzer";
-74 String result = instance.getName();
-75 assertEquals(expResult, result);
-76 }
-77
-78/**
-79 * Test of supportsExtension method, of class FileNameAnalyzer.
-80 */
-81 @Test
-82publicvoid testSupportsExtension() {
-83 String extension = "any";
-84 FileNameAnalyzer instance = new FileNameAnalyzer();
-85boolean expResult = true;
-86boolean result = instance.supportsExtension(extension);
-87 assertEquals(expResult, result);
-88 }
+21import org.junit.After;
+22import org.junit.AfterClass;
+23importstatic org.junit.Assert.assertEquals;
+24importstatic org.junit.Assert.assertTrue;
+25import org.junit.Before;
+26import org.junit.BeforeClass;
+27import org.junit.Test;
+28import org.owasp.dependencycheck.dependency.Dependency;
+29
+30/**
+31 *
+32 * @author Jeremy Long <jeremy.long@owasp.org>
+33 */
+34publicclassFileNameAnalyzerTest {
+35
+36publicFileNameAnalyzerTest() {
+37 }
+38
+39 @BeforeClass
+40publicstaticvoid setUpClass() throws Exception {
+41 }
+42
+43 @AfterClass
+44publicstaticvoid tearDownClass() throws Exception {
+45 }
+46
+47 @Before
+48publicvoid setUp() {
+49 }
+50
+51 @After
+52publicvoid tearDown() {
+53 }
+54
+55/**
+56 * Test of getName method, of class FileNameAnalyzer.
+57 */
+58 @Test
+59publicvoid testGetName() {
+60 FileNameAnalyzer instance = new FileNameAnalyzer();
+61 String expResult = "File Name Analyzer";
+62 String result = instance.getName();
+63 assertEquals(expResult, result);
+64 }
+65
+66/**
+67 * Test of getAnalysisPhase method, of class FileNameAnalyzer.
+68 */
+69 @Test
+70publicvoid testGetAnalysisPhase() {
+71 FileNameAnalyzer instance = new FileNameAnalyzer();
+72 AnalysisPhase expResult = AnalysisPhase.INFORMATION_COLLECTION;
+73 AnalysisPhase result = instance.getAnalysisPhase();
+74 assertEquals(expResult, result);
+75 }
+76
+77/**
+78 * Test of analyze method, of class FileNameAnalyzer.
+79 */
+80 @Test
+81publicvoid testAnalyze() throws Exception {
+82 File struts = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
+83 Dependency resultStruts = new Dependency(struts);
+84 File axis = new File(this.getClass().getClassLoader().getResource("axis2-adb-1.4.1.jar").getPath());
+85 Dependency resultAxis = new Dependency(axis);
+86 FileNameAnalyzer instance = new FileNameAnalyzer();
+87 instance.analyze(resultStruts, null);
+88 assertTrue(resultStruts.getVendorEvidence().toString().toLowerCase().contains("struts"));
89
-90/**
-91 * Test of getAnalysisPhase method, of class FileNameAnalyzer.
-92 */
-93 @Test
-94publicvoid testGetAnalysisPhase() {
-95 FileNameAnalyzer instance = new FileNameAnalyzer();
-96 AnalysisPhase expResult = AnalysisPhase.INFORMATION_COLLECTION;
-97 AnalysisPhase result = instance.getAnalysisPhase();
-98 assertEquals(expResult, result);
-99 }
-100
-101/**
-102 * Test of analyze method, of class FileNameAnalyzer.
-103 */
-104 @Test
-105publicvoid testAnalyze() throws Exception {
-106 File struts = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
-107 Dependency resultStruts = new Dependency(struts);
-108 File axis = new File(this.getClass().getClassLoader().getResource("axis2-adb-1.4.1.jar").getPath());
-109 Dependency resultAxis = new Dependency(axis);
+90 instance.analyze(resultAxis, null);
+91 assertTrue(resultStruts.getVersionEvidence().toString().toLowerCase().contains("2.1.2"));
+92
+93 }
+94
+95/**
+96 * Test of initialize method, of class FileNameAnalyzer.
+97 */
+98 @Test
+99publicvoid testInitialize() throws Exception {
+100 FileNameAnalyzer instance = new FileNameAnalyzer();
+101 instance.initialize();
+102 assertTrue(true); //initialize does nothing.
+103 }
+104
+105/**
+106 * Test of close method, of class FileNameAnalyzer.
+107 */
+108 @Test
+109publicvoid testClose() throws Exception {
110 FileNameAnalyzer instance = new FileNameAnalyzer();
-111 instance.analyze(resultStruts, null);
-112 assertTrue(resultStruts.getVendorEvidence().toString().toLowerCase().contains("struts"));
-113
-114 instance.analyze(resultAxis, null);
-115 assertTrue(resultStruts.getVersionEvidence().toString().toLowerCase().contains("2.1.2"));
-116
-117 }
-118
-119/**
-120 * Test of initialize method, of class FileNameAnalyzer.
-121 */
-122 @Test
-123publicvoid testInitialize() throws Exception {
-124 FileNameAnalyzer instance = new FileNameAnalyzer();
-125 instance.initialize();
-126 assertTrue(true); //initialize does nothing.
-127 }
-128
-129/**
-130 * Test of close method, of class FileNameAnalyzer.
-131 */
-132 @Test
-133publicvoid testClose() throws Exception {
-134 FileNameAnalyzer instance = new FileNameAnalyzer();
-135 instance.close();
-136 assertTrue(true); //close does nothing.
-137 }
-138 }
+111 instance.close();
+112 assertTrue(true); //close does nothing.
+113 }
+114 }
diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/NuspecAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/NuspecAnalyzerTest.html
index 2b764dd77..02b058ef3 100644
--- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/NuspecAnalyzerTest.html
+++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/NuspecAnalyzerTest.html
@@ -25,42 +25,46 @@
17 */18package org.owasp.dependencycheck.analyzer;
19
-20import org.junit.Before;
-21import org.junit.Test;
-22importstatic org.junit.Assert.*;
-23
-24publicclassNuspecAnalyzerTest {
-25private NuspecAnalyzer instance;
-26
-27 @Before
-28publicvoid setUp() {
-29 instance = new NuspecAnalyzer();
-30 }
-31
-32 @Test
-33publicvoid testGetAnalyzerName() {
-34 assertEquals("Nuspec Analyzer", instance.getName());
-35 }
-36
-37 @Test
-38publicvoid testGetSupportedExtensions() {
-39 assertTrue(instance.getSupportedExtensions().contains("nuspec"));
-40 assertFalse(instance.getSupportedExtensions().contains("nupkg"));
-41 }
-42
-43 @Test
-44publicvoid testSupportsExtension() {
-45 assertTrue(instance.supportsExtension("nuspec"));
-46 assertFalse(instance.supportsExtension("nupkg"));
-47 }
-48
-49 @Test
-50publicvoid testGetAnalysisPhaze() {
-51 assertEquals(AnalysisPhase.INFORMATION_COLLECTION, instance.getAnalysisPhase());
-52 }
-53 }
-54
-55// vim: cc=120:sw=4:ts=4:sts=4
+20importstatic org.junit.Assert.assertEquals;
+21importstatic org.junit.Assert.assertFalse;
+22importstatic org.junit.Assert.assertTrue;
+23import org.junit.Before;
+24import org.junit.Test;
+25
+26publicclassNuspecAnalyzerTest {
+27
+28private NuspecAnalyzer instance;
+29
+30 @Before
+31publicvoid setUp() {
+32 instance = new NuspecAnalyzer();
+33 instance.setEnabled(true);
+34 }
+35
+36 @Test
+37publicvoid testGetAnalyzerName() {
+38 assertEquals("Nuspec Analyzer", instance.getName());
+39 }
+40
+41 @Test
+42publicvoid testGetSupportedExtensions() {
+43 assertTrue(instance.getSupportedExtensions().contains("nuspec"));
+44 assertFalse(instance.getSupportedExtensions().contains("nupkg"));
+45 }
+46
+47 @Test
+48publicvoid testSupportsExtension() {
+49 assertTrue(instance.supportsExtension("nuspec"));
+50 assertFalse(instance.supportsExtension("nupkg"));
+51 }
+52
+53 @Test
+54publicvoid testGetAnalysisPhaze() {
+55 assertEquals(AnalysisPhase.INFORMATION_COLLECTION, instance.getAnalysisPhase());
+56 }
+57 }
+58
+59// vim: cc=120:sw=4:ts=4:sts=4
diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerTest.html
new file mode 100644
index 000000000..81e27b85a
--- /dev/null
+++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzerTest.html
@@ -0,0 +1,140 @@
+
+
+
+VulnerabilitySuppressionAnalyzerTest xref
+
+
+
+
+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) 2012 Jeremy Long. All Rights Reserved.
+17 */
+18package org.owasp.dependencycheck.data.cpe;
+19
+20import junit.framework.TestCase;
+21import org.junit.After;
+22import org.junit.AfterClass;
+23import org.junit.Before;
+24import org.junit.BeforeClass;
+25import org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase;
+26
+27/**
+28 * An abstract database test case that is used to ensure the H2 DB exists prior to performing tests that utilize the
+29 * data contained within.
+30 *
+31 * @author Jeremy Long <jeremy.long@owasp.org>
+32 */
+33publicabstractclassAbstractDatabaseTestCaseextends TestCase {
+34
+35 @BeforeClass
+36publicstaticvoid setUpClass() throws Exception {
+37 }
+38
+39 @AfterClass
+40publicstaticvoid tearDownClass() throws Exception {
+41 }
+42
+43 @Before
+44 @Override
+45publicvoid setUp() throws Exception {
+46 BaseDBTestCase.ensureDBExists();
+47super.setUp();
+48 }
+49
+50 @After
+51 @Override
+52publicvoid tearDown() throws Exception {
+53super.tearDown();
+54 }
+55 }
+
+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) 2014 Jeremy Long. All Rights Reserved.
+17 */
+18package org.owasp.dependencycheck.agent;
+19
+20import java.io.File;
+21import java.io.IOException;
+22import java.util.List;
+23import java.util.logging.Level;
+24import java.util.logging.Logger;
+25import org.owasp.dependencycheck.Engine;
+26import org.owasp.dependencycheck.data.nvdcve.CveDB;
+27import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
+28import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
+29import org.owasp.dependencycheck.dependency.Dependency;
+30import org.owasp.dependencycheck.dependency.Identifier;
+31import org.owasp.dependencycheck.dependency.Vulnerability;
+32import org.owasp.dependencycheck.exception.ScanAgentException;
+33import org.owasp.dependencycheck.reporting.ReportGenerator;
+34import org.owasp.dependencycheck.utils.Settings;
+35
+36/**
+37 * This class provides a way to easily conduct a scan solely based on existing evidence metadata rather than collecting
+38 * evidence from the files themselves. This class is based on the Ant task and Maven plugin with the exception that it
+39 * takes a list of dependencies that can be programmatically added from data in a spreadsheet, database or some other
+40 * datasource and conduct a scan based on this pre-defined evidence.
+41 *
+42 * <h2>Example:</h2>
+43 * <pre>
+44 * List<Dependency> dependencies = new ArrayList<Dependency>();
+45 * Dependency dependency = new Dependency(new File(FileUtils.getBitBucket()));
+46 * dependency.getProductEvidence().addEvidence("my-datasource", "name", "Jetty", Confidence.HIGH);
+47 * dependency.getVersionEvidence().addEvidence("my-datasource", "version", "5.1.10", Confidence.HIGH);
+48 * dependency.getVendorEvidence().addEvidence("my-datasource", "vendor", "mortbay", Confidence.HIGH);
+49 * dependencies.add(dependency);
+50 *
+51 * DependencyCheckScanAgent scan = new DependencyCheckScanAgent();
+52 * scan.setDependencies(dependencies);
+53 * scan.setReportFormat(ReportGenerator.Format.ALL);
+54 * scan.setReportOutputDirectory(System.getProperty("user.home"));
+55 * scan.execute();
+56 * </pre>
+57 *
+58 * @author Steve Springett <steve.springett@owasp.org>
+59 */
+60 @SuppressWarnings("unused")
+61publicclassDependencyCheckScanAgent {
+62
+63/**
+64 * System specific new line character.
+65 */
+66privatestaticfinal String NEW_LINE = System.getProperty("line.separator", "\n").intern();
+67
+68/**
+69 * The application name for the report.
+70 */
+71private String applicationName = "Dependency-Check";
+72
+73/**
+74 * Get the value of applicationName.
+75 *
+76 * @return the value of applicationName
+77 */
+78public String getApplicationName() {
+79return applicationName;
+80 }
+81
+82/**
+83 * Set the value of applicationName.
+84 *
+85 * @param applicationName new value of applicationName
+86 */
+87publicvoid setApplicationName(String applicationName) {
+88this.applicationName = applicationName;
+89 }
+90
+91/**
+92 * The pre-determined dependencies to scan
+93 */
+94private List<Dependency> dependencies;
+95
+96/**
+97 * Returns a list of pre-determined dependencies.
+98 *
+99 * @return returns a list of dependencies
+100 */
+101public List<Dependency> getDependencies() {
+102return dependencies;
+103 }
+104
+105/**
+106 * Sets the list of dependencies to scan.
+107 *
+108 * @param dependencies new value of dependencies
+109 */
+110publicvoid setDependencies(List<Dependency> dependencies) {
+111this.dependencies = dependencies;
+112 }
+113
+114/**
+115 * The location of the data directory that contains
+116 */
+117private String dataDirectory = null;
+118
+119/**
+120 * Get the value of dataDirectory.
+121 *
+122 * @return the value of dataDirectory
+123 */
+124public String getDataDirectory() {
+125return dataDirectory;
+126 }
+127
+128/**
+129 * Set the value of dataDirectory.
+130 *
+131 * @param dataDirectory new value of dataDirectory
+132 */
+133publicvoid setDataDirectory(String dataDirectory) {
+134this.dataDirectory = dataDirectory;
+135 }
+136
+137/**
+138 * Specifies the destination directory for the generated Dependency-Check report.
+139 */
+140private String reportOutputDirectory;
+141
+142/**
+143 * Get the value of reportOutputDirectory.
+144 *
+145 * @return the value of reportOutputDirectory
+146 */
+147public String getReportOutputDirectory() {
+148return reportOutputDirectory;
+149 }
+150
+151/**
+152 * Set the value of reportOutputDirectory.
+153 *
+154 * @param reportOutputDirectory new value of reportOutputDirectory
+155 */
+156publicvoid setReportOutputDirectory(String reportOutputDirectory) {
+157this.reportOutputDirectory = reportOutputDirectory;
+158 }
+159
+160/**
+161 * Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11
+162 * which means since the CVSS scores are 0-10, by default the build will never fail and the CVSS score is set to 11.
+163 * The valid range for the fail build on CVSS is 0 to 11, where anything above 10 will not cause the build to fail.
+164 */
+165privatefloat failBuildOnCVSS = 11;
+166
+167/**
+168 * Get the value of failBuildOnCVSS.
+169 *
+170 * @return the value of failBuildOnCVSS
+171 */
+172publicfloat getFailBuildOnCVSS() {
+173return failBuildOnCVSS;
+174 }
+175
+176/**
+177 * Set the value of failBuildOnCVSS.
+178 *
+179 * @param failBuildOnCVSS new value of failBuildOnCVSS
+180 */
+181publicvoid setFailBuildOnCVSS(float failBuildOnCVSS) {
+182this.failBuildOnCVSS = failBuildOnCVSS;
+183 }
+184
+185/**
+186 * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to
+187 * false. Default is true.
+188 */
+189privateboolean autoUpdate = true;
+190
+191/**
+192 * Get the value of autoUpdate.
+193 *
+194 * @return the value of autoUpdate
+195 */
+196publicboolean isAutoUpdate() {
+197return autoUpdate;
+198 }
+199
+200/**
+201 * Set the value of autoUpdate.
+202 *
+203 * @param autoUpdate new value of autoUpdate
+204 */
+205publicvoid setAutoUpdate(boolean autoUpdate) {
+206this.autoUpdate = autoUpdate;
+207 }
+208
+209/**
+210 * The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this
+211 * within the Site plugin unless the externalReport is set to true. Default is HTML.
+212 */
+213private ReportGenerator.Format reportFormat = ReportGenerator.Format.HTML;
+214
+215/**
+216 * Get the value of reportFormat.
+217 *
+218 * @return the value of reportFormat
+219 */
+220public ReportGenerator.Format getReportFormat() {
+221return reportFormat;
+222 }
+223
+224/**
+225 * Set the value of reportFormat.
+226 *
+227 * @param reportFormat new value of reportFormat
+228 */
+229publicvoid setReportFormat(ReportGenerator.Format reportFormat) {
+230this.reportFormat = reportFormat;
+231 }
+232
+233/**
+234 * The Proxy URL.
+235 */
+236private String proxyUrl;
+237
+238/**
+239 * Get the value of proxyUrl.
+240 *
+241 * @return the value of proxyUrl
+242 */
+243public String getProxyUrl() {
+244return proxyUrl;
+245 }
+246
+247/**
+248 * Set the value of proxyUrl.
+249 *
+250 * @param proxyUrl new value of proxyUrl
+251 */
+252publicvoid setProxyUrl(String proxyUrl) {
+253this.proxyUrl = proxyUrl;
+254 }
+255
+256/**
+257 * The Proxy Port.
+258 */
+259private String proxyPort;
+260
+261/**
+262 * Get the value of proxyPort.
+263 *
+264 * @return the value of proxyPort
+265 */
+266public String getProxyPort() {
+267return proxyPort;
+268 }
+269
+270/**
+271 * Set the value of proxyPort.
+272 *
+273 * @param proxyPort new value of proxyPort
+274 */
+275publicvoid setProxyPort(String proxyPort) {
+276this.proxyPort = proxyPort;
+277 }
+278
+279/**
+280 * The Proxy username.
+281 */
+282private String proxyUsername;
+283
+284/**
+285 * Get the value of proxyUsername.
+286 *
+287 * @return the value of proxyUsername
+288 */
+289public String getProxyUsername() {
+290return proxyUsername;
+291 }
+292
+293/**
+294 * Set the value of proxyUsername.
+295 *
+296 * @param proxyUsername new value of proxyUsername
+297 */
+298publicvoid setProxyUsername(String proxyUsername) {
+299this.proxyUsername = proxyUsername;
+300 }
+301
+302/**
+303 * The Proxy password.
+304 */
+305private String proxyPassword;
+306
+307/**
+308 * Get the value of proxyPassword.
+309 *
+310 * @return the value of proxyPassword
+311 */
+312public String getProxyPassword() {
+313return proxyPassword;
+314 }
+315
+316/**
+317 * Set the value of proxyPassword.
+318 *
+319 * @param proxyPassword new value of proxyPassword
+320 */
+321publicvoid setProxyPassword(String proxyPassword) {
+322this.proxyPassword = proxyPassword;
+323 }
+324
+325/**
+326 * The Connection Timeout.
+327 */
+328private String connectionTimeout;
+329
+330/**
+331 * Get the value of connectionTimeout.
+332 *
+333 * @return the value of connectionTimeout
+334 */
+335public String getConnectionTimeout() {
+336return connectionTimeout;
+337 }
+338
+339/**
+340 * Set the value of connectionTimeout.
+341 *
+342 * @param connectionTimeout new value of connectionTimeout
+343 */
+344publicvoid setConnectionTimeout(String connectionTimeout) {
+345this.connectionTimeout = connectionTimeout;
+346 }
+347
+348/**
+349 * The file path used for verbose logging.
+350 */
+351private String logFile = null;
+352
+353/**
+354 * Get the value of logFile.
+355 *
+356 * @return the value of logFile
+357 */
+358public String getLogFile() {
+359return logFile;
+360 }
+361
+362/**
+363 * Set the value of logFile.
+364 *
+365 * @param logFile new value of logFile
+366 */
+367publicvoid setLogFile(String logFile) {
+368this.logFile = logFile;
+369 }
+370
+371/**
+372 * The path to the suppression file.
+373 */
+374private String suppressionFile;
+375
+376/**
+377 * Get the value of suppressionFile.
+378 *
+379 * @return the value of suppressionFile
+380 */
+381public String getSuppressionFile() {
+382return suppressionFile;
+383 }
+384
+385/**
+386 * Set the value of suppressionFile.
+387 *
+388 * @param suppressionFile new value of suppressionFile
+389 */
+390publicvoid setSuppressionFile(String suppressionFile) {
+391this.suppressionFile = suppressionFile;
+392 }
+393
+394/**
+395 * flag indicating whether or not to show a summary of findings.
+396 */
+397privateboolean showSummary = true;
+398
+399/**
+400 * Get the value of showSummary.
+401 *
+402 * @return the value of showSummary
+403 */
+404publicboolean isShowSummary() {
+405return showSummary;
+406 }
+407
+408/**
+409 * Set the value of showSummary.
+410 *
+411 * @param showSummary new value of showSummary
+412 */
+413publicvoid setShowSummary(boolean showSummary) {
+414this.showSummary = showSummary;
+415 }
+416
+417/**
+418 * Whether or not the nexus analyzer is enabled.
+419 */
+420privateboolean nexusAnalyzerEnabled = true;
+421
+422/**
+423 * Get the value of nexusAnalyzerEnabled.
+424 *
+425 * @return the value of nexusAnalyzerEnabled
+426 */
+427publicboolean isNexusAnalyzerEnabled() {
+428return nexusAnalyzerEnabled;
+429 }
+430
+431/**
+432 * Set the value of nexusAnalyzerEnabled.
+433 *
+434 * @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled
+435 */
+436publicvoid setNexusAnalyzerEnabled(boolean nexusAnalyzerEnabled) {
+437this.nexusAnalyzerEnabled = nexusAnalyzerEnabled;
+438 }
+439
+440/**
+441 * The URL of the Nexus server.
+442 */
+443private String nexusUrl;
+444
+445/**
+446 * Get the value of nexusUrl.
+447 *
+448 * @return the value of nexusUrl
+449 */
+450public String getNexusUrl() {
+451return nexusUrl;
+452 }
+453
+454/**
+455 * Set the value of nexusUrl.
+456 *
+457 * @param nexusUrl new value of nexusUrl
+458 */
+459publicvoid setNexusUrl(String nexusUrl) {
+460this.nexusUrl = nexusUrl;
+461 }
+462
+463/**
+464 * Whether or not the defined proxy should be used when connecting to Nexus.
+465 */
+466privateboolean nexusUsesProxy = true;
+467
+468/**
+469 * Get the value of nexusUsesProxy.
+470 *
+471 * @return the value of nexusUsesProxy
+472 */
+473publicboolean isNexusUsesProxy() {
+474return nexusUsesProxy;
+475 }
+476
+477/**
+478 * Set the value of nexusUsesProxy.
+479 *
+480 * @param nexusUsesProxy new value of nexusUsesProxy
+481 */
+482publicvoid setNexusUsesProxy(boolean nexusUsesProxy) {
+483this.nexusUsesProxy = nexusUsesProxy;
+484 }
+485
+486/**
+487 * The database driver name; such as org.h2.Driver.
+488 */
+489private String databaseDriverName;
+490
+491/**
+492 * Get the value of databaseDriverName.
+493 *
+494 * @return the value of databaseDriverName
+495 */
+496public String getDatabaseDriverName() {
+497return databaseDriverName;
+498 }
+499
+500/**
+501 * Set the value of databaseDriverName.
+502 *
+503 * @param databaseDriverName new value of databaseDriverName
+504 */
+505publicvoid setDatabaseDriverName(String databaseDriverName) {
+506this.databaseDriverName = databaseDriverName;
+507 }
+508
+509/**
+510 * The path to the database driver JAR file if it is not on the class path.
+511 */
+512private String databaseDriverPath;
+513
+514/**
+515 * Get the value of databaseDriverPath.
+516 *
+517 * @return the value of databaseDriverPath
+518 */
+519public String getDatabaseDriverPath() {
+520return databaseDriverPath;
+521 }
+522
+523/**
+524 * Set the value of databaseDriverPath.
+525 *
+526 * @param databaseDriverPath new value of databaseDriverPath
+527 */
+528publicvoid setDatabaseDriverPath(String databaseDriverPath) {
+529this.databaseDriverPath = databaseDriverPath;
+530 }
+531
+532/**
+533 * The database connection string.
+534 */
+535private String connectionString;
+536
+537/**
+538 * Get the value of connectionString.
+539 *
+540 * @return the value of connectionString
+541 */
+542public String getConnectionString() {
+543return connectionString;
+544 }
+545
+546/**
+547 * Set the value of connectionString.
+548 *
+549 * @param connectionString new value of connectionString
+550 */
+551publicvoid setConnectionString(String connectionString) {
+552this.connectionString = connectionString;
+553 }
+554
+555/**
+556 * The user name for connecting to the database.
+557 */
+558private String databaseUser;
+559
+560/**
+561 * Get the value of databaseUser.
+562 *
+563 * @return the value of databaseUser
+564 */
+565public String getDatabaseUser() {
+566return databaseUser;
+567 }
+568
+569/**
+570 * Set the value of databaseUser.
+571 *
+572 * @param databaseUser new value of databaseUser
+573 */
+574publicvoid setDatabaseUser(String databaseUser) {
+575this.databaseUser = databaseUser;
+576 }
+577
+578/**
+579 * The password to use when connecting to the database.
+580 */
+581private String databasePassword;
+582
+583/**
+584 * Get the value of databasePassword.
+585 *
+586 * @return the value of databasePassword
+587 */
+588public String getDatabasePassword() {
+589return databasePassword;
+590 }
+591
+592/**
+593 * Set the value of databasePassword.
+594 *
+595 * @param databasePassword new value of databasePassword
+596 */
+597publicvoid setDatabasePassword(String databasePassword) {
+598this.databasePassword = databasePassword;
+599 }
+600
+601/**
+602 * Additional ZIP File extensions to add analyze. This should be a comma-separated list of file extensions to treat
+603 * like ZIP files.
+604 */
+605private String zipExtensions;
+606
+607/**
+608 * Get the value of zipExtensions.
+609 *
+610 * @return the value of zipExtensions
+611 */
+612public String getZipExtensions() {
+613return zipExtensions;
+614 }
+615
+616/**
+617 * Set the value of zipExtensions.
+618 *
+619 * @param zipExtensions new value of zipExtensions
+620 */
+621publicvoid setZipExtensions(String zipExtensions) {
+622this.zipExtensions = zipExtensions;
+623 }
+624
+625/**
+626 * The url for the modified NVD CVE (1.2 schema).
+627 */
+628private String cveUrl12Modified;
+629
+630/**
+631 * Get the value of cveUrl12Modified.
+632 *
+633 * @return the value of cveUrl12Modified
+634 */
+635public String getCveUrl12Modified() {
+636return cveUrl12Modified;
+637 }
+638
+639/**
+640 * Set the value of cveUrl12Modified.
+641 *
+642 * @param cveUrl12Modified new value of cveUrl12Modified
+643 */
+644publicvoid setCveUrl12Modified(String cveUrl12Modified) {
+645this.cveUrl12Modified = cveUrl12Modified;
+646 }
+647
+648/**
+649 * The url for the modified NVD CVE (2.0 schema).
+650 */
+651private String cveUrl20Modified;
+652
+653/**
+654 * Get the value of cveUrl20Modified.
+655 *
+656 * @return the value of cveUrl20Modified
+657 */
+658public String getCveUrl20Modified() {
+659return cveUrl20Modified;
+660 }
+661
+662/**
+663 * Set the value of cveUrl20Modified.
+664 *
+665 * @param cveUrl20Modified new value of cveUrl20Modified
+666 */
+667publicvoid setCveUrl20Modified(String cveUrl20Modified) {
+668this.cveUrl20Modified = cveUrl20Modified;
+669 }
+670
+671/**
+672 * Base Data Mirror URL for CVE 1.2.
+673 */
+674private String cveUrl12Base;
+675
+676/**
+677 * Get the value of cveUrl12Base.
+678 *
+679 * @return the value of cveUrl12Base
+680 */
+681public String getCveUrl12Base() {
+682return cveUrl12Base;
+683 }
+684
+685/**
+686 * Set the value of cveUrl12Base.
+687 *
+688 * @param cveUrl12Base new value of cveUrl12Base
+689 */
+690publicvoid setCveUrl12Base(String cveUrl12Base) {
+691this.cveUrl12Base = cveUrl12Base;
+692 }
+693
+694/**
+695 * Data Mirror URL for CVE 2.0.
+696 */
+697private String cveUrl20Base;
+698
+699/**
+700 * Get the value of cveUrl20Base.
+701 *
+702 * @return the value of cveUrl20Base
+703 */
+704public String getCveUrl20Base() {
+705return cveUrl20Base;
+706 }
+707
+708/**
+709 * Set the value of cveUrl20Base.
+710 *
+711 * @param cveUrl20Base new value of cveUrl20Base
+712 */
+713publicvoid setCveUrl20Base(String cveUrl20Base) {
+714this.cveUrl20Base = cveUrl20Base;
+715 }
+716
+717/**
+718 * The path to Mono for .NET assembly analysis on non-windows systems.
+719 */
+720private String pathToMono;
+721
+722/**
+723 * Get the value of pathToMono.
+724 *
+725 * @return the value of pathToMono
+726 */
+727public String getPathToMono() {
+728return pathToMono;
+729 }
+730
+731/**
+732 * Set the value of pathToMono.
+733 *
+734 * @param pathToMono new value of pathToMono
+735 */
+736publicvoid setPathToMono(String pathToMono) {
+737this.pathToMono = pathToMono;
+738 }
+739
+740/**
+741 * Executes the Dependency-Check on the dependent libraries.
+742 *
+743 * @return the Engine used to scan the dependencies.
+744 * @throws org.owasp.dependencycheck.data.nvdcve.DatabaseException thrown if there is an exception connecting to the
+745 * database
+746 */
+747privateEngine executeDependencyCheck() throws DatabaseException {
+748 populateSettings();
+749Engine engine = null;
+750try {
+751 engine = newEngine();
+752 engine.setDependencies(this.dependencies);
+753 engine.analyzeDependencies();
+754
+755 } finally {
+756if (engine != null) {
+757 engine.cleanup();
+758 }
+759 }
+760return engine;
+761 }
+762
+763/**
+764 * Generates the reports for a given dependency-check engine.
+765 *
+766 * @param engine a dependency-check engine
+767 * @param outDirectory the directory to write the reports to
+768 */
+769privatevoid generateExternalReports(Engine engine, File outDirectory) {
+770DatabaseProperties prop = null;
+771CveDB cve = null;
+772try {
+773 cve = newCveDB();
+774 cve.open();
+775 prop = cve.getDatabaseProperties();
+776 } catch (DatabaseException ex) {
+777 Logger.getLogger(DependencyCheckScanAgent.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex);
+778 } finally {
+779if (cve != null) {
+780 cve.close();
+781 }
+782 }
+783finalReportGenerator r = newReportGenerator(this.applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
+784try {
+785 r.generateReports(outDirectory.getCanonicalPath(), this.reportFormat.name());
+786 } catch (IOException ex) {
+787 Logger.getLogger(DependencyCheckScanAgent.class.getName()).log(Level.SEVERE,
+788"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
+789 Logger.getLogger(DependencyCheckScanAgent.class.getName()).log(Level.FINE, null, ex);
+790 } catch (Throwable ex) {
+791 Logger.getLogger(DependencyCheckScanAgent.class.getName()).log(Level.SEVERE,
+792"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
+793 Logger.getLogger(DependencyCheckScanAgent.class.getName()).log(Level.FINE, null, ex);
+794 }
+795 }
+796
+797/**
+798 * Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system
+799 * properties required to change the proxy url, port, and connection timeout.
+800 */
+801privatevoid populateSettings() {
+802if (dataDirectory != null) {
+803 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
+804 } else {
+805final File jarPath = new File(DependencyCheckScanAgent.class.getProtectionDomain().getCodeSource().getLocation().getPath());
+806final File base = jarPath.getParentFile();
+807final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
+808final File dataDir = new File(base, sub);
+809 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
+810 }
+811
+812 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
+813
+814if (proxyUrl != null && !proxyUrl.isEmpty()) {
+815 Settings.setString(Settings.KEYS.PROXY_URL, proxyUrl);
+816 }
+817if (proxyPort != null && !proxyPort.isEmpty()) {
+818 Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
+819 }
+820if (proxyUsername != null && !proxyUsername.isEmpty()) {
+821 Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUsername);
+822 }
+823if (proxyPassword != null && !proxyPassword.isEmpty()) {
+824 Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
+825 }
+826if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
+827 Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
+828 }
+829if (suppressionFile != null && !suppressionFile.isEmpty()) {
+830 Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
+831 }
+832 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
+833if (nexusUrl != null && !nexusUrl.isEmpty()) {
+834 Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
+835 }
+836 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
+837if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
+838 Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
+839 }
+840if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
+841 Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
+842 }
+843if (connectionString != null && !connectionString.isEmpty()) {
+844 Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
+845 }
+846if (databaseUser != null && !databaseUser.isEmpty()) {
+847 Settings.setString(Settings.KEYS.DB_USER, databaseUser);
+848 }
+849if (databasePassword != null && !databasePassword.isEmpty()) {
+850 Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
+851 }
+852if (zipExtensions != null && !zipExtensions.isEmpty()) {
+853 Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
+854 }
+855if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) {
+856 Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
+857 }
+858if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) {
+859 Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
+860 }
+861if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) {
+862 Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
+863 }
+864if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) {
+865 Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
+866 }
+867if (pathToMono != null && !pathToMono.isEmpty()) {
+868 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
+869 }
+870 }
+871
+872/**
+873 * Executes the dependency-check and generates the report.
+874 *
+875 * @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if there is an exception executing the
+876 * scan.
+877 */
+878publicvoid execute() throws ScanAgentException {
+879Engine engine = null;
+880try {
+881 engine = executeDependencyCheck();
+882 generateExternalReports(engine, new File(this.reportOutputDirectory));
+883if (this.showSummary) {
+884 showSummary(engine.getDependencies());
+885 }
+886if (this.failBuildOnCVSS <= 10) {
+887 checkForFailure(engine.getDependencies());
+888 }
+889 } catch (DatabaseException ex) {
+890 Logger.getLogger(DependencyCheckScanAgent.class.getName()).log(Level.SEVERE,
+891"Unable to connect to the dependency-check database; analysis has stopped");
+892 Logger.getLogger(DependencyCheckScanAgent.class.getName()).log(Level.FINE, "", ex);
+893 } finally {
+894if (engine != null) {
+895 engine.cleanup();
+896 }
+897 }
+898 }
+899
+900/**
+901 * Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the
+902 * configuration.
+903 *
+904 * @param dependencies the list of dependency objects
+905 * @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if there is an exception executing the
+906 * scan.
+907 */
+908privatevoid checkForFailure(List<Dependency> dependencies) throws ScanAgentException {
+909final StringBuilder ids = new StringBuilder();
+910for (Dependency d : dependencies) {
+911boolean addName = true;
+912for (Vulnerability v : d.getVulnerabilities()) {
+913if (v.getCvssScore() >= failBuildOnCVSS) {
+914if (addName) {
+915 addName = false;
+916 ids.append(NEW_LINE).append(d.getFileName()).append(": ");
+917 ids.append(v.getName());
+918 } else {
+919 ids.append(", ").append(v.getName());
+920 }
+921 }
+922 }
+923 }
+924if (ids.length() > 0) {
+925final String msg = String.format("%n%nDependency-Check Failure:%n"
+926 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
+927 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
+928
+929thrownewScanAgentException(msg);
+930 }
+931 }
+932
+933/**
+934 * Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
+935 *
+936 * @param dependencies a list of dependency objects
+937 */
+938privatevoid showSummary(List<Dependency> dependencies) {
+939final StringBuilder summary = new StringBuilder();
+940for (Dependency d : dependencies) {
+941boolean firstEntry = true;
+942final StringBuilder ids = new StringBuilder();
+943for (Vulnerability v : d.getVulnerabilities()) {
+944if (firstEntry) {
+945 firstEntry = false;
+946 } else {
+947 ids.append(", ");
+948 }
+949 ids.append(v.getName());
+950 }
+951if (ids.length() > 0) {
+952 summary.append(d.getFileName()).append(" (");
+953 firstEntry = true;
+954for (Identifier id : d.getIdentifiers()) {
+955if (firstEntry) {
+956 firstEntry = false;
+957 } else {
+958 summary.append(", ");
+959 }
+960 summary.append(id.getValue());
+961 }
+962 summary.append(") : ").append(ids).append(NEW_LINE);
+963 }
+964 }
+965if (summary.length() > 0) {
+966final String msg = String.format("%n%n"
+967 + "One or more dependencies were identified with known vulnerabilities:%n%n%s"
+968 + "%n%nSee the dependency-check report for more details.%n%n", summary.toString());
+969 Logger.getLogger(DependencyCheckScanAgent.class.getName()).log(Level.WARNING, msg);
+970 }
+971 }
+972
+973 }
+
+
+
+
+
\ No newline at end of file
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html
index fe33563bb..4316faf28 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html
@@ -25,53 +25,32 @@
17 */18package org.owasp.dependencycheck.analyzer;
19
-20import java.util.Collections;
-21import java.util.HashSet;
-22import java.util.Set;
-23
-24/**
-25 *
-26 * @author Jeremy Long <jeremy.long@owasp.org>
-27 */
-28publicabstractclassAbstractAnalyzerimplementsAnalyzer {
-29
-30/**
-31 * Utility method to help in the creation of the extensions set. This constructs a new Set that can be used in a
-32 * final static declaration.<br/><br/>
-33 *
-34 * This implementation was copied from
-35 * http://stackoverflow.com/questions/2041778/initialize-java-hashset-values-by-construction
-36 *
-37 * @param strings a list of strings to add to the set.
-38 * @return a Set of strings.
-39 */
-40protectedstatic Set<String> newHashSet(String... strings) {
-41final Set<String> set = new HashSet<String>();
-42
-43 Collections.addAll(set, strings);
-44return set;
-45 }
-46
-47/**
-48 * The initialize method does nothing for this Analyzer.
-49 *
-50 * @throws Exception thrown if there is an exception
-51 */
-52 @Override
-53publicvoid initialize() throws Exception {
-54//do nothing
-55 }
-56
-57/**
-58 * The close method does nothing for this Analyzer.
-59 *
-60 * @throws Exception thrown if there is an exception
-61 */
-62 @Override
-63publicvoid close() throws Exception {
-64//do nothing
-65 }
-66 }
+20/**
+21 *
+22 * @author Jeremy Long <jeremy.long@owasp.org>
+23 */
+24publicabstractclassAbstractAnalyzerimplementsAnalyzer {
+25
+26/**
+27 * The initialize method does nothing for this Analyzer.
+28 *
+29 * @throws Exception thrown if there is an exception
+30 */
+31 @Override
+32publicvoid initialize() throws Exception {
+33//do nothing
+34 }
+35
+36/**
+37 * The close method does nothing for this Analyzer.
+38 *
+39 * @throws Exception thrown if there is an exception
+40 */
+41 @Override
+42publicvoid close() throws Exception {
+43//do nothing
+44 }
+45 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html
new file mode 100644
index 000000000..73e73a994
--- /dev/null
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html
@@ -0,0 +1,242 @@
+
+
+
+AbstractFileTypeAnalyzer xref
+
+
+
+
+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) 2014 Jeremy Long. All Rights Reserved.
+17 */
+18package org.owasp.dependencycheck.analyzer;
+19
+20import java.util.Collections;
+21import java.util.HashSet;
+22import java.util.Set;
+23import java.util.logging.Level;
+24import java.util.logging.Logger;
+25import org.owasp.dependencycheck.Engine;
+26import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+27import org.owasp.dependencycheck.dependency.Dependency;
+28import org.owasp.dependencycheck.utils.InvalidSettingException;
+29import org.owasp.dependencycheck.utils.Settings;
+30
+31/**
+32 * The base FileTypeAnalyzer that all analyzers that have specific file types they analyze should extend.
+33 *
+34 * @author Jeremy Long <jeremy.long@owasp.org>
+35 */
+36publicabstractclassAbstractFileTypeAnalyzerextendsAbstractAnalyzerimplementsFileTypeAnalyzer {
+37
+38//<editor-fold defaultstate="collapsed" desc="Constructor">
+39/**
+40 * Base constructor that all children must call. This checks the configuration to determine if the analyzer is
+41 * enabled.
+42 */
+43publicAbstractFileTypeAnalyzer() {
+44final String key = getAnalyzerEnabledSettingKey();
+45try {
+46 enabled = Settings.getBoolean(key, true);
+47 } catch (InvalidSettingException ex) {
+48 String msg = String.format("Invalid settting for property '%s'", key);
+49 LOGGER.log(Level.WARNING, msg);
+50 LOGGER.log(Level.FINE, "", ex);
+51 msg = String.format("%s has been disabled", getName());
+52 LOGGER.log(Level.WARNING, msg);
+53 }
+54 }
+55//</editor-fold>
+56
+57//<editor-fold defaultstate="collapsed" desc="Field defentitions">
+58/**
+59 * The logger.
+60 */
+61privatestaticfinal Logger LOGGER = Logger.getLogger(AbstractFileTypeAnalyzer.class.getName());
+62/**
+63 * Whether the file type analyzer detected any files it needs to analyze.
+64 */
+65privateboolean filesMatched = false;
+66
+67/**
+68 * Get the value of filesMatched. A flag indicating whether the scan included any file types this analyzer supports.
+69 *
+70 * @return the value of filesMatched
+71 */
+72protectedboolean isFilesMatched() {
+73return filesMatched;
+74 }
+75
+76/**
+77 * Set the value of filesMatched. A flag indicating whether the scan included any file types this analyzer supports.
+78 *
+79 * @param filesMatched new value of filesMatched
+80 */
+81protectedvoid setFilesMatched(boolean filesMatched) {
+82this.filesMatched = filesMatched;
+83 }
+84
+85/**
+86 * A flag indicating whether or not the analyzer is enabled.
+87 */
+88privateboolean enabled = true;
+89
+90/**
+91 * Get the value of enabled.
+92 *
+93 * @return the value of enabled
+94 */
+95publicboolean isEnabled() {
+96return enabled;
+97 }
+98
+99/**
+100 * Set the value of enabled.
+101 *
+102 * @param enabled new value of enabled
+103 */
+104publicvoid setEnabled(boolean enabled) {
+105this.enabled = enabled;
+106 }
+107//</editor-fold>
+108
+109//<editor-fold defaultstate="collapsed" desc="Abstract methods children must implement">
+110/**
+111 * <p>
+112 * Returns a list of supported file extensions. An example would be an analyzer that inspected java jar files. The
+113 * getSupportedExtensions function would return a set with a single element "jar".</p>
+114 *
+115 * <p>
+116 * <b>Note:</b> when implementing this the extensions returned MUST be lowercase.</p>
+117 *
+118 * @return The file extensions supported by this analyzer.
+119 *
+120 * <p>
+121 * If the analyzer returns null it will not cause additional files to be analyzed but will be executed against every
+122 * file loaded</p>
+123 */
+124protectedabstract Set<String> getSupportedExtensions();
+125
+126/**
+127 * Initializes the file type analyzer.
+128 *
+129 * @throws Exception thrown if there is an exception during initialization
+130 */
+131protectedabstractvoid initializeFileTypeAnalyzer() throws Exception;
+132
+133/**
+134 * Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted,
+135 * scanned, and added to the list of dependencies within the engine.
+136 *
+137 * @param dependency the dependency to analyze
+138 * @param engine the engine scanning
+139 * @throws AnalysisException thrown if there is an analysis exception
+140 */
+141protectedabstractvoid analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException;
+142
+143/**
+144 * <p>
+145 * Returns the setting key to determine if the analyzer is enabled.</p>
+146 *
+147 * @return the key for the analyzer's enabled property
+148 */
+149protectedabstract String getAnalyzerEnabledSettingKey();
+150
+151//</editor-fold>
+152//<editor-fold defaultstate="collapsed" desc="Final implementations for the Analyzer interface">
+153/**
+154 * Initializes the analyzer.
+155 *
+156 * @throws Exception thrown if there is an exception during initialization
+157 */
+158 @Override
+159publicfinalvoid initialize() throws Exception {
+160if (filesMatched) {
+161 initializeFileTypeAnalyzer();
+162 } else {
+163 enabled = false;
+164 }
+165 }
+166
+167/**
+168 * Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted,
+169 * scanned, and added to the list of dependencies within the engine.
+170 *
+171 * @param dependency the dependency to analyze
+172 * @param engine the engine scanning
+173 * @throws AnalysisException thrown if there is an analysis exception
+174 */
+175 @Override
+176publicfinalvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
+177if (enabled) {
+178 analyzeFileType(dependency, engine);
+179 }
+180 }
+181
+182/**
+183 * Returns whether or not this analyzer can process the given extension.
+184 *
+185 * @param extension the file extension to test for support.
+186 * @return whether or not the specified file extension is supported by this analyzer.
+187 */
+188 @Override
+189publicfinalboolean supportsExtension(String extension) {
+190if (!enabled) {
+191return false;
+192 }
+193final Set<String> ext = getSupportedExtensions();
+194if (ext == null) {
+195final String msg = String.format("The '%s' analyzer is misconfigured and does not have any file extensions;"
+196 + " it will be disabled", getName());
+197 Logger.getLogger(AbstractFileTypeAnalyzer.class.getName()).log(Level.SEVERE, msg);
+198return false;
+199 } else {
+200finalboolean match = ext.contains(extension);
+201if (match) {
+202 filesMatched = match;
+203 }
+204return match;
+205 }
+206 }
+207//</editor-fold>
+208
+209//<editor-fold defaultstate="collapsed" desc="Static utility methods">
+210/**
+211 * <p>
+212 * Utility method to help in the creation of the extensions set. This constructs a new Set that can be used in a
+213 * final static declaration.</p>
+214 *
+215 * <p>
+216 * This implementation was copied from
+217 * http://stackoverflow.com/questions/2041778/initialize-java-hashset-values-by-construction</p>
+218 *
+219 * @param strings a list of strings to add to the set.
+220 * @return a Set of strings.
+221 */
+222protectedstatic Set<String> newHashSet(String... strings) {
+223final Set<String> set = new HashSet<String>();
+224
+225 Collections.addAll(set, strings);
+226return set;
+227 }
+228//</editor-fold>
+229 }
+
+
+
+
+
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html
index 3740c0487..c8ecbbce0 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html
@@ -59,110 +59,102 @@
51returnnull;
52 }
53
-54/**
-55 * Returns whether or not this analyzer can process the given extension.
-56 *
-57 * @param extension the file extension to test for support.
-58 * @return whether or not the specified file extension is supported by this analyzer.
+54//</editor-fold>
+55/**
+56 * The initialize method loads the suppression XML file.
+57 *
+58 * @throws Exception thrown if there is an exception59 */60 @Override
-61publicboolean supportsExtension(String extension) {
-62returntrue;
-63 }
-64
-65//</editor-fold>
-66/**
-67 * The initialize method loads the suppression XML file.
-68 *
-69 * @throws Exception thrown if there is an exception
-70 */
-71 @Override
-72publicvoid initialize() throws Exception {
-73super.initialize();
-74 loadSuppressionData();
-75 }
-76/**
-77 * The list of suppression rules
-78 */
-79private List<SuppressionRule> rules;
-80
-81/**
-82 * Get the value of rules.
-83 *
-84 * @return the value of rules
-85 */
-86public List<SuppressionRule> getRules() {
-87return rules;
-88 }
-89
-90/**
-91 * Set the value of rules.
-92 *
-93 * @param rules new value of rules
-94 */
-95publicvoid setRules(List<SuppressionRule> rules) {
-96this.rules = rules;
-97 }
-98
-99/**
-100 * Loads the suppression rules file.
-101 *
-102 * @throws SuppressionParseException thrown if the XML cannot be parsed.
-103 */
-104privatevoid loadSuppressionData() throws SuppressionParseException {
-105final String suppressionFilePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
-106if (suppressionFilePath == null) {
-107return;
-108 }
-109 File file = null;
-110boolean deleteTempFile = false;
-111try {
-112final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
-113if (uriRx.matcher(suppressionFilePath).matches()) {
-114 deleteTempFile = true;
-115 file = FileUtils.getTempFile("suppression", "xml");
-116final URL url = new URL(suppressionFilePath);
+61publicvoid initialize() throws Exception {
+62super.initialize();
+63 loadSuppressionData();
+64 }
+65/**
+66 * The list of suppression rules
+67 */
+68private List<SuppressionRule> rules;
+69
+70/**
+71 * Get the value of rules.
+72 *
+73 * @return the value of rules
+74 */
+75public List<SuppressionRule> getRules() {
+76return rules;
+77 }
+78
+79/**
+80 * Set the value of rules.
+81 *
+82 * @param rules new value of rules
+83 */
+84publicvoid setRules(List<SuppressionRule> rules) {
+85this.rules = rules;
+86 }
+87
+88/**
+89 * Loads the suppression rules file.
+90 *
+91 * @throws SuppressionParseException thrown if the XML cannot be parsed.
+92 */
+93privatevoid loadSuppressionData() throws SuppressionParseException {
+94final String suppressionFilePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
+95if (suppressionFilePath == null) {
+96return;
+97 }
+98 File file = null;
+99boolean deleteTempFile = false;
+100try {
+101final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
+102if (uriRx.matcher(suppressionFilePath).matches()) {
+103 deleteTempFile = true;
+104 file = FileUtils.getTempFile("suppression", "xml");
+105final URL url = new URL(suppressionFilePath);
+106try {
+107 Downloader.fetchFile(url, file, false);
+108 } catch (DownloadFailedException ex) {
+109 Downloader.fetchFile(url, file, true);
+110 }
+111 } else {
+112 file = new File(suppressionFilePath);
+113 }
+114
+115if (file != null) {
+116finalSuppressionParser parser = newSuppressionParser();
117try {
-118 Downloader.fetchFile(url, file, false);
-119 } catch (DownloadFailedException ex) {
-120 Downloader.fetchFile(url, file, true);
-121 }
-122 }
-123
-124if (file != null) {
-125finalSuppressionParser parser = newSuppressionParser();
-126try {
-127 rules = parser.parseSuppressionRules(file);
-128 } catch (SuppressionParseException ex) {
-129final String msg = String.format("Unable to parse suppression xml file '%s'", file.getPath());
-130 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING, msg);
-131 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING, ex.getMessage());
-132 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, null, ex);
-133throw ex;
-134 }
-135 }
-136 } catch (DownloadFailedException ex) {
-137 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING,
-138"Unable to fetch the configured suppression file");
-139 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, "", ex);
-140thrownewSuppressionParseException("Unable to fetch the configured suppression file", ex);
-141 } catch (MalformedURLException ex) {
-142 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING,
-143"Configured suppression file has an invalid URL");
-144 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, "", ex);
-145thrownewSuppressionParseException("Configured suppression file has an invalid URL", ex);
-146 } catch (IOException ex) {
-147 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING,
-148"Unable to create temp file for suppressions");
-149 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, "", ex);
-150thrownewSuppressionParseException("Unable to create temp file for suppressions", ex);
-151 } finally {
-152if (deleteTempFile && file != null) {
-153 FileUtils.delete(file);
-154 }
-155 }
-156 }
-157 }
+118 rules = parser.parseSuppressionRules(file);
+119 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, rules.size() + " suppression rules were loaded.");
+120 } catch (SuppressionParseException ex) {
+121final String msg = String.format("Unable to parse suppression xml file '%s'", file.getPath());
+122 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING, msg);
+123 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING, ex.getMessage());
+124 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, "", ex);
+125throw ex;
+126 }
+127 }
+128 } catch (DownloadFailedException ex) {
+129 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING,
+130"Unable to fetch the configured suppression file");
+131 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, "", ex);
+132thrownewSuppressionParseException("Unable to fetch the configured suppression file", ex);
+133 } catch (MalformedURLException ex) {
+134 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING,
+135"Configured suppression file has an invalid URL");
+136 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, "", ex);
+137thrownewSuppressionParseException("Configured suppression file has an invalid URL", ex);
+138 } catch (IOException ex) {
+139 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING,
+140"Unable to create temp file for suppressions");
+141 Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, "", ex);
+142thrownewSuppressionParseException("Unable to create temp file for suppressions", ex);
+143 } finally {
+144if (deleteTempFile && file != null) {
+145 FileUtils.delete(file);
+146 }
+147 }
+148 }
+149 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/Analyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/Analyzer.html
index 4f9927220..3a71f87bc 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/Analyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/Analyzer.html
@@ -25,83 +25,58 @@
17 */18package org.owasp.dependencycheck.analyzer;
19
-20import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
-21import java.util.Set;
-22import org.owasp.dependencycheck.Engine;
-23import org.owasp.dependencycheck.dependency.Dependency;
-24
-25/**
-26 * An interface that defines an Analyzer that is used to identify Dependencies. An analyzer will collect information
-27 * about the dependency in the form of Evidence.
-28 *
-29 * @author Jeremy Long <jeremy.long@owasp.org>
-30 */
-31publicinterfaceAnalyzer {
-32
-33/**
-34 * Analyzes the given dependency. The analysis could be anything from identifying an Identifier for the dependency,
-35 * to finding vulnerabilities, etc. Additionally, if the analyzer collects enough information to add a description
-36 * or license information for the dependency it should be added.
-37 *
-38 * @param dependency a dependency to analyze.
-39 * @param engine the engine that is scanning the dependencies - this is useful if we need to check other
-40 * dependencies
-41 * @throws AnalysisException is thrown if there is an error analyzing the dependency file
-42 */
-43void analyze(Dependency dependency, Engine engine) throws AnalysisException;
-44
-45/**
-46 * <p>
-47 * Returns a list of supported file extensions. An example would be an analyzer that inspected java jar files. The
-48 * getSupportedExtensions function would return a set with a single element "jar".</p>
-49 *
-50 * <p>
-51 * <b>Note:</b> when implementing this the extensions returned MUST be lowercase.</p>
-52 *
-53 * @return The file extensions supported by this analyzer.
-54 *
-55 * <p>
-56 * If the analyzer returns null it will not cause additional files to be analyzed but will be executed against every
-57 * file loaded</p>
-58 */
-59 Set<String> getSupportedExtensions();
-60
-61/**
-62 * Returns the name of the analyzer.
-63 *
-64 * @return the name of the analyzer.
-65 */
-66 String getName();
-67
-68/**
-69 * Returns whether or not this analyzer can process the given extension.
-70 *
-71 * @param extension the file extension to test for support.
-72 * @return whether or not the specified file extension is supported by this analyzer.
-73 */
-74boolean supportsExtension(String extension);
-75
-76/**
-77 * Returns the phase that the analyzer is intended to run in.
-78 *
-79 * @return the phase that the analyzer is intended to run in.
-80 */
-81AnalysisPhase getAnalysisPhase();
-82
-83/**
-84 * The initialize method is called (once) prior to the analyze method being called on all of the dependencies.
-85 *
-86 * @throws Exception is thrown if an exception occurs initializing the analyzer.
-87 */
-88void initialize() throws Exception;
-89
-90/**
-91 * The close method is called after all of the dependencies have been analyzed.
-92 *
-93 * @throws Exception is thrown if an exception occurs closing the analyzer.
-94 */
-95void close() throws Exception;
-96 }
+20import org.owasp.dependencycheck.Engine;
+21import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+22import org.owasp.dependencycheck.dependency.Dependency;
+23
+24/**
+25 * An interface that defines an Analyzer that is used to identify Dependencies. An analyzer will collect information
+26 * about the dependency in the form of Evidence.
+27 *
+28 * @author Jeremy Long <jeremy.long@owasp.org>
+29 */
+30publicinterfaceAnalyzer {
+31
+32/**
+33 * Analyzes the given dependency. The analysis could be anything from identifying an Identifier for the dependency,
+34 * to finding vulnerabilities, etc. Additionally, if the analyzer collects enough information to add a description
+35 * or license information for the dependency it should be added.
+36 *
+37 * @param dependency a dependency to analyze.
+38 * @param engine the engine that is scanning the dependencies - this is useful if we need to check other
+39 * dependencies
+40 * @throws AnalysisException is thrown if there is an error analyzing the dependency file
+41 */
+42void analyze(Dependency dependency, Engine engine) throws AnalysisException;
+43
+44/**
+45 * Returns the name of the analyzer.
+46 *
+47 * @return the name of the analyzer.
+48 */
+49 String getName();
+50
+51/**
+52 * Returns the phase that the analyzer is intended to run in.
+53 *
+54 * @return the phase that the analyzer is intended to run in.
+55 */
+56AnalysisPhase getAnalysisPhase();
+57
+58/**
+59 * The initialize method is called (once) prior to the analyze method being called on all of the dependencies.
+60 *
+61 * @throws Exception is thrown if an exception occurs initializing the analyzer.
+62 */
+63void initialize() throws Exception;
+64
+65/**
+66 * The close method is called after all of the dependencies have been analyzed.
+67 *
+68 * @throws Exception is thrown if an exception occurs closing the analyzer.
+69 */
+70void close() throws Exception;
+71 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html
index 408d54d34..7c873eb15 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html
@@ -61,367 +61,374 @@
53 *54 * @author Jeremy Long <jeremy.long@owasp.org>55 */
-56publicclassArchiveAnalyzerextendsAbstractAnalyzerimplementsAnalyzer {
+56publicclassArchiveAnalyzerextendsAbstractFileTypeAnalyzer {
5758/**
-59 * The buffer size to use when extracting files from the archive.
+59 * The logger.60 */
-61privatestaticfinalint BUFFER_SIZE = 4096;
+61privatestaticfinal Logger LOGGER = Logger.getLogger(ArchiveAnalyzer.class.getName());
62/**
-63 * The count of directories created during analysis. This is used for creating temporary directories.
+63 * The buffer size to use when extracting files from the archive.64 */
-65privatestaticint dirCount = 0;
+65privatestaticfinalint BUFFER_SIZE = 4096;
66/**
-67 * The parent directory for the individual directories per archive.
+67 * The count of directories created during analysis. This is used for creating temporary directories.68 */
-69private File tempFileLocation = null;
+69privatestaticint dirCount = 0;
70/**
-71 * The max scan depth that the analyzer will recursively extract nested archives.
+71 * The parent directory for the individual directories per archive.72 */
-73privatestaticfinalint MAX_SCAN_DEPTH = Settings.getInt("archive.scan.depth", 3);
+73private File tempFileLocation = null;
74/**
-75 * Tracks the current scan/extraction depth for nested archives.
+75 * The max scan depth that the analyzer will recursively extract nested archives.76 */
-77privateint scanDepth = 0;
-78//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
-79/**
-80 * The name of the analyzer.
-81 */
-82privatestaticfinal String ANALYZER_NAME = "Archive Analyzer";
-83/**
-84 * The phase that this analyzer is intended to run in.
-85 */
-86privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL;
-87/**
-88 * The set of things we can handle with Zip methods
-89 */
-90privatestaticfinal Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "nupkg");
-91/**
-92 * The set of file extensions supported by this analyzer. Note for developers, any additions to this list will need
-93 * to be explicitly handled in extractFiles().
+77privatestaticfinalint MAX_SCAN_DEPTH = Settings.getInt("archive.scan.depth", 3);
+78/**
+79 * Tracks the current scan/extraction depth for nested archives.
+80 */
+81privateint scanDepth = 0;
+82
+83//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
+84/**
+85 * The name of the analyzer.
+86 */
+87privatestaticfinal String ANALYZER_NAME = "Archive Analyzer";
+88/**
+89 * The phase that this analyzer is intended to run in.
+90 */
+91privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL;
+92/**
+93 * The set of things we can handle with Zip methods94 */
-95privatestaticfinal Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz");
-96
-97static {
-98final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
-99if (additionalZipExt != null) {
-100final HashSet ext = new HashSet<String>(Arrays.asList(additionalZipExt));
-101 ZIPPABLES.addAll(ext);
-102 }
-103 EXTENSIONS.addAll(ZIPPABLES);
-104 }
-105
-106/**
-107 * Returns a list of file EXTENSIONS supported by this analyzer.
-108 *
-109 * @return a list of file EXTENSIONS supported by this analyzer.
-110 */
-111public Set<String> getSupportedExtensions() {
-112return EXTENSIONS;
-113 }
-114
-115/**
-116 * Returns the name of the analyzer.
-117 *
-118 * @return the name of the analyzer.
-119 */
-120public String getName() {
-121return ANALYZER_NAME;
-122 }
-123
-124/**
-125 * Returns whether or not this analyzer can process the given extension.
-126 *
-127 * @param extension the file extension to test for support.
-128 * @return whether or not the specified file extension is supported by this analyzer.
-129 */
-130publicboolean supportsExtension(String extension) {
-131return EXTENSIONS.contains(extension);
-132 }
-133
-134/**
-135 * Returns the phase that the analyzer is intended to run in.
-136 *
-137 * @return the phase that the analyzer is intended to run in.
-138 */
-139publicAnalysisPhase getAnalysisPhase() {
-140return ANALYSIS_PHASE;
-141 }
-142//</editor-fold>
-143
-144/**
-145 * The initialize method does nothing for this Analyzer.
-146 *
-147 * @throws Exception is thrown if there is an exception deleting or creating temporary files
-148 */
-149 @Override
-150publicvoid initialize() throws Exception {
-151final File baseDir = Settings.getTempDirectory();
-152if (!baseDir.exists()) {
-153if (!baseDir.mkdirs()) {
-154final String msg = String.format("Unable to make a temporary folder '%s'", baseDir.getPath());
-155thrownewAnalysisException(msg);
-156 }
-157 }
-158 tempFileLocation = File.createTempFile("check", "tmp", baseDir);
-159if (!tempFileLocation.delete()) {
-160final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
-161thrownewAnalysisException(msg);
-162 }
-163if (!tempFileLocation.mkdirs()) {
-164final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
-165thrownewAnalysisException(msg);
-166 }
-167 }
-168
-169/**
-170 * The close method deletes any temporary files and directories created during analysis.
-171 *
-172 * @throws Exception thrown if there is an exception deleting temporary files
-173 */
-174 @Override
-175publicvoid close() throws Exception {
-176if (tempFileLocation != null && tempFileLocation.exists()) {
-177 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, "Attempting to delete temporary files");
-178finalboolean success = FileUtils.delete(tempFileLocation);
-179if (!success) {
-180 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.WARNING,
-181"Failed to delete some temporary files, see the log for more details");
-182 }
-183 }
-184 }
-185
-186/**
-187 * Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted,
-188 * scanned, and added to the list of dependencies within the engine.
-189 *
-190 * @param dependency the dependency to analyze
-191 * @param engine the engine scanning
-192 * @throws AnalysisException thrown if there is an analysis exception
-193 */
-194 @Override
-195publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-196final File f = new File(dependency.getActualFilePath());
-197final File tmpDir = getNextTempDirectory();
-198 extractFiles(f, tmpDir, engine);
-199
-200//make a copy
-201final List<Dependency> dependencies = new ArrayList<Dependency>(engine.getDependencies());
-202 engine.scan(tmpDir);
-203final List<Dependency> newDependencies = engine.getDependencies();
-204if (dependencies.size() != newDependencies.size()) {
-205//get the new dependencies
-206final Set<Dependency> dependencySet = new HashSet<Dependency>();
-207 dependencySet.addAll(newDependencies);
-208 dependencySet.removeAll(dependencies);
-209
-210for (Dependency d : dependencySet) {
-211//fix the dependency's display name and path
-212final String displayPath = String.format("%s%s",
-213 dependency.getFilePath(),
-214 d.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
-215final String displayName = String.format("%s%s%s",
-216 dependency.getFileName(),
-217 File.separator,
-218 d.getFileName());
-219 d.setFilePath(displayPath);
-220 d.setFileName(displayName);
-221
-222//TODO - can we get more evidence from the parent? EAR contains module name, etc.
-223//analyze the dependency (i.e. extract files) if it is a supported type.
-224if (this.supportsExtension(d.getFileExtension()) && scanDepth < MAX_SCAN_DEPTH) {
-225 scanDepth += 1;
-226 analyze(d, engine);
-227 scanDepth -= 1;
-228 }
-229 }
-230 }
-231 Collections.sort(engine.getDependencies());
-232 }
-233
-234/**
-235 * Retrieves the next temporary directory to extract an archive too.
-236 *
-237 * @return a directory
-238 * @throws AnalysisException thrown if unable to create temporary directory
-239 */
-240private File getNextTempDirectory() throws AnalysisException {
-241 dirCount += 1;
-242final File directory = new File(tempFileLocation, String.valueOf(dirCount));
-243//getting an exception for some directories not being able to be created; might be because the directory already exists?
-244if (directory.exists()) {
-245return getNextTempDirectory();
-246 }
-247if (!directory.mkdirs()) {
-248final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath());
-249thrownewAnalysisException(msg);
-250 }
-251return directory;
-252 }
-253
-254/**
-255 * Extracts the contents of an archive into the specified directory.
-256 *
-257 * @param archive an archive file such as a WAR or EAR
-258 * @param destination a directory to extract the contents to
-259 * @param engine the scanning engine
-260 * @throws AnalysisException thrown if the archive is not found
-261 */
-262privatevoid extractFiles(File archive, File destination, Engine engine) throws AnalysisException {
-263if (archive == null || destination == null) {
-264return;
-265 }
-266
-267 FileInputStream fis = null;
-268try {
-269 fis = new FileInputStream(archive);
-270 } catch (FileNotFoundException ex) {
-271 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex);
-272thrownewAnalysisException("Archive file was not found.", ex);
-273 }
-274final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase();
+95privatestaticfinal Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "nupkg");
+96/**
+97 * The set of file extensions supported by this analyzer. Note for developers, any additions to this list will need
+98 * to be explicitly handled in extractFiles().
+99 */
+100privatestaticfinal Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz");
+101
+102static {
+103final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
+104if (additionalZipExt != null) {
+105final HashSet ext = new HashSet<String>(Arrays.asList(additionalZipExt));
+106 ZIPPABLES.addAll(ext);
+107 }
+108 EXTENSIONS.addAll(ZIPPABLES);
+109 }
+110
+111/**
+112 * Returns a list of file EXTENSIONS supported by this analyzer.
+113 *
+114 * @return a list of file EXTENSIONS supported by this analyzer.
+115 */
+116 @Override
+117public Set<String> getSupportedExtensions() {
+118return EXTENSIONS;
+119 }
+120
+121/**
+122 * Returns the name of the analyzer.
+123 *
+124 * @return the name of the analyzer.
+125 */
+126 @Override
+127public String getName() {
+128return ANALYZER_NAME;
+129 }
+130
+131/**
+132 * Returns the phase that the analyzer is intended to run in.
+133 *
+134 * @return the phase that the analyzer is intended to run in.
+135 */
+136 @Override
+137publicAnalysisPhase getAnalysisPhase() {
+138return ANALYSIS_PHASE;
+139 }
+140//</editor-fold>
+141
+142/**
+143 * Returns the key used in the properties file to reference the analyzer's enabled property.
+144 *
+145 * @return the analyzer's enabled property setting key
+146 */
+147 @Override
+148protected String getAnalyzerEnabledSettingKey() {
+149return Settings.KEYS.ANALYZER_ARCHIVE_ENABLED;
+150 }
+151
+152/**
+153 * The initialize method does nothing for this Analyzer.
+154 *
+155 * @throws Exception is thrown if there is an exception deleting or creating temporary files
+156 */
+157 @Override
+158publicvoid initializeFileTypeAnalyzer() throws Exception {
+159final File baseDir = Settings.getTempDirectory();
+160if (!baseDir.exists()) {
+161if (!baseDir.mkdirs()) {
+162final String msg = String.format("Unable to make a temporary folder '%s'", baseDir.getPath());
+163thrownewAnalysisException(msg);
+164 }
+165 }
+166 tempFileLocation = File.createTempFile("check", "tmp", baseDir);
+167if (!tempFileLocation.delete()) {
+168final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
+169thrownewAnalysisException(msg);
+170 }
+171if (!tempFileLocation.mkdirs()) {
+172final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
+173thrownewAnalysisException(msg);
+174 }
+175 }
+176
+177/**
+178 * The close method deletes any temporary files and directories created during analysis.
+179 *
+180 * @throws Exception thrown if there is an exception deleting temporary files
+181 */
+182 @Override
+183publicvoid close() throws Exception {
+184if (tempFileLocation != null && tempFileLocation.exists()) {
+185 LOGGER.log(Level.FINE, "Attempting to delete temporary files");
+186finalboolean success = FileUtils.delete(tempFileLocation);
+187if (!success) {
+188 LOGGER.log(Level.WARNING, "Failed to delete some temporary files, see the log for more details");
+189 }
+190 }
+191 }
+192
+193/**
+194 * Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted,
+195 * scanned, and added to the list of dependencies within the engine.
+196 *
+197 * @param dependency the dependency to analyze
+198 * @param engine the engine scanning
+199 * @throws AnalysisException thrown if there is an analysis exception
+200 */
+201 @Override
+202publicvoid analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
+203final File f = new File(dependency.getActualFilePath());
+204final File tmpDir = getNextTempDirectory();
+205 extractFiles(f, tmpDir, engine);
+206
+207//make a copy
+208final List<Dependency> dependencies = new ArrayList<Dependency>(engine.getDependencies());
+209 engine.scan(tmpDir);
+210final List<Dependency> newDependencies = engine.getDependencies();
+211if (dependencies.size() != newDependencies.size()) {
+212//get the new dependencies
+213final Set<Dependency> dependencySet = new HashSet<Dependency>();
+214 dependencySet.addAll(newDependencies);
+215 dependencySet.removeAll(dependencies);
+216
+217for (Dependency d : dependencySet) {
+218//fix the dependency's display name and path
+219final String displayPath = String.format("%s%s",
+220 dependency.getFilePath(),
+221 d.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
+222final String displayName = String.format("%s%s%s",
+223 dependency.getFileName(),
+224 File.separator,
+225 d.getFileName());
+226 d.setFilePath(displayPath);
+227 d.setFileName(displayName);
+228
+229//TODO - can we get more evidence from the parent? EAR contains module name, etc.
+230//analyze the dependency (i.e. extract files) if it is a supported type.
+231if (this.supportsExtension(d.getFileExtension()) && scanDepth < MAX_SCAN_DEPTH) {
+232 scanDepth += 1;
+233 analyze(d, engine);
+234 scanDepth -= 1;
+235 }
+236 }
+237 }
+238 Collections.sort(engine.getDependencies());
+239 }
+240
+241/**
+242 * Retrieves the next temporary directory to extract an archive too.
+243 *
+244 * @return a directory
+245 * @throws AnalysisException thrown if unable to create temporary directory
+246 */
+247private File getNextTempDirectory() throws AnalysisException {
+248 dirCount += 1;
+249final File directory = new File(tempFileLocation, String.valueOf(dirCount));
+250//getting an exception for some directories not being able to be created; might be because the directory already exists?
+251if (directory.exists()) {
+252return getNextTempDirectory();
+253 }
+254if (!directory.mkdirs()) {
+255final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath());
+256thrownewAnalysisException(msg);
+257 }
+258return directory;
+259 }
+260
+261/**
+262 * Extracts the contents of an archive into the specified directory.
+263 *
+264 * @param archive an archive file such as a WAR or EAR
+265 * @param destination a directory to extract the contents to
+266 * @param engine the scanning engine
+267 * @throws AnalysisException thrown if the archive is not found
+268 */
+269privatevoid extractFiles(File archive, File destination, Engine engine) throws AnalysisException {
+270if (archive == null || destination == null) {
+271return;
+272 }
+273
+274 FileInputStream fis = null;
275try {
-276if (ZIPPABLES.contains(archiveExt)) {
-277 extractArchive(new ZipArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
-278 } elseif ("tar".equals(archiveExt)) {
-279 extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
-280 } elseif ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) {
-281final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName());
-282final String uncompressedExt = FileUtils.getFileExtension(uncompressedName).toLowerCase();
-283if (engine.supportsExtension(uncompressedExt)) {
-284 decompressFile(new GzipCompressorInputStream(new BufferedInputStream(fis)), new File(destination, uncompressedName));
-285 }
-286 }
-287 } catch (ArchiveExtractionException ex) {
-288final String msg = String.format("Exception extracting archive '%s'.", archive.getName());
-289 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.WARNING, msg);
-290 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex);
-291 } catch (IOException ex) {
-292final String msg = String.format("Exception reading archive '%s'.", archive.getName());
-293 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.WARNING, msg);
-294 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex);
-295 } finally {
-296try {
-297 fis.close();
-298 } catch (IOException ex) {
-299 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINEST, null, ex);
-300 }
-301 }
-302 }
-303
-304/**
-305 * Extracts files from an archive.
-306 *
-307 * @param input the archive to extract files from
-308 * @param destination the location to write the files too
-309 * @param engine the dependency-check engine
-310 * @throws ArchiveExtractionException thrown if there is an exception extracting files from the archive
-311 */
-312privatevoid extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException {
-313 ArchiveEntry entry;
-314try {
-315while ((entry = input.getNextEntry()) != null) {
-316if (entry.isDirectory()) {
-317final File d = new File(destination, entry.getName());
-318if (!d.exists()) {
-319if (!d.mkdirs()) {
-320final String msg = String.format("Unable to create directory '%s'.", d.getAbsolutePath());
-321thrownewAnalysisException(msg);
-322 }
-323 }
-324 } else {
-325final File file = new File(destination, entry.getName());
-326final String ext = FileUtils.getFileExtension(file.getName());
-327if (engine.supportsExtension(ext)) {
-328 BufferedOutputStream bos = null;
-329 FileOutputStream fos;
-330try {
-331final File parent = file.getParentFile();
-332if (!parent.isDirectory()) {
-333if (!parent.mkdirs()) {
-334final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath());
-335thrownewAnalysisException(msg);
-336 }
-337 }
-338 fos = new FileOutputStream(file);
-339 bos = new BufferedOutputStream(fos, BUFFER_SIZE);
-340int count;
-341final byte data[] = new byte[BUFFER_SIZE];
-342while ((count = input.read(data, 0, BUFFER_SIZE)) != -1) {
-343 bos.write(data, 0, count);
+276 fis = new FileInputStream(archive);
+277 } catch (FileNotFoundException ex) {
+278 LOGGER.log(Level.FINE, null, ex);
+279thrownewAnalysisException("Archive file was not found.", ex);
+280 }
+281final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase();
+282try {
+283if (ZIPPABLES.contains(archiveExt)) {
+284 extractArchive(new ZipArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
+285 } elseif ("tar".equals(archiveExt)) {
+286 extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
+287 } elseif ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) {
+288final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName());
+289final String uncompressedExt = FileUtils.getFileExtension(uncompressedName).toLowerCase();
+290if (engine.supportsExtension(uncompressedExt)) {
+291 decompressFile(new GzipCompressorInputStream(new BufferedInputStream(fis)), new File(destination, uncompressedName));
+292 }
+293 }
+294 } catch (ArchiveExtractionException ex) {
+295final String msg = String.format("Exception extracting archive '%s'.", archive.getName());
+296 LOGGER.log(Level.WARNING, msg);
+297 LOGGER.log(Level.FINE, null, ex);
+298 } catch (IOException ex) {
+299final String msg = String.format("Exception reading archive '%s'.", archive.getName());
+300 LOGGER.log(Level.WARNING, msg);
+301 LOGGER.log(Level.FINE, null, ex);
+302 } finally {
+303try {
+304 fis.close();
+305 } catch (IOException ex) {
+306 LOGGER.log(Level.FINEST, null, ex);
+307 }
+308 }
+309 }
+310
+311/**
+312 * Extracts files from an archive.
+313 *
+314 * @param input the archive to extract files from
+315 * @param destination the location to write the files too
+316 * @param engine the dependency-check engine
+317 * @throws ArchiveExtractionException thrown if there is an exception extracting files from the archive
+318 */
+319privatevoid extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException {
+320 ArchiveEntry entry;
+321try {
+322while ((entry = input.getNextEntry()) != null) {
+323if (entry.isDirectory()) {
+324final File d = new File(destination, entry.getName());
+325if (!d.exists()) {
+326if (!d.mkdirs()) {
+327final String msg = String.format("Unable to create directory '%s'.", d.getAbsolutePath());
+328thrownewAnalysisException(msg);
+329 }
+330 }
+331 } else {
+332final File file = new File(destination, entry.getName());
+333final String ext = FileUtils.getFileExtension(file.getName());
+334if (engine.supportsExtension(ext)) {
+335 BufferedOutputStream bos = null;
+336 FileOutputStream fos;
+337try {
+338final File parent = file.getParentFile();
+339if (!parent.isDirectory()) {
+340if (!parent.mkdirs()) {
+341final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath());
+342thrownewAnalysisException(msg);
+343 }
344 }
-345 bos.flush();
-346 } catch (FileNotFoundException ex) {
-347 Logger.getLogger(ArchiveAnalyzer.class
-348 .getName()).log(Level.FINE, null, ex);
-349final String msg = String.format("Unable to find file '%s'.", file.getName());
-350thrownewAnalysisException(msg, ex);
-351 } catch (IOException ex) {
-352 Logger.getLogger(ArchiveAnalyzer.class
-353 .getName()).log(Level.FINE, null, ex);
-354final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
-355thrownewAnalysisException(msg, ex);
-356 } finally {
-357if (bos != null) {
-358try {
-359 bos.close();
-360 } catch (IOException ex) {
-361 Logger.getLogger(ArchiveAnalyzer.class
-362 .getName()).log(Level.FINEST, null, ex);
-363 }
-364 }
-365 }
-366 }
-367 }
-368 }
-369 } catch (IOException ex) {
-370thrownewArchiveExtractionException(ex);
-371 } catch (Throwable ex) {
-372thrownewArchiveExtractionException(ex);
-373 } finally {
-374if (input != null) {
-375try {
-376 input.close();
-377 } catch (IOException ex) {
-378 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINEST, null, ex);
-379 }
-380 }
-381 }
-382 }
-383
-384/**
-385 * Decompresses a file.
-386 *
-387 * @param inputStream the compressed file
-388 * @param outputFile the location to write the decompressed file
-389 * @throws ArchiveExtractionException thrown if there is an exception decompressing the file
-390 */
-391privatevoid decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException {
-392 FileOutputStream out = null;
-393try {
-394 out = new FileOutputStream(outputFile);
-395final byte[] buffer = new byte[BUFFER_SIZE];
-396int n = 0;
-397while (-1 != (n = inputStream.read(buffer))) {
-398 out.write(buffer, 0, n);
-399 }
-400 } catch (FileNotFoundException ex) {
-401 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex);
-402thrownewArchiveExtractionException(ex);
-403 } catch (IOException ex) {
-404 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex);
-405thrownewArchiveExtractionException(ex);
-406 } finally {
-407if (out != null) {
-408try {
-409 out.close();
-410 } catch (IOException ex) {
-411 Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINEST, null, ex);
-412 }
-413 }
-414 }
-415 }
-416 }
+345 fos = new FileOutputStream(file);
+346 bos = new BufferedOutputStream(fos, BUFFER_SIZE);
+347int count;
+348final byte data[] = new byte[BUFFER_SIZE];
+349while ((count = input.read(data, 0, BUFFER_SIZE)) != -1) {
+350 bos.write(data, 0, count);
+351 }
+352 bos.flush();
+353 } catch (FileNotFoundException ex) {
+354 Logger.getLogger(ArchiveAnalyzer.class
+355 .getName()).log(Level.FINE, null, ex);
+356final String msg = String.format("Unable to find file '%s'.", file.getName());
+357thrownewAnalysisException(msg, ex);
+358 } catch (IOException ex) {
+359 Logger.getLogger(ArchiveAnalyzer.class
+360 .getName()).log(Level.FINE, null, ex);
+361final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
+362thrownewAnalysisException(msg, ex);
+363 } finally {
+364if (bos != null) {
+365try {
+366 bos.close();
+367 } catch (IOException ex) {
+368 Logger.getLogger(ArchiveAnalyzer.class
+369 .getName()).log(Level.FINEST, null, ex);
+370 }
+371 }
+372 }
+373 }
+374 }
+375 }
+376 } catch (IOException ex) {
+377thrownewArchiveExtractionException(ex);
+378 } catch (Throwable ex) {
+379thrownewArchiveExtractionException(ex);
+380 } finally {
+381if (input != null) {
+382try {
+383 input.close();
+384 } catch (IOException ex) {
+385 LOGGER.log(Level.FINEST, null, ex);
+386 }
+387 }
+388 }
+389 }
+390
+391/**
+392 * Decompresses a file.
+393 *
+394 * @param inputStream the compressed file
+395 * @param outputFile the location to write the decompressed file
+396 * @throws ArchiveExtractionException thrown if there is an exception decompressing the file
+397 */
+398privatevoid decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException {
+399 FileOutputStream out = null;
+400try {
+401 out = new FileOutputStream(outputFile);
+402final byte[] buffer = new byte[BUFFER_SIZE];
+403int n = 0;
+404while (-1 != (n = inputStream.read(buffer))) {
+405 out.write(buffer, 0, n);
+406 }
+407 } catch (FileNotFoundException ex) {
+408 LOGGER.log(Level.FINE, null, ex);
+409thrownewArchiveExtractionException(ex);
+410 } catch (IOException ex) {
+411 LOGGER.log(Level.FINE, null, ex);
+412thrownewArchiveExtractionException(ex);
+413 } finally {
+414if (out != null) {
+415try {
+416 out.close();
+417 } catch (IOException ex) {
+418 LOGGER.log(Level.FINEST, null, ex);
+419 }
+420 }
+421 }
+422 }
+423 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html
index e03fd4e8f..8ea79e5aa 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html
@@ -25,256 +25,302 @@
17 */18package org.owasp.dependencycheck.analyzer;
19
-20import java.io.File;
-21import java.io.FileOutputStream;
-22import java.io.IOException;
-23import java.io.InputStream;
-24import java.util.ArrayList;
-25import java.util.List;
-26import java.util.Set;
-27import java.util.logging.Level;
-28import java.util.logging.Logger;
-29import javax.xml.parsers.DocumentBuilder;
-30import javax.xml.parsers.DocumentBuilderFactory;
-31import javax.xml.xpath.XPath;
-32import javax.xml.xpath.XPathExpressionException;
-33import javax.xml.xpath.XPathFactory;
-34import org.owasp.dependencycheck.Engine;
-35import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
-36import org.owasp.dependencycheck.dependency.Confidence;
-37import org.owasp.dependencycheck.dependency.Dependency;
-38import org.owasp.dependencycheck.dependency.Evidence;
-39import org.owasp.dependencycheck.utils.Settings;
-40import org.w3c.dom.Document;
-41import org.xml.sax.SAXException;
-42
-43/**
-44 * Analyzer for getting company, product, and version information from a .NET assembly.
-45 *
-46 * @author colezlaw
+20import java.io.BufferedReader;
+21import java.io.File;
+22import java.io.FileOutputStream;
+23import java.io.IOException;
+24import java.io.InputStream;
+25import java.io.InputStreamReader;
+26import java.util.ArrayList;
+27import java.util.List;
+28import java.util.Set;
+29import java.util.logging.Level;
+30import java.util.logging.Logger;
+31import javax.xml.parsers.DocumentBuilder;
+32import javax.xml.parsers.DocumentBuilderFactory;
+33import javax.xml.xpath.XPath;
+34import javax.xml.xpath.XPathExpressionException;
+35import javax.xml.xpath.XPathFactory;
+36import org.owasp.dependencycheck.Engine;
+37import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+38import org.owasp.dependencycheck.dependency.Confidence;
+39import org.owasp.dependencycheck.dependency.Dependency;
+40import org.owasp.dependencycheck.dependency.Evidence;
+41import org.owasp.dependencycheck.utils.Settings;
+42import org.w3c.dom.Document;
+43import org.xml.sax.SAXException;
+44
+45/**
+46 * Analyzer for getting company, product, and version information from a .NET assembly.47 *
-48 */
-49publicclassAssemblyAnalyzerextendsAbstractAnalyzer {
-50
-51/**
-52 * The analyzer name
-53 */
-54privatestaticfinal String ANALYZER_NAME = "Assembly Analyzer";
-55/**
-56 * The analysis phase
-57 */
-58privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
-59/**
-60 * The list of supported extensions
-61 */
-62privatestaticfinal Set<String> SUPORTED_EXTENSIONS = newHashSet("dll", "exe");
-63/**
-64 * The temp value for GrokAssembly.exe
-65 */
-66private File grokAssemblyExe;
-67/**
-68 * The DocumentBuilder for parsing the XML
-69 */
-70private DocumentBuilder builder;
-71/**
-72 * Logger
-73 */
-74privatestaticfinal Logger LOG = Logger.getLogger(AbstractAnalyzer.class.getName());
-75
-76/**
-77 * Builds the beginnings of a List for ProcessBuilder
-78 *
-79 * @return the list of arguments to begin populating the ProcessBuilder
-80 */
-81private List<String> buildArgumentList() {
-82// Use file.separator as a wild guess as to whether this is Windows
-83final List<String> args = new ArrayList<String>();
-84if (!"\\".equals(System.getProperty("file.separator"))) {
-85if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) {
-86 args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
-87 } else {
-88 args.add("mono");
-89 }
-90 }
-91 args.add(grokAssemblyExe.getPath());
-92
-93return args;
-94 }
-95
-96/**
-97 * Performs the analysis on a single Dependency.
-98 *
-99 * @param dependency the dependency to analyze
-100 * @param engine the engine to perform the analysis under
-101 * @throws AnalysisException if anything goes sideways
-102 */
-103 @Override
-104publicvoid analyze(Dependency dependency, Engine engine)
-105throwsAnalysisException {
-106if (grokAssemblyExe == null) {
-107 LOG.warning("GrokAssembly didn't get deployed");
-108return;
-109 }
-110
-111final List<String> args = buildArgumentList();
-112 args.add(dependency.getActualFilePath());
-113final ProcessBuilder pb = new ProcessBuilder(args);
-114try {
-115final Process proc = pb.start();
-116final Document doc = builder.parse(proc.getInputStream());
-117final XPath xpath = XPathFactory.newInstance().newXPath();
-118
-119// First, see if there was an error
-120final String error = xpath.evaluate("/assembly/error", doc);
-121if (error != null && !"".equals(error)) {
-122thrownewAnalysisException(error);
-123 }
-124
-125final String version = xpath.evaluate("/assembly/version", doc);
-126if (version != null) {
-127 dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version",
-128 version, Confidence.HIGHEST));
-129 }
-130
-131final String vendor = xpath.evaluate("/assembly/company", doc);
-132if (vendor != null) {
-133 dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor",
-134 vendor, Confidence.HIGH));
-135 }
-136
-137final String product = xpath.evaluate("/assembly/product", doc);
-138if (product != null) {
-139 dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product",
-140 product, Confidence.HIGH));
-141 }
-142
-143 } catch (IOException ioe) {
-144thrownewAnalysisException(ioe);
-145 } catch (SAXException saxe) {
-146thrownewAnalysisException("Couldn't parse GrokAssembly result", saxe);
-147 } catch (XPathExpressionException xpe) {
-148// This shouldn't happen
-149thrownewAnalysisException(xpe);
-150 }
-151 }
+48 * @author colezlaw
+49 *
+50 */
+51publicclassAssemblyAnalyzerextendsAbstractFileTypeAnalyzer {
+52
+53/**
+54 * The analyzer name
+55 */
+56privatestaticfinal String ANALYZER_NAME = "Assembly Analyzer";
+57/**
+58 * The analysis phase
+59 */
+60privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
+61/**
+62 * The list of supported extensions
+63 */
+64privatestaticfinal Set<String> SUPORTED_EXTENSIONS = newHashSet("dll", "exe");
+65/**
+66 * The temp value for GrokAssembly.exe
+67 */
+68private File grokAssemblyExe = null;
+69/**
+70 * The DocumentBuilder for parsing the XML
+71 */
+72private DocumentBuilder builder;
+73/**
+74 * Logger
+75 */
+76privatestaticfinal Logger LOG = Logger.getLogger(AssemblyAnalyzer.class.getName());
+77
+78/**
+79 * Builds the beginnings of a List for ProcessBuilder
+80 *
+81 * @return the list of arguments to begin populating the ProcessBuilder
+82 */
+83private List<String> buildArgumentList() {
+84// Use file.separator as a wild guess as to whether this is Windows
+85final List<String> args = new ArrayList<String>();
+86if (!"\\".equals(System.getProperty("file.separator"))) {
+87if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) {
+88 args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
+89 } else {
+90 args.add("mono");
+91 }
+92 }
+93 args.add(grokAssemblyExe.getPath());
+94
+95return args;
+96 }
+97
+98/**
+99 * Performs the analysis on a single Dependency.
+100 *
+101 * @param dependency the dependency to analyze
+102 * @param engine the engine to perform the analysis under
+103 * @throws AnalysisException if anything goes sideways
+104 */
+105 @Override
+106publicvoid analyzeFileType(Dependency dependency, Engine engine)
+107throwsAnalysisException {
+108if (grokAssemblyExe == null) {
+109 LOG.warning("GrokAssembly didn't get deployed");
+110return;
+111 }
+112
+113final List<String> args = buildArgumentList();
+114 args.add(dependency.getActualFilePath());
+115final ProcessBuilder pb = new ProcessBuilder(args);
+116 BufferedReader rdr = null;
+117try {
+118final Process proc = pb.start();
+119// Try evacuating the error stream
+120 rdr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
+121 String line = null;
+122while (rdr.ready() && (line = rdr.readLine()) != null) {
+123 LOG.log(Level.WARNING, "Error from GrokAssembly: {0}", line);
+124 }
+125int rc = 0;
+126final Document doc = builder.parse(proc.getInputStream());
+127final XPath xpath = XPathFactory.newInstance().newXPath();
+128
+129// First, see if there was an error
+130final String error = xpath.evaluate("/assembly/error", doc);
+131if (error != null && !"".equals(error)) {
+132thrownewAnalysisException(error);
+133 }
+134
+135final String version = xpath.evaluate("/assembly/version", doc);
+136if (version != null) {
+137 dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version",
+138 version, Confidence.HIGHEST));
+139 }
+140
+141final String vendor = xpath.evaluate("/assembly/company", doc);
+142if (vendor != null) {
+143 dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor",
+144 vendor, Confidence.HIGH));
+145 }
+146
+147final String product = xpath.evaluate("/assembly/product", doc);
+148if (product != null) {
+149 dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product",
+150 product, Confidence.HIGH));
+151 }
152
-153/**
-154 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a temporary location.
-155 *
-156 * @throws Exception if anything goes wrong
-157 */
-158 @Override
-159publicvoid initialize() throws Exception {
-160super.initialize();
-161final File tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory());
-162 FileOutputStream fos = null;
-163 InputStream is = null;
-164try {
-165 fos = new FileOutputStream(tempFile);
-166 is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe");
-167final byte[] buff = new byte[4096];
-168int bread = -1;
-169while ((bread = is.read(buff)) >= 0) {
-170 fos.write(buff, 0, bread);
-171 }
-172 grokAssemblyExe = tempFile;
-173// Set the temp file to get deleted when we're done
-174 grokAssemblyExe.deleteOnExit();
-175 LOG.log(Level.FINE, "Extracted GrokAssembly.exe to {0}", grokAssemblyExe.getPath());
-176 } catch (IOException ioe) {
-177 LOG.log(Level.WARNING, "Could not extract GrokAssembly.exe: {0}", ioe.getMessage());
-178thrownewAnalysisException("Could not extract GrokAssembly.exe", ioe);
-179 } finally {
-180if (fos != null) {
-181try {
-182 fos.close();
-183 } catch (Throwable e) {
-184 LOG.fine("Error closing output stream");
-185 }
-186 }
-187if (is != null) {
-188try {
-189 is.close();
-190 } catch (Throwable e) {
-191 LOG.fine("Error closing input stream");
-192 }
-193 }
-194 }
-195
-196// Now, need to see if GrokAssembly actually runs from this location.
-197final List<String> args = buildArgumentList();
-198try {
-199final Process p = new ProcessBuilder(args).start();
-200final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream());
-201final XPath xpath = XPathFactory.newInstance().newXPath();
-202final String error = xpath.evaluate("/assembly/error", doc);
-203if (p.waitFor() != 1 || error == null || "".equals(error)) {
-204 LOG.warning("An error occured with the .NET AssemblyAnalyzer, please see the log for more details.");
-205 LOG.fine("GrokAssembly.exe is not working properly");
-206 grokAssemblyExe = null;
-207thrownewAnalysisException("Could not execute .NET AssemblyAnalyzer");
-208 }
-209 } catch (Throwable e) {
-210 LOG.warning("An error occured with the .NET AssemblyAnalyzer; "
-211 + "this can be ignored unless you are scanning .NET dlls. Please see the log for more details.");
-212 LOG.log(Level.FINE, "Could not execute GrokAssembly {0}", e.getMessage());
-213thrownewAnalysisException("An error occured with the .NET AssemblyAnalyzer", e);
-214 }
-215
-216 builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
-217 }
-218
-219 @Override
-220publicvoid close() throws Exception {
-221super.close();
-222try {
-223 grokAssemblyExe.delete();
-224 } catch (SecurityException se) {
-225 LOG.fine("Can't delete temporary GrokAssembly.exe");
-226 }
-227 }
-228
-229/**
-230 * Gets the set of extensions supported by this analyzer.
-231 *
-232 * @return the list of supported extensions
-233 */
-234 @Override
-235public Set<String> getSupportedExtensions() {
-236return SUPORTED_EXTENSIONS;
-237 }
-238
-239/**
-240 * Gets this analyzer's name.
-241 *
-242 * @return the analyzer name
-243 */
-244 @Override
-245public String getName() {
-246return ANALYZER_NAME;
-247 }
-248
-249/**
-250 * Gets whether the analyzer supports the provided extension.
-251 *
-252 * @param extension the extension to check
-253 * @return whether the analyzer supports the extension
-254 */
-255 @Override
-256publicboolean supportsExtension(String extension) {
-257return SUPORTED_EXTENSIONS.contains(extension);
-258 }
-259
-260/**
-261 * Returns the phase this analyzer runs under.
-262 *
-263 * @return the phase this runs under
-264 */
-265 @Override
-266publicAnalysisPhase getAnalysisPhase() {
-267return ANALYSIS_PHASE;
-268 }
-269 }
+153try {
+154 rc = proc.waitFor();
+155 } catch (InterruptedException ie) {
+156return;
+157 }
+158if (rc == 3) {
+159 LOG.log(Level.INFO, "{0} is not a valid assembly", dependency.getActualFilePath());
+160return;
+161 } elseif (rc != 0) {
+162 LOG.log(Level.WARNING, "Return code {0} from GrokAssembly", rc);
+163 }
+164
+165 } catch (IOException ioe) {
+166thrownewAnalysisException(ioe);
+167 } catch (SAXException saxe) {
+168thrownewAnalysisException("Couldn't parse GrokAssembly result", saxe);
+169 } catch (XPathExpressionException xpe) {
+170// This shouldn't happen
+171thrownewAnalysisException(xpe);
+172 } finally {
+173if (rdr != null) {
+174try {
+175 rdr.close();
+176 } catch (IOException ex) {
+177 Logger.getLogger(AssemblyAnalyzer.class.getName()).log(Level.FINEST, "ignore", ex);
+178 }
+179 }
+180 }
+181 }
+182
+183/**
+184 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a temporary location.
+185 *
+186 * @throws Exception if anything goes wrong
+187 */
+188 @Override
+189publicvoid initializeFileTypeAnalyzer() throws Exception {
+190final File tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory());
+191 FileOutputStream fos = null;
+192 InputStream is = null;
+193try {
+194 fos = new FileOutputStream(tempFile);
+195 is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe");
+196final byte[] buff = new byte[4096];
+197int bread = -1;
+198while ((bread = is.read(buff)) >= 0) {
+199 fos.write(buff, 0, bread);
+200 }
+201 grokAssemblyExe = tempFile;
+202// Set the temp file to get deleted when we're done
+203 grokAssemblyExe.deleteOnExit();
+204 LOG.log(Level.FINE, "Extracted GrokAssembly.exe to {0}", grokAssemblyExe.getPath());
+205 } catch (IOException ioe) {
+206 LOG.log(Level.WARNING, "Could not extract GrokAssembly.exe: {0}", ioe.getMessage());
+207thrownewAnalysisException("Could not extract GrokAssembly.exe", ioe);
+208 } finally {
+209if (fos != null) {
+210try {
+211 fos.close();
+212 } catch (Throwable e) {
+213 LOG.fine("Error closing output stream");
+214 }
+215 }
+216if (is != null) {
+217try {
+218 is.close();
+219 } catch (Throwable e) {
+220 LOG.fine("Error closing input stream");
+221 }
+222 }
+223 }
+224
+225// Now, need to see if GrokAssembly actually runs from this location.
+226final List<String> args = buildArgumentList();
+227 BufferedReader rdr = null;
+228try {
+229final ProcessBuilder pb = new ProcessBuilder(args);
+230final Process p = pb.start();
+231// Try evacuating the error stream
+232 rdr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
+233 String line;
+234while (rdr.ready() && (line = rdr.readLine()) != null) {
+235// We expect this to complain
+236 }
+237final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream());
+238final XPath xpath = XPathFactory.newInstance().newXPath();
+239final String error = xpath.evaluate("/assembly/error", doc);
+240if (p.waitFor() != 1 || error == null || "".equals(error)) {
+241 LOG.warning("An error occured with the .NET AssemblyAnalyzer, please see the log for more details.");
+242 LOG.fine("GrokAssembly.exe is not working properly");
+243 grokAssemblyExe = null;
+244thrownewAnalysisException("Could not execute .NET AssemblyAnalyzer");
+245 }
+246 } catch (Throwable e) {
+247 LOG.warning("An error occured with the .NET AssemblyAnalyzer; "
+248 + "this can be ignored unless you are scanning .NET dlls. Please see the log for more details.");
+249 LOG.log(Level.FINE, "Could not execute GrokAssembly {0}", e.getMessage());
+250thrownewAnalysisException("An error occured with the .NET AssemblyAnalyzer", e);
+251 } finally {
+252if (rdr != null) {
+253try {
+254 rdr.close();
+255 } catch (IOException ex) {
+256 Logger.getLogger(AssemblyAnalyzer.class.getName()).log(Level.FINEST, "ignore", ex);
+257 }
+258 }
+259 }
+260
+261 builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+262 }
+263
+264 @Override
+265publicvoid close() throws Exception {
+266super.close();
+267try {
+268if (grokAssemblyExe != null && !grokAssemblyExe.delete()) {
+269 grokAssemblyExe.deleteOnExit();
+270 }
+271 } catch (SecurityException se) {
+272 LOG.fine("Can't delete temporary GrokAssembly.exe");
+273 }
+274 }
+275
+276/**
+277 * Gets the set of extensions supported by this analyzer.
+278 *
+279 * @return the list of supported extensions
+280 */
+281 @Override
+282public Set<String> getSupportedExtensions() {
+283return SUPORTED_EXTENSIONS;
+284 }
+285
+286/**
+287 * Gets this analyzer's name.
+288 *
+289 * @return the analyzer name
+290 */
+291 @Override
+292public String getName() {
+293return ANALYZER_NAME;
+294 }
+295
+296/**
+297 * Returns the phase this analyzer runs under.
+298 *
+299 * @return the phase this runs under
+300 */
+301 @Override
+302publicAnalysisPhase getAnalysisPhase() {
+303return ANALYSIS_PHASE;
+304 }
+305
+306/**
+307 * Returns the key used in the properties file to reference the analyzer's enabled property.
+308 *
+309 * @return the analyzer's enabled property setting key
+310 */
+311 @Override
+312protected String getAnalyzerEnabledSettingKey() {
+313return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED;
+314 }
+315 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html
index 90e61a81f..b973fce0b 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html
@@ -96,686 +96,665 @@
88privateCveDB cve;
8990/**
-91 * Opens the data source.
+91 * Returns the name of this analyzer.92 *
-93 * @throws IOException when the Lucene directory to be queried does not exist or is corrupt.
-94 * @throws DatabaseException when the database throws an exception. This usually occurs when the database is in use
-95 * by another process.
-96 */
-97publicvoid open() throws IOException, DatabaseException {
-98 Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.FINE, "Opening the CVE Database");
-99 cve = newCveDB();
-100 cve.open();
-101 Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.FINE, "Creating the Lucene CPE Index");
-102 cpe = CpeMemoryIndex.getInstance();
-103try {
-104 cpe.open(cve);
-105 } catch (IndexException ex) {
-106 Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.FINE, "IndexException", ex);
-107thrownewDatabaseException(ex);
-108 }
-109 }
-110
-111/**
-112 * Closes the data sources.
-113 */
-114 @Override
-115publicvoid close() {
-116if (cpe != null) {
-117 cpe.close();
-118 }
-119if (cve != null) {
-120 cve.close();
-121 }
-122 }
-123
-124/**
-125 * Searches the data store of CPE entries, trying to identify the CPE for the given dependency based on the evidence
-126 * contained within. The dependency passed in is updated with any identified CPE values.
-127 *
-128 * @param dependency the dependency to search for CPE entries on.
-129 * @throws CorruptIndexException is thrown when the Lucene index is corrupt.
-130 * @throws IOException is thrown when an IOException occurs.
-131 * @throws ParseException is thrown when the Lucene query cannot be parsed.
-132 */
-133protectedvoid determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
-134Confidence confidence = Confidence.HIGHEST;
-135
-136 String vendors = addEvidenceWithoutDuplicateTerms("", dependency.getVendorEvidence(), confidence);
-137 String products = addEvidenceWithoutDuplicateTerms("", dependency.getProductEvidence(), confidence);
-138/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
-139 * CPE identified. As such, we are "using" the evidence and ignoring the results. */
-140 addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
-141
-142int ctr = 0;
-143do {
-144if (!vendors.isEmpty() && !products.isEmpty()) {
-145final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
-146 dependency.getVendorEvidence().getWeighting());
-147
-148for (IndexEntry e : entries) {
-149if (verifyEntry(e, dependency)) {
-150final String vendor = e.getVendor();
-151final String product = e.getProduct();
-152 determineIdentifiers(dependency, vendor, product);
-153 }
-154 }
-155 }
-156 confidence = reduceConfidence(confidence);
-157if (dependency.getVendorEvidence().contains(confidence)) {
-158 vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence);
-159 }
-160if (dependency.getProductEvidence().contains(confidence)) {
-161 products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence);
-162 }
-163/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
-164 * CPE identified. As such, we are "using" the evidence and ignoring the results. */
-165if (dependency.getVersionEvidence().contains(confidence)) {
-166 addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
-167 }
-168 } while ((++ctr) < 4);
-169 }
-170
-171/**
-172 * Returns the text created by concatenating the text and the values from the EvidenceCollection (filtered for a
-173 * specific confidence). This attempts to prevent duplicate terms from being added.<br/<br/> Note, if the evidence
-174 * is longer then 200 characters it will be truncated.
-175 *
-176 * @param text the base text.
-177 * @param ec an EvidenceCollection
-178 * @param confidenceFilter a Confidence level to filter the evidence by.
-179 * @return the new evidence text
-180 */
-181private String addEvidenceWithoutDuplicateTerms(final String text, finalEvidenceCollection ec, Confidence confidenceFilter) {
-182final String txt = (text == null) ? "" : text;
-183final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size()));
-184 sb.append(' ').append(txt).append(' ');
-185for (Evidence e : ec.iterator(confidenceFilter)) {
-186 String value = e.getValue();
-187
-188//hack to get around the fact that lucene does a really good job of recognizing domains and not
-189// splitting them. TODO - put together a better lucene analyzer specific to the domain.
-190if (value.startsWith("http://")) {
-191 value = value.substring(7).replaceAll("\\.", " ");
+93 * @return the name of this analyzer.
+94 */
+95 @Override
+96public String getName() {
+97return"CPE Analyzer";
+98 }
+99
+100/**
+101 * Returns the analysis phase that this analyzer should run in.
+102 *
+103 * @return the analysis phase that this analyzer should run in.
+104 */
+105 @Override
+106publicAnalysisPhase getAnalysisPhase() {
+107return AnalysisPhase.IDENTIFIER_ANALYSIS;
+108 }
+109
+110/**
+111 * Creates the CPE Lucene Index.
+112 *
+113 * @throws Exception is thrown if there is an issue opening the index.
+114 */
+115 @Override
+116publicvoid initialize() throws Exception {
+117this.open();
+118 }
+119
+120/**
+121 * Opens the data source.
+122 *
+123 * @throws IOException when the Lucene directory to be queried does not exist or is corrupt.
+124 * @throws DatabaseException when the database throws an exception. This usually occurs when the database is in use
+125 * by another process.
+126 */
+127publicvoid open() throws IOException, DatabaseException {
+128 Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.FINE, "Opening the CVE Database");
+129 cve = newCveDB();
+130 cve.open();
+131 Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.FINE, "Creating the Lucene CPE Index");
+132 cpe = CpeMemoryIndex.getInstance();
+133try {
+134 cpe.open(cve);
+135 } catch (IndexException ex) {
+136 Logger.getLogger(CPEAnalyzer.class.getName()).log(Level.FINE, "IndexException", ex);
+137thrownewDatabaseException(ex);
+138 }
+139 }
+140
+141/**
+142 * Closes the data sources.
+143 */
+144 @Override
+145publicvoid close() {
+146if (cpe != null) {
+147 cpe.close();
+148 }
+149if (cve != null) {
+150 cve.close();
+151 }
+152 }
+153
+154/**
+155 * Searches the data store of CPE entries, trying to identify the CPE for the given dependency based on the evidence
+156 * contained within. The dependency passed in is updated with any identified CPE values.
+157 *
+158 * @param dependency the dependency to search for CPE entries on.
+159 * @throws CorruptIndexException is thrown when the Lucene index is corrupt.
+160 * @throws IOException is thrown when an IOException occurs.
+161 * @throws ParseException is thrown when the Lucene query cannot be parsed.
+162 */
+163protectedvoid determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
+164Confidence confidence = Confidence.HIGHEST;
+165
+166 String vendors = addEvidenceWithoutDuplicateTerms("", dependency.getVendorEvidence(), confidence);
+167 String products = addEvidenceWithoutDuplicateTerms("", dependency.getProductEvidence(), confidence);
+168/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
+169 * CPE identified. As such, we are "using" the evidence and ignoring the results. */
+170 addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
+171
+172int ctr = 0;
+173do {
+174if (!vendors.isEmpty() && !products.isEmpty()) {
+175final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
+176 dependency.getVendorEvidence().getWeighting());
+177
+178for (IndexEntry e : entries) {
+179if (verifyEntry(e, dependency)) {
+180final String vendor = e.getVendor();
+181final String product = e.getProduct();
+182 determineIdentifiers(dependency, vendor, product);
+183 }
+184 }
+185 }
+186 confidence = reduceConfidence(confidence);
+187if (dependency.getVendorEvidence().contains(confidence)) {
+188 vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence);
+189 }
+190if (dependency.getProductEvidence().contains(confidence)) {
+191 products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence);
192 }
-193if (value.startsWith("https://")) {
-194 value = value.substring(8).replaceAll("\\.", " ");
-195 }
-196if (sb.indexOf(" " + value + " ") < 0) {
-197 sb.append(value).append(' ');
-198 }
-199 }
-200return sb.toString().trim();
-201 }
-202
-203/**
-204 * Reduces the given confidence by one level. This returns LOW if the confidence passed in is not HIGH.
+193/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
+194 * CPE identified. As such, we are "using" the evidence and ignoring the results. */
+195if (dependency.getVersionEvidence().contains(confidence)) {
+196 addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
+197 }
+198 } while ((++ctr) < 4);
+199 }
+200
+201/**
+202 * Returns the text created by concatenating the text and the values from the EvidenceCollection (filtered for a
+203 * specific confidence). This attempts to prevent duplicate terms from being added.<br/<br/> Note, if the evidence
+204 * is longer then 200 characters it will be truncated.205 *
-206 * @param c the confidence to reduce.
-207 * @return One less then the confidence passed in.
-208 */
-209privateConfidence reduceConfidence(finalConfidence c) {
-210if (c == Confidence.HIGHEST) {
-211return Confidence.HIGH;
-212 } elseif (c == Confidence.HIGH) {
-213return Confidence.MEDIUM;
-214 } else {
-215return Confidence.LOW;
-216 }
-217 }
-218
-219/**
-220 * <p>
-221 * Searches the Lucene CPE index to identify possible CPE entries associated with the supplied vendor, product, and
-222 * version.</p>
-223 *
-224 * <p>
-225 * If either the vendorWeightings or productWeightings lists have been populated this data is used to add weighting
-226 * factors to the search.</p>
-227 *
-228 * @param vendor the text used to search the vendor field
-229 * @param product the text used to search the product field
-230 * @param vendorWeightings a list of strings to use to add weighting factors to the vendor field
-231 * @param productWeightings Adds a list of strings that will be used to add weighting factors to the product search
-232 * @return a list of possible CPE values
-233 * @throws CorruptIndexException when the Lucene index is corrupt
-234 * @throws IOException when the Lucene index is not found
-235 * @throws ParseException when the generated query is not valid
-236 */
-237protected List<IndexEntry> searchCPE(String vendor, String product,
-238 Set<String> vendorWeightings, Set<String> productWeightings)
-239throws CorruptIndexException, IOException, ParseException {
-240final ArrayList<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS);
-241
-242final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings);
-243if (searchString == null) {
-244return ret;
-245 }
-246
-247final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS);
-248for (ScoreDoc d : docs.scoreDocs) {
-249if (d.score >= 0.08) {
-250final Document doc = cpe.getDocument(d.doc);
-251finalIndexEntry entry = newIndexEntry();
-252 entry.setVendor(doc.get(Fields.VENDOR));
-253 entry.setProduct(doc.get(Fields.PRODUCT));
-254// if (d.score < 0.08) {
-255// System.out.print(entry.getVendor());
-256// System.out.print(":");
-257// System.out.print(entry.getProduct());
-258// System.out.print(":");
-259// System.out.println(d.score);
-260// }
-261 entry.setSearchScore(d.score);
-262if (!ret.contains(entry)) {
-263 ret.add(entry);
-264 }
-265 }
-266 }
-267return ret;
-268 }
-269
-270/**
-271 * <p>
-272 * Builds a Lucene search string by properly escaping data and constructing a valid search query.</p>
-273 *
-274 * <p>
-275 * If either the possibleVendor or possibleProducts lists have been populated this data is used to add weighting
-276 * factors to the search string generated.</p>
-277 *
-278 * @param vendor text to search the vendor field
-279 * @param product text to search the product field
-280 * @param vendorWeighting a list of strings to apply to the vendor to boost the terms weight
-281 * @param productWeightings a list of strings to apply to the product to boost the terms weight
-282 * @return the Lucene query
-283 */
-284protected String buildSearch(String vendor, String product,
-285 Set<String> vendorWeighting, Set<String> productWeightings) {
-286final String v = vendor; //.replaceAll("[^\\w\\d]", " ");
-287final String p = product; //.replaceAll("[^\\w\\d]", " ");
-288final StringBuilder sb = new StringBuilder(v.length() + p.length()
-289 + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER);
-290
-291if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) {
-292returnnull;
-293 }
-294 sb.append(" AND ");
-295if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) {
-296returnnull;
-297 }
-298return sb.toString();
-299 }
-300
-301/**
-302 * This method constructs a Lucene query for a given field. The searchText is split into separate words and if the
-303 * word is within the list of weighted words then an additional weighting is applied to the term as it is appended
-304 * into the query.
-305 *
-306 * @param sb a StringBuilder that the query text will be appended to.
-307 * @param field the field within the Lucene index that the query is searching.
-308 * @param searchText text used to construct the query.
-309 * @param weightedText a list of terms that will be considered higher importance when searching.
-310 * @return if the append was successful.
-311 */
-312privateboolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) {
-313 sb.append(" ").append(field).append(":( ");
-314
-315final String cleanText = cleanseText(searchText);
-316
-317if ("".equals(cleanText)) {
-318return false;
-319 }
+206 * @param text the base text.
+207 * @param ec an EvidenceCollection
+208 * @param confidenceFilter a Confidence level to filter the evidence by.
+209 * @return the new evidence text
+210 */
+211private String addEvidenceWithoutDuplicateTerms(final String text, finalEvidenceCollection ec, Confidence confidenceFilter) {
+212final String txt = (text == null) ? "" : text;
+213final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size()));
+214 sb.append(' ').append(txt).append(' ');
+215for (Evidence e : ec.iterator(confidenceFilter)) {
+216 String value = e.getValue();
+217
+218//hack to get around the fact that lucene does a really good job of recognizing domains and not
+219// splitting them. TODO - put together a better lucene analyzer specific to the domain.
+220if (value.startsWith("http://")) {
+221 value = value.substring(7).replaceAll("\\.", " ");
+222 }
+223if (value.startsWith("https://")) {
+224 value = value.substring(8).replaceAll("\\.", " ");
+225 }
+226if (sb.indexOf(" " + value + " ") < 0) {
+227 sb.append(value).append(' ');
+228 }
+229 }
+230return sb.toString().trim();
+231 }
+232
+233/**
+234 * Reduces the given confidence by one level. This returns LOW if the confidence passed in is not HIGH.
+235 *
+236 * @param c the confidence to reduce.
+237 * @return One less then the confidence passed in.
+238 */
+239privateConfidence reduceConfidence(finalConfidence c) {
+240if (c == Confidence.HIGHEST) {
+241return Confidence.HIGH;
+242 } elseif (c == Confidence.HIGH) {
+243return Confidence.MEDIUM;
+244 } else {
+245return Confidence.LOW;
+246 }
+247 }
+248
+249/**
+250 * <p>
+251 * Searches the Lucene CPE index to identify possible CPE entries associated with the supplied vendor, product, and
+252 * version.</p>
+253 *
+254 * <p>
+255 * If either the vendorWeightings or productWeightings lists have been populated this data is used to add weighting
+256 * factors to the search.</p>
+257 *
+258 * @param vendor the text used to search the vendor field
+259 * @param product the text used to search the product field
+260 * @param vendorWeightings a list of strings to use to add weighting factors to the vendor field
+261 * @param productWeightings Adds a list of strings that will be used to add weighting factors to the product search
+262 * @return a list of possible CPE values
+263 * @throws CorruptIndexException when the Lucene index is corrupt
+264 * @throws IOException when the Lucene index is not found
+265 * @throws ParseException when the generated query is not valid
+266 */
+267protected List<IndexEntry> searchCPE(String vendor, String product,
+268 Set<String> vendorWeightings, Set<String> productWeightings)
+269throws CorruptIndexException, IOException, ParseException {
+270final ArrayList<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS);
+271
+272final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings);
+273if (searchString == null) {
+274return ret;
+275 }
+276
+277final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS);
+278for (ScoreDoc d : docs.scoreDocs) {
+279if (d.score >= 0.08) {
+280final Document doc = cpe.getDocument(d.doc);
+281finalIndexEntry entry = newIndexEntry();
+282 entry.setVendor(doc.get(Fields.VENDOR));
+283 entry.setProduct(doc.get(Fields.PRODUCT));
+284// if (d.score < 0.08) {
+285// System.out.print(entry.getVendor());
+286// System.out.print(":");
+287// System.out.print(entry.getProduct());
+288// System.out.print(":");
+289// System.out.println(d.score);
+290// }
+291 entry.setSearchScore(d.score);
+292if (!ret.contains(entry)) {
+293 ret.add(entry);
+294 }
+295 }
+296 }
+297return ret;
+298 }
+299
+300/**
+301 * <p>
+302 * Builds a Lucene search string by properly escaping data and constructing a valid search query.</p>
+303 *
+304 * <p>
+305 * If either the possibleVendor or possibleProducts lists have been populated this data is used to add weighting
+306 * factors to the search string generated.</p>
+307 *
+308 * @param vendor text to search the vendor field
+309 * @param product text to search the product field
+310 * @param vendorWeighting a list of strings to apply to the vendor to boost the terms weight
+311 * @param productWeightings a list of strings to apply to the product to boost the terms weight
+312 * @return the Lucene query
+313 */
+314protected String buildSearch(String vendor, String product,
+315 Set<String> vendorWeighting, Set<String> productWeightings) {
+316final String v = vendor; //.replaceAll("[^\\w\\d]", " ");
+317final String p = product; //.replaceAll("[^\\w\\d]", " ");
+318final StringBuilder sb = new StringBuilder(v.length() + p.length()
+319 + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER);
320
-321if (weightedText == null || weightedText.isEmpty()) {
-322 LuceneUtils.appendEscapedLuceneQuery(sb, cleanText);
-323 } else {
-324final StringTokenizer tokens = new StringTokenizer(cleanText);
-325while (tokens.hasMoreElements()) {
-326final String word = tokens.nextToken();
-327 String temp = null;
-328for (String weighted : weightedText) {
-329final String weightedStr = cleanseText(weighted);
-330if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) {
-331 temp = LuceneUtils.escapeLuceneQuery(word) + WEIGHTING_BOOST;
-332if (!word.equalsIgnoreCase(weightedStr)) {
-333 temp += " " + LuceneUtils.escapeLuceneQuery(weightedStr) + WEIGHTING_BOOST;
-334 }
-335 }
-336 }
-337if (temp == null) {
-338 temp = LuceneUtils.escapeLuceneQuery(word);
-339 }
-340 sb.append(" ").append(temp);
-341 }
-342 }
-343 sb.append(" ) ");
-344returntrue;
-345 }
+321if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) {
+322returnnull;
+323 }
+324 sb.append(" AND ");
+325if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) {
+326returnnull;
+327 }
+328return sb.toString();
+329 }
+330
+331/**
+332 * This method constructs a Lucene query for a given field. The searchText is split into separate words and if the
+333 * word is within the list of weighted words then an additional weighting is applied to the term as it is appended
+334 * into the query.
+335 *
+336 * @param sb a StringBuilder that the query text will be appended to.
+337 * @param field the field within the Lucene index that the query is searching.
+338 * @param searchText text used to construct the query.
+339 * @param weightedText a list of terms that will be considered higher importance when searching.
+340 * @return if the append was successful.
+341 */
+342privateboolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) {
+343 sb.append(" ").append(field).append(":( ");
+344
+345final String cleanText = cleanseText(searchText);
346
-347/**
-348 * Removes characters from the input text that are not used within the CPE index.
-349 *
-350 * @param text is the text to remove the characters from.
-351 * @return the text having removed some characters.
-352 */
-353private String cleanseText(String text) {
-354return text.replaceAll(CLEANSE_CHARACTER_RX, " ");
-355 }
-356
-357/**
-358 * Compares two strings after lower casing them and removing the non-alpha characters.
-359 *
-360 * @param l string one to compare.
-361 * @param r string two to compare.
-362 * @return whether or not the two strings are similar.
-363 */
-364privateboolean equalsIgnoreCaseAndNonAlpha(String l, String r) {
-365if (l == null || r == null) {
-366return false;
-367 }
-368
-369final String left = l.replaceAll(CLEANSE_NONALPHA_RX, "");
-370final String right = r.replaceAll(CLEANSE_NONALPHA_RX, "");
-371return left.equalsIgnoreCase(right);
-372 }
-373
-374/**
-375 * Ensures that the CPE Identified matches the dependency. This validates that the product, vendor, and version
-376 * information for the CPE are contained within the dependencies evidence.
-377 *
-378 * @param entry a CPE entry.
-379 * @param dependency the dependency that the CPE entries could be for.
-380 * @return whether or not the entry is valid.
-381 */
-382privateboolean verifyEntry(finalIndexEntry entry, finalDependency dependency) {
-383boolean isValid = false;
-384
-385if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct())
-386 && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) {
-387//&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion())
-388 isValid = true;
-389 }
-390return isValid;
-391 }
-392
-393/**
-394 * Used to determine if the EvidenceCollection contains a specific string.
-395 *
-396 * @param ec an EvidenceCollection
-397 * @param text the text to search for
-398 * @return whether or not the EvidenceCollection contains the string
-399 */
-400privateboolean collectionContainsString(EvidenceCollection ec, String text) {
-401
-402//<editor-fold defaultstate="collapsed" desc="This code fold contains an old version of the code, delete once more testing is done">
-403// String[] splitText = text.split("[\\s_-]");
-404//
-405// for (String search : splitText) {
-406// //final String search = text.replaceAll("[\\s_-]", "").toLowerCase();
-407// if (ec.containsUsedString(search)) {
-408// return true;
-409// }
-410// }
-411//</editor-fold>
-412//TODO - likely need to change the split... not sure if this will work for CPE with special chars
-413if (text == null) {
-414return false;
-415 }
-416final String[] words = text.split("[\\s_-]");
-417final List<String> list = new ArrayList<String>();
-418 String tempWord = null;
-419for (String word : words) {
-420/*
-421 single letter words should be concatenated with the next word.
-422 so { "m", "core", "sample" } -> { "mcore", "sample" }
-423 */
-424if (tempWord != null) {
-425 list.add(tempWord + word);
-426 tempWord = null;
-427 } elseif (word.length() <= 2) {
-428 tempWord = word;
-429 } else {
-430 list.add(word);
-431 }
-432 }
-433if (tempWord != null && !list.isEmpty()) {
-434final String tmp = list.get(list.size() - 1) + tempWord;
-435 list.add(tmp);
-436 }
-437boolean contains = true;
-438for (String word : list) {
-439 contains &= ec.containsUsedString(word);
-440 }
-441return contains;
-442 }
-443
-444/**
-445 * Analyzes a dependency and attempts to determine if there are any CPE identifiers for this dependency.
-446 *
-447 * @param dependency The Dependency to analyze.
-448 * @param engine The analysis engine
-449 * @throws AnalysisException is thrown if there is an issue analyzing the dependency.
-450 */
-451 @Override
-452publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-453try {
-454 determineCPE(dependency);
-455 } catch (CorruptIndexException ex) {
-456thrownewAnalysisException("CPE Index is corrupt.", ex);
-457 } catch (IOException ex) {
-458thrownewAnalysisException("Failure opening the CPE Index.", ex);
-459 } catch (ParseException ex) {
-460thrownewAnalysisException("Unable to parse the generated Lucene query for this dependency.", ex);
-461 }
-462 }
-463
-464/**
-465 * Returns true because this analyzer supports all dependency types.
-466 *
-467 * @return true.
-468 */
-469 @Override
-470public Set<String> getSupportedExtensions() {
-471returnnull;
+347if ("".equals(cleanText)) {
+348return false;
+349 }
+350
+351if (weightedText == null || weightedText.isEmpty()) {
+352 LuceneUtils.appendEscapedLuceneQuery(sb, cleanText);
+353 } else {
+354final StringTokenizer tokens = new StringTokenizer(cleanText);
+355while (tokens.hasMoreElements()) {
+356final String word = tokens.nextToken();
+357 String temp = null;
+358for (String weighted : weightedText) {
+359final String weightedStr = cleanseText(weighted);
+360if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) {
+361 temp = LuceneUtils.escapeLuceneQuery(word) + WEIGHTING_BOOST;
+362if (!word.equalsIgnoreCase(weightedStr)) {
+363 temp += " " + LuceneUtils.escapeLuceneQuery(weightedStr) + WEIGHTING_BOOST;
+364 }
+365 }
+366 }
+367if (temp == null) {
+368 temp = LuceneUtils.escapeLuceneQuery(word);
+369 }
+370 sb.append(" ").append(temp);
+371 }
+372 }
+373 sb.append(" ) ");
+374returntrue;
+375 }
+376
+377/**
+378 * Removes characters from the input text that are not used within the CPE index.
+379 *
+380 * @param text is the text to remove the characters from.
+381 * @return the text having removed some characters.
+382 */
+383private String cleanseText(String text) {
+384return text.replaceAll(CLEANSE_CHARACTER_RX, " ");
+385 }
+386
+387/**
+388 * Compares two strings after lower casing them and removing the non-alpha characters.
+389 *
+390 * @param l string one to compare.
+391 * @param r string two to compare.
+392 * @return whether or not the two strings are similar.
+393 */
+394privateboolean equalsIgnoreCaseAndNonAlpha(String l, String r) {
+395if (l == null || r == null) {
+396return false;
+397 }
+398
+399final String left = l.replaceAll(CLEANSE_NONALPHA_RX, "");
+400final String right = r.replaceAll(CLEANSE_NONALPHA_RX, "");
+401return left.equalsIgnoreCase(right);
+402 }
+403
+404/**
+405 * Ensures that the CPE Identified matches the dependency. This validates that the product, vendor, and version
+406 * information for the CPE are contained within the dependencies evidence.
+407 *
+408 * @param entry a CPE entry.
+409 * @param dependency the dependency that the CPE entries could be for.
+410 * @return whether or not the entry is valid.
+411 */
+412privateboolean verifyEntry(finalIndexEntry entry, finalDependency dependency) {
+413boolean isValid = false;
+414
+415if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct())
+416 && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) {
+417//&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion())
+418 isValid = true;
+419 }
+420return isValid;
+421 }
+422
+423/**
+424 * Used to determine if the EvidenceCollection contains a specific string.
+425 *
+426 * @param ec an EvidenceCollection
+427 * @param text the text to search for
+428 * @return whether or not the EvidenceCollection contains the string
+429 */
+430privateboolean collectionContainsString(EvidenceCollection ec, String text) {
+431
+432//<editor-fold defaultstate="collapsed" desc="This code fold contains an old version of the code, delete once more testing is done">
+433// String[] splitText = text.split("[\\s_-]");
+434//
+435// for (String search : splitText) {
+436// //final String search = text.replaceAll("[\\s_-]", "").toLowerCase();
+437// if (ec.containsUsedString(search)) {
+438// return true;
+439// }
+440// }
+441//</editor-fold>
+442//TODO - likely need to change the split... not sure if this will work for CPE with special chars
+443if (text == null) {
+444return false;
+445 }
+446final String[] words = text.split("[\\s_-]");
+447final List<String> list = new ArrayList<String>();
+448 String tempWord = null;
+449for (String word : words) {
+450/*
+451 single letter words should be concatenated with the next word.
+452 so { "m", "core", "sample" } -> { "mcore", "sample" }
+453 */
+454if (tempWord != null) {
+455 list.add(tempWord + word);
+456 tempWord = null;
+457 } elseif (word.length() <= 2) {
+458 tempWord = word;
+459 } else {
+460 list.add(word);
+461 }
+462 }
+463if (tempWord != null && !list.isEmpty()) {
+464final String tmp = list.get(list.size() - 1) + tempWord;
+465 list.add(tmp);
+466 }
+467boolean contains = true;
+468for (String word : list) {
+469 contains &= ec.containsUsedString(word);
+470 }
+471return contains;
472 }
473474/**
-475 * Returns the name of this analyzer.
+475 * Analyzes a dependency and attempts to determine if there are any CPE identifiers for this dependency.476 *
-477 * @return the name of this analyzer.
-478 */
-479 @Override
-480public String getName() {
-481return"CPE Analyzer";
-482 }
-483
-484/**
-485 * Returns true because this analyzer supports all dependency types.
-486 *
-487 * @param extension the file extension of the dependency being analyzed.
-488 * @return true.
-489 */
-490 @Override
-491publicboolean supportsExtension(String extension) {
-492returntrue;
-493 }
-494
-495/**
-496 * Returns the analysis phase that this analyzer should run in.
-497 *
-498 * @return the analysis phase that this analyzer should run in.
-499 */
-500 @Override
-501publicAnalysisPhase getAnalysisPhase() {
-502return AnalysisPhase.IDENTIFIER_ANALYSIS;
-503 }
-504
-505/**
-506 * Opens the CPE Lucene Index.
-507 *
-508 * @throws Exception is thrown if there is an issue opening the index.
-509 */
-510 @Override
-511publicvoid initialize() throws Exception {
-512this.open();
-513 }
-514
-515/**
-516 * Retrieves a list of CPE values from the CveDB based on the vendor and product passed in. The list is then
-517 * validated to find only CPEs that are valid for the given dependency. It is possible that the CPE identified is a
-518 * best effort "guess" based on the vendor, product, and version information.
-519 *
-520 * @param dependency the Dependency being analyzed
-521 * @param vendor the vendor for the CPE being analyzed
-522 * @param product the product for the CPE being analyzed
-523 * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
-524 */
-525privatevoid determineIdentifiers(Dependency dependency, String vendor, String product) throws UnsupportedEncodingException {
-526final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
-527DependencyVersion bestGuess = newDependencyVersion("-");
-528Confidence bestGuessConf = null;
-529final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
-530for (Confidence conf : Confidence.values()) {
-531for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
-532finalDependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
-533if (evVer == null) {
-534continue;
-535 }
-536for (VulnerableSoftware vs : cpes) {
-537DependencyVersion dbVer;
-538if (vs.getRevision() != null && !vs.getRevision().isEmpty()) {
-539 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + "." + vs.getRevision());
-540 } else {
-541 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
-542 }
-543if (dbVer == null//special case, no version specified - everything is vulnerable
-544 || evVer.equals(dbVer)) { //yeah! exact match
-545final String url = String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(vs.getName(), "UTF-8"));
-546finalIdentifierMatch match = newIdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
-547 collected.add(match);
-548 } else {
-549//TODO the following isn't quite right is it? need to think about this guessing game a bit more.
-550if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
-551 && evVer.matchesAtLeastThreeLevels(dbVer)) {
-552if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
-553if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
-554 bestGuess = dbVer;
-555 bestGuessConf = conf;
-556 }
-557 }
-558 }
-559 }
-560 }
-561if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
-562if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) {
-563 bestGuess = evVer;
-564 bestGuessConf = conf;
-565 }
-566 }
-567 }
-568 }
-569final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
-570final String url = null; //String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(cpeName, "UTF-8"));
-571if (bestGuessConf == null) {
-572 bestGuessConf = Confidence.LOW;
-573 }
-574finalIdentifierMatch match = newIdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf);
-575 collected.add(match);
-576
-577 Collections.sort(collected);
-578finalIdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence();
-579finalConfidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence();
-580for (IdentifierMatch m : collected) {
-581if (bestIdentifierQuality.equals(m.getConfidence())
-582 && bestEvidenceQuality.equals(m.getEvidenceConfidence())) {
-583finalIdentifier i = m.getIdentifier();
-584if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) {
-585 i.setConfidence(Confidence.LOW);
-586 } else {
-587 i.setConfidence(bestEvidenceQuality);
-588 }
-589 dependency.addIdentifier(i);
-590 }
-591 }
-592 }
-593
-594/**
-595 * The confidence whether the identifier is an exact match, or a best guess.
-596 */
-597private enum IdentifierConfidence {
-598
-599/**
-600 * An exact match for the CPE.
+477 * @param dependency The Dependency to analyze.
+478 * @param engine The analysis engine
+479 * @throws AnalysisException is thrown if there is an issue analyzing the dependency.
+480 */
+481 @Override
+482publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
+483try {
+484 determineCPE(dependency);
+485 } catch (CorruptIndexException ex) {
+486thrownewAnalysisException("CPE Index is corrupt.", ex);
+487 } catch (IOException ex) {
+488thrownewAnalysisException("Failure opening the CPE Index.", ex);
+489 } catch (ParseException ex) {
+490thrownewAnalysisException("Unable to parse the generated Lucene query for this dependency.", ex);
+491 }
+492 }
+493
+494/**
+495 * Retrieves a list of CPE values from the CveDB based on the vendor and product passed in. The list is then
+496 * validated to find only CPEs that are valid for the given dependency. It is possible that the CPE identified is a
+497 * best effort "guess" based on the vendor, product, and version information.
+498 *
+499 * @param dependency the Dependency being analyzed
+500 * @param vendor the vendor for the CPE being analyzed
+501 * @param product the product for the CPE being analyzed
+502 * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
+503 */
+504privatevoid determineIdentifiers(Dependency dependency, String vendor, String product) throws UnsupportedEncodingException {
+505final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
+506DependencyVersion bestGuess = newDependencyVersion("-");
+507Confidence bestGuessConf = null;
+508final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
+509for (Confidence conf : Confidence.values()) {
+510for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
+511finalDependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
+512if (evVer == null) {
+513continue;
+514 }
+515for (VulnerableSoftware vs : cpes) {
+516DependencyVersion dbVer;
+517if (vs.getRevision() != null && !vs.getRevision().isEmpty()) {
+518 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + "." + vs.getRevision());
+519 } else {
+520 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
+521 }
+522if (dbVer == null//special case, no version specified - everything is vulnerable
+523 || evVer.equals(dbVer)) { //yeah! exact match
+524final String url = String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(vs.getName(), "UTF-8"));
+525finalIdentifierMatch match = newIdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
+526 collected.add(match);
+527 } else {
+528//TODO the following isn't quite right is it? need to think about this guessing game a bit more.
+529if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
+530 && evVer.matchesAtLeastThreeLevels(dbVer)) {
+531if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
+532if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
+533 bestGuess = dbVer;
+534 bestGuessConf = conf;
+535 }
+536 }
+537 }
+538 }
+539 }
+540if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
+541if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) {
+542 bestGuess = evVer;
+543 bestGuessConf = conf;
+544 }
+545 }
+546 }
+547 }
+548final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
+549final String url = null; //String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(cpeName, "UTF-8"));
+550if (bestGuessConf == null) {
+551 bestGuessConf = Confidence.LOW;
+552 }
+553finalIdentifierMatch match = newIdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf);
+554 collected.add(match);
+555
+556 Collections.sort(collected);
+557finalIdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence();
+558finalConfidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence();
+559for (IdentifierMatch m : collected) {
+560if (bestIdentifierQuality.equals(m.getConfidence())
+561 && bestEvidenceQuality.equals(m.getEvidenceConfidence())) {
+562finalIdentifier i = m.getIdentifier();
+563if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) {
+564 i.setConfidence(Confidence.LOW);
+565 } else {
+566 i.setConfidence(bestEvidenceQuality);
+567 }
+568 dependency.addIdentifier(i);
+569 }
+570 }
+571 }
+572
+573/**
+574 * The confidence whether the identifier is an exact match, or a best guess.
+575 */
+576private enum IdentifierConfidence {
+577
+578/**
+579 * An exact match for the CPE.
+580 */
+581 EXACT_MATCH,
+582/**
+583 * A best guess for the CPE.
+584 */
+585 BEST_GUESS
+586 }
+587
+588/**
+589 * A simple object to hold an identifier and carry information about the confidence in the identifier.
+590 */
+591privatestaticclassIdentifierMatchimplements Comparable<IdentifierMatch> {
+592
+593/**
+594 * Constructs an IdentifierMatch.
+595 *
+596 * @param type the type of identifier (such as CPE)
+597 * @param value the value of the identifier
+598 * @param url the URL of the identifier
+599 * @param identifierConfidence the confidence in the identifier: best guess or exact match
+600 * @param evidenceConfidence the confidence of the evidence used to find the identifier601 */
-602 EXACT_MATCH,
-603/**
-604 * A best guess for the CPE.
-605 */
-606 BEST_GUESS
-607 }
-608
-609/**
-610 * A simple object to hold an identifier and carry information about the confidence in the identifier.
-611 */
-612privatestaticclassIdentifierMatchimplements Comparable<IdentifierMatch> {
-613
-614/**
-615 * Constructs an IdentifierMatch.
-616 *
-617 * @param type the type of identifier (such as CPE)
-618 * @param value the value of the identifier
-619 * @param url the URL of the identifier
-620 * @param identifierConfidence the confidence in the identifier: best guess or exact match
-621 * @param evidenceConfidence the confidence of the evidence used to find the identifier
-622 */
-623IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) {
-624this.identifier = newIdentifier(type, value, url);
-625this.confidence = identifierConfidence;
-626this.evidenceConfidence = evidenceConfidence;
-627 }
-628//<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier">
-629/**
-630 * The confidence in the evidence used to identify this match.
-631 */
-632privateConfidence evidenceConfidence;
-633
-634/**
-635 * Get the value of evidenceConfidence
-636 *
-637 * @return the value of evidenceConfidence
-638 */
-639publicConfidence getEvidenceConfidence() {
-640return evidenceConfidence;
-641 }
-642
-643/**
-644 * Set the value of evidenceConfidence
-645 *
-646 * @param evidenceConfidence new value of evidenceConfidence
-647 */
-648publicvoid setEvidenceConfidence(Confidence evidenceConfidence) {
-649this.evidenceConfidence = evidenceConfidence;
-650 }
-651/**
-652 * The confidence whether this is an exact match, or a best guess.
-653 */
-654privateIdentifierConfidence confidence;
-655
-656/**
-657 * Get the value of confidence.
-658 *
-659 * @return the value of confidence
-660 */
-661publicIdentifierConfidence getConfidence() {
-662return confidence;
-663 }
-664
-665/**
-666 * Set the value of confidence.
-667 *
-668 * @param confidence new value of confidence
-669 */
-670publicvoid setConfidence(IdentifierConfidence confidence) {
-671this.confidence = confidence;
-672 }
-673/**
-674 * The CPE identifier.
-675 */
-676privateIdentifier identifier;
-677
-678/**
-679 * Get the value of identifier.
-680 *
-681 * @return the value of identifier
-682 */
-683publicIdentifier getIdentifier() {
-684return identifier;
-685 }
-686
-687/**
-688 * Set the value of identifier.
-689 *
-690 * @param identifier new value of identifier
-691 */
-692publicvoid setIdentifier(Identifier identifier) {
-693this.identifier = identifier;
-694 }
-695//</editor-fold>
-696//<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals">
-697
-698/**
-699 * Standard toString() implementation.
-700 *
-701 * @return the string representation of the object
-702 */
-703 @Override
-704public String toString() {
-705return"IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence
-706 + ", confidence=" + confidence + ", identifier=" + identifier + '}';
-707 }
-708
-709/**
-710 * Standard hashCode() implementation.
-711 *
-712 * @return the hashCode
-713 */
-714 @Override
-715publicint hashCode() {
-716int hash = 5;
-717 hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0);
-718 hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0);
-719 hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0);
-720return hash;
-721 }
-722
-723/**
-724 * Standard equals implementation.
-725 *
-726 * @param obj the object to compare
-727 * @return true if the objects are equal, otherwise false
-728 */
-729 @Override
-730publicboolean equals(Object obj) {
-731if (obj == null) {
-732return false;
-733 }
-734if (getClass() != obj.getClass()) {
-735return false;
-736 }
-737finalIdentifierMatch other = (IdentifierMatch) obj;
-738if (this.evidenceConfidence != other.evidenceConfidence) {
-739return false;
-740 }
-741if (this.confidence != other.confidence) {
-742return false;
-743 }
-744if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) {
-745return false;
-746 }
-747returntrue;
-748 }
-749//</editor-fold>
-750
-751/**
-752 * Standard implementation of compareTo that compares identifier confidence, evidence confidence, and then the
-753 * identifier.
-754 *
-755 * @param o the IdentifierMatch to compare to
-756 * @return the natural ordering of IdentifierMatch
-757 */
-758 @Override
-759publicint compareTo(IdentifierMatch o) {
-760int conf = this.confidence.compareTo(o.confidence);
-761if (conf == 0) {
-762 conf = this.evidenceConfidence.compareTo(o.evidenceConfidence);
-763if (conf == 0) {
-764 conf = identifier.compareTo(o.identifier);
-765 }
-766 }
-767return conf;
-768 }
-769 }
-770 }
+602IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) {
+603this.identifier = newIdentifier(type, value, url);
+604this.confidence = identifierConfidence;
+605this.evidenceConfidence = evidenceConfidence;
+606 }
+607//<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier">
+608/**
+609 * The confidence in the evidence used to identify this match.
+610 */
+611privateConfidence evidenceConfidence;
+612
+613/**
+614 * Get the value of evidenceConfidence
+615 *
+616 * @return the value of evidenceConfidence
+617 */
+618publicConfidence getEvidenceConfidence() {
+619return evidenceConfidence;
+620 }
+621
+622/**
+623 * Set the value of evidenceConfidence
+624 *
+625 * @param evidenceConfidence new value of evidenceConfidence
+626 */
+627publicvoid setEvidenceConfidence(Confidence evidenceConfidence) {
+628this.evidenceConfidence = evidenceConfidence;
+629 }
+630/**
+631 * The confidence whether this is an exact match, or a best guess.
+632 */
+633privateIdentifierConfidence confidence;
+634
+635/**
+636 * Get the value of confidence.
+637 *
+638 * @return the value of confidence
+639 */
+640publicIdentifierConfidence getConfidence() {
+641return confidence;
+642 }
+643
+644/**
+645 * Set the value of confidence.
+646 *
+647 * @param confidence new value of confidence
+648 */
+649publicvoid setConfidence(IdentifierConfidence confidence) {
+650this.confidence = confidence;
+651 }
+652/**
+653 * The CPE identifier.
+654 */
+655privateIdentifier identifier;
+656
+657/**
+658 * Get the value of identifier.
+659 *
+660 * @return the value of identifier
+661 */
+662publicIdentifier getIdentifier() {
+663return identifier;
+664 }
+665
+666/**
+667 * Set the value of identifier.
+668 *
+669 * @param identifier new value of identifier
+670 */
+671publicvoid setIdentifier(Identifier identifier) {
+672this.identifier = identifier;
+673 }
+674//</editor-fold>
+675//<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals">
+676
+677/**
+678 * Standard toString() implementation.
+679 *
+680 * @return the string representation of the object
+681 */
+682 @Override
+683public String toString() {
+684return"IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence
+685 + ", confidence=" + confidence + ", identifier=" + identifier + '}';
+686 }
+687
+688/**
+689 * Standard hashCode() implementation.
+690 *
+691 * @return the hashCode
+692 */
+693 @Override
+694publicint hashCode() {
+695int hash = 5;
+696 hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0);
+697 hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0);
+698 hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0);
+699return hash;
+700 }
+701
+702/**
+703 * Standard equals implementation.
+704 *
+705 * @param obj the object to compare
+706 * @return true if the objects are equal, otherwise false
+707 */
+708 @Override
+709publicboolean equals(Object obj) {
+710if (obj == null) {
+711return false;
+712 }
+713if (getClass() != obj.getClass()) {
+714return false;
+715 }
+716finalIdentifierMatch other = (IdentifierMatch) obj;
+717if (this.evidenceConfidence != other.evidenceConfidence) {
+718return false;
+719 }
+720if (this.confidence != other.confidence) {
+721return false;
+722 }
+723if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) {
+724return false;
+725 }
+726returntrue;
+727 }
+728//</editor-fold>
+729
+730/**
+731 * Standard implementation of compareTo that compares identifier confidence, evidence confidence, and then the
+732 * identifier.
+733 *
+734 * @param o the IdentifierMatch to compare to
+735 * @return the natural ordering of IdentifierMatch
+736 */
+737 @Override
+738publicint compareTo(IdentifierMatch o) {
+739int conf = this.confidence.compareTo(o.confidence);
+740if (conf == 0) {
+741 conf = this.evidenceConfidence.compareTo(o.evidenceConfidence);
+742if (conf == 0) {
+743 conf = identifier.compareTo(o.identifier);
+744 }
+745 }
+746return conf;
+747 }
+748 }
+749 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html
index 6b3864989..6385c3980 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html
@@ -25,17 +25,17 @@
17 */18package org.owasp.dependencycheck.analyzer;
19
-20import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
-21import java.io.File;
-22import java.util.HashSet;
-23import java.util.Iterator;
-24import java.util.ListIterator;
-25import java.util.Set;
-26import java.util.logging.Level;
-27import java.util.logging.Logger;
-28import java.util.regex.Matcher;
-29import java.util.regex.Pattern;
-30import org.owasp.dependencycheck.Engine;
+20import java.io.File;
+21import java.util.HashSet;
+22import java.util.Iterator;
+23import java.util.ListIterator;
+24import java.util.Set;
+25import java.util.logging.Level;
+26import java.util.logging.Logger;
+27import java.util.regex.Matcher;
+28import java.util.regex.Pattern;
+29import org.owasp.dependencycheck.Engine;
+30import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
31import org.owasp.dependencycheck.dependency.Dependency;
32import org.owasp.dependencycheck.dependency.Identifier;
33import org.owasp.dependencycheck.utils.DependencyVersion;
@@ -66,357 +66,334 @@
58//</editor-fold>59//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">60/**
-61 * The set of file extensions supported by this analyzer.
+61 * The name of the analyzer.62 */
-63privatestaticfinal Set<String> EXTENSIONS = null;
+63privatestaticfinal String ANALYZER_NAME = "Dependency Bundling Analyzer";
64/**
-65 * The name of the analyzer.
+65 * The phase that this analyzer is intended to run in.66 */
-67privatestaticfinal String ANALYZER_NAME = "Dependency Bundling Analyzer";
-68/**
-69 * The phase that this analyzer is intended to run in.
-70 */
-71privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_FINDING_ANALYSIS;
-72
-73/**
-74 * Returns a list of file EXTENSIONS supported by this analyzer.
-75 *
-76 * @return a list of file EXTENSIONS supported by this analyzer.
-77 */
-78public Set<String> getSupportedExtensions() {
-79return EXTENSIONS;
-80 }
-81
-82/**
-83 * Returns the name of the analyzer.
-84 *
-85 * @return the name of the analyzer.
-86 */
-87public String getName() {
-88return ANALYZER_NAME;
-89 }
-90
-91/**
-92 * Returns whether or not this analyzer can process the given extension.
-93 *
-94 * @param extension the file extension to test for support
-95 * @return whether or not the specified file extension is supported by this analyzer.
-96 */
-97publicboolean supportsExtension(String extension) {
-98returntrue;
-99 }
-100
-101/**
-102 * Returns the phase that the analyzer is intended to run in.
-103 *
-104 * @return the phase that the analyzer is intended to run in.
-105 */
-106publicAnalysisPhase getAnalysisPhase() {
-107return ANALYSIS_PHASE;
-108 }
-109//</editor-fold>
-110
-111/**
-112 * Analyzes a set of dependencies. If they have been found to have the same base path and the same set of
-113 * identifiers they are likely related. The related dependencies are bundled into a single reportable item.
-114 *
-115 * @param ignore this analyzer ignores the dependency being analyzed
-116 * @param engine the engine that is scanning the dependencies
-117 * @throws AnalysisException is thrown if there is an error reading the JAR file.
-118 */
-119 @Override
-120publicvoid analyze(Dependency ignore, Engine engine) throws AnalysisException {
-121if (!analyzed) {
-122 analyzed = true;
-123final Set<Dependency> dependenciesToRemove = new HashSet<Dependency>();
-124final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator();
-125//for (Dependency nextDependency : engine.getDependencies()) {
-126while (mainIterator.hasNext()) {
-127finalDependency dependency = mainIterator.next();
-128if (mainIterator.hasNext()) {
-129final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
-130while (subIterator.hasNext()) {
-131finalDependency nextDependency = subIterator.next();
-132if (isShadedJar(dependency, nextDependency)) {
-133if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
-134 dependenciesToRemove.add(dependency);
-135 } else {
-136 dependenciesToRemove.add(nextDependency);
-137 }
-138 } elseif (hashesMatch(dependency, nextDependency)) {
-139if (isCore(dependency, nextDependency)) {
-140 mergeDependencies(dependency, nextDependency, dependenciesToRemove);
-141 } else {
-142 mergeDependencies(nextDependency, dependency, dependenciesToRemove);
-143 }
-144 } elseif (cpeIdentifiersMatch(dependency, nextDependency)
-145 && hasSameBasePath(dependency, nextDependency)
-146 && fileNameMatch(dependency, nextDependency)) {
-147
-148if (isCore(dependency, nextDependency)) {
-149 mergeDependencies(dependency, nextDependency, dependenciesToRemove);
-150 } else {
-151 mergeDependencies(nextDependency, dependency, dependenciesToRemove);
-152 }
-153 }
-154 }
-155 }
-156 }
-157//removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
-158// was difficult because of the inner iterator.
-159for (Dependency d : dependenciesToRemove) {
-160 engine.getDependencies().remove(d);
-161 }
-162 }
-163 }
-164
-165/**
-166 * Adds the relatedDependency to the dependency's related dependencies.
-167 *
-168 * @param dependency the main dependency
-169 * @param relatedDependency a collection of dependencies to be removed from the main analysis loop, this is the
-170 * source of dependencies to remove
-171 * @param dependenciesToRemove a collection of dependencies that will be removed from the main analysis loop, this
-172 * function adds to this collection
-173 */
-174privatevoid mergeDependencies(finalDependency dependency, finalDependency relatedDependency, final Set<Dependency> dependenciesToRemove) {
-175 dependency.addRelatedDependency(relatedDependency);
-176final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator();
-177while (i.hasNext()) {
-178 dependency.addRelatedDependency(i.next());
-179 i.remove();
-180 }
-181 dependenciesToRemove.add(relatedDependency);
-182 }
-183
-184/**
-185 * Attempts to trim a maven repo to a common base path. This is typically
-186 * [drive]\[repo_location]\repository\[path1]\[path2].
-187 *
-188 * @param path the path to trim
-189 * @return a string representing the base path.
-190 */
-191private String getBaseRepoPath(final String path) {
-192int pos = path.indexOf("repository" + File.separator) + 11;
-193if (pos < 0) {
-194return path;
-195 }
-196int tmp = path.indexOf(File.separator, pos);
-197if (tmp <= 0) {
-198return path;
-199 }
-200if (tmp > 0) {
-201 pos = tmp + 1;
-202 }
-203 tmp = path.indexOf(File.separator, pos);
-204if (tmp > 0) {
-205 pos = tmp + 1;
-206 }
-207return path.substring(0, pos);
-208 }
-209
-210/**
-211 * Returns true if the file names (and version if it exists) of the two dependencies are sufficiently similar.
-212 *
-213 * @param dependency1 a dependency2 to compare
-214 * @param dependency2 a dependency2 to compare
-215 * @return true if the identifiers in the two supplied dependencies are equal
-216 */
-217privateboolean fileNameMatch(Dependency dependency1, Dependency dependency2) {
-218if (dependency1 == null || dependency1.getFileName() == null
-219 || dependency2 == null || dependency2.getFileName() == null) {
-220return false;
-221 }
-222 String fileName1 = dependency1.getFileName();
-223 String fileName2 = dependency2.getFileName();
-224
-225//update to deal with archive analyzer, the starting name maybe the same
-226// as this is incorrectly looking at the starting path
-227final File one = new File(fileName1);
-228final File two = new File(fileName2);
-229final String oneParent = one.getParent();
-230final String twoParent = two.getParent();
-231if (oneParent != null) {
-232if (oneParent.equals(twoParent)) {
-233 fileName1 = one.getName();
-234 fileName2 = two.getName();
-235 } else {
-236return false;
-237 }
-238 } elseif (twoParent != null) {
-239return false;
-240 }
-241
-242//version check
-243finalDependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1);
-244finalDependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2);
-245if (version1 != null && version2 != null) {
-246if (!version1.equals(version2)) {
-247return false;
-248 }
+67privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_FINDING_ANALYSIS;
+68
+69/**
+70 * Returns the name of the analyzer.
+71 *
+72 * @return the name of the analyzer.
+73 */
+74public String getName() {
+75return ANALYZER_NAME;
+76 }
+77
+78/**
+79 * Returns the phase that the analyzer is intended to run in.
+80 *
+81 * @return the phase that the analyzer is intended to run in.
+82 */
+83publicAnalysisPhase getAnalysisPhase() {
+84return ANALYSIS_PHASE;
+85 }
+86//</editor-fold>
+87
+88/**
+89 * Analyzes a set of dependencies. If they have been found to have the same base path and the same set of
+90 * identifiers they are likely related. The related dependencies are bundled into a single reportable item.
+91 *
+92 * @param ignore this analyzer ignores the dependency being analyzed
+93 * @param engine the engine that is scanning the dependencies
+94 * @throws AnalysisException is thrown if there is an error reading the JAR file.
+95 */
+96 @Override
+97publicvoid analyze(Dependency ignore, Engine engine) throws AnalysisException {
+98if (!analyzed) {
+99 analyzed = true;
+100final Set<Dependency> dependenciesToRemove = new HashSet<Dependency>();
+101final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator();
+102//for (Dependency nextDependency : engine.getDependencies()) {
+103while (mainIterator.hasNext()) {
+104finalDependency dependency = mainIterator.next();
+105if (mainIterator.hasNext()) {
+106final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
+107while (subIterator.hasNext()) {
+108finalDependency nextDependency = subIterator.next();
+109if (isShadedJar(dependency, nextDependency)) {
+110if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
+111 dependenciesToRemove.add(dependency);
+112 } else {
+113 dependenciesToRemove.add(nextDependency);
+114 }
+115 } elseif (hashesMatch(dependency, nextDependency)) {
+116if (isCore(dependency, nextDependency)) {
+117 mergeDependencies(dependency, nextDependency, dependenciesToRemove);
+118 } else {
+119 mergeDependencies(nextDependency, dependency, dependenciesToRemove);
+120 }
+121 } elseif (cpeIdentifiersMatch(dependency, nextDependency)
+122 && hasSameBasePath(dependency, nextDependency)
+123 && fileNameMatch(dependency, nextDependency)) {
+124
+125if (isCore(dependency, nextDependency)) {
+126 mergeDependencies(dependency, nextDependency, dependenciesToRemove);
+127 } else {
+128 mergeDependencies(nextDependency, dependency, dependenciesToRemove);
+129 }
+130 }
+131 }
+132 }
+133 }
+134//removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
+135// was difficult because of the inner iterator.
+136for (Dependency d : dependenciesToRemove) {
+137 engine.getDependencies().remove(d);
+138 }
+139 }
+140 }
+141
+142/**
+143 * Adds the relatedDependency to the dependency's related dependencies.
+144 *
+145 * @param dependency the main dependency
+146 * @param relatedDependency a collection of dependencies to be removed from the main analysis loop, this is the
+147 * source of dependencies to remove
+148 * @param dependenciesToRemove a collection of dependencies that will be removed from the main analysis loop, this
+149 * function adds to this collection
+150 */
+151privatevoid mergeDependencies(finalDependency dependency, finalDependency relatedDependency, final Set<Dependency> dependenciesToRemove) {
+152 dependency.addRelatedDependency(relatedDependency);
+153final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator();
+154while (i.hasNext()) {
+155 dependency.addRelatedDependency(i.next());
+156 i.remove();
+157 }
+158 dependenciesToRemove.add(relatedDependency);
+159 }
+160
+161/**
+162 * Attempts to trim a maven repo to a common base path. This is typically
+163 * [drive]\[repo_location]\repository\[path1]\[path2].
+164 *
+165 * @param path the path to trim
+166 * @return a string representing the base path.
+167 */
+168private String getBaseRepoPath(final String path) {
+169int pos = path.indexOf("repository" + File.separator) + 11;
+170if (pos < 0) {
+171return path;
+172 }
+173int tmp = path.indexOf(File.separator, pos);
+174if (tmp <= 0) {
+175return path;
+176 }
+177if (tmp > 0) {
+178 pos = tmp + 1;
+179 }
+180 tmp = path.indexOf(File.separator, pos);
+181if (tmp > 0) {
+182 pos = tmp + 1;
+183 }
+184return path.substring(0, pos);
+185 }
+186
+187/**
+188 * Returns true if the file names (and version if it exists) of the two dependencies are sufficiently similar.
+189 *
+190 * @param dependency1 a dependency2 to compare
+191 * @param dependency2 a dependency2 to compare
+192 * @return true if the identifiers in the two supplied dependencies are equal
+193 */
+194privateboolean fileNameMatch(Dependency dependency1, Dependency dependency2) {
+195if (dependency1 == null || dependency1.getFileName() == null
+196 || dependency2 == null || dependency2.getFileName() == null) {
+197return false;
+198 }
+199 String fileName1 = dependency1.getFileName();
+200 String fileName2 = dependency2.getFileName();
+201
+202//update to deal with archive analyzer, the starting name maybe the same
+203// as this is incorrectly looking at the starting path
+204final File one = new File(fileName1);
+205final File two = new File(fileName2);
+206final String oneParent = one.getParent();
+207final String twoParent = two.getParent();
+208if (oneParent != null) {
+209if (oneParent.equals(twoParent)) {
+210 fileName1 = one.getName();
+211 fileName2 = two.getName();
+212 } else {
+213return false;
+214 }
+215 } elseif (twoParent != null) {
+216return false;
+217 }
+218
+219//version check
+220finalDependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1);
+221finalDependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2);
+222if (version1 != null && version2 != null) {
+223if (!version1.equals(version2)) {
+224return false;
+225 }
+226 }
+227
+228//filename check
+229final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1);
+230final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2);
+231if (match1.find() && match2.find()) {
+232return match1.group().equals(match2.group());
+233 }
+234
+235return false;
+236 }
+237
+238/**
+239 * Returns true if the CPE identifiers in the two supplied dependencies are equal.
+240 *
+241 * @param dependency1 a dependency2 to compare
+242 * @param dependency2 a dependency2 to compare
+243 * @return true if the identifiers in the two supplied dependencies are equal
+244 */
+245privateboolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) {
+246if (dependency1 == null || dependency1.getIdentifiers() == null
+247 || dependency2 == null || dependency2.getIdentifiers() == null) {
+248return false;
249 }
-250
-251//filename check
-252final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1);
-253final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2);
-254if (match1.find() && match2.find()) {
-255return match1.group().equals(match2.group());
-256 }
-257
-258return false;
-259 }
-260
-261/**
-262 * Returns true if the CPE identifiers in the two supplied dependencies are equal.
-263 *
-264 * @param dependency1 a dependency2 to compare
-265 * @param dependency2 a dependency2 to compare
-266 * @return true if the identifiers in the two supplied dependencies are equal
-267 */
-268privateboolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) {
-269if (dependency1 == null || dependency1.getIdentifiers() == null
-270 || dependency2 == null || dependency2.getIdentifiers() == null) {
-271return false;
-272 }
-273boolean matches = false;
-274int cpeCount1 = 0;
-275int cpeCount2 = 0;
-276for (Identifier i : dependency1.getIdentifiers()) {
-277if ("cpe".equals(i.getType())) {
-278 cpeCount1 += 1;
-279 }
-280 }
-281for (Identifier i : dependency2.getIdentifiers()) {
-282if ("cpe".equals(i.getType())) {
-283 cpeCount2 += 1;
-284 }
-285 }
-286if (cpeCount1 > 0 && cpeCount1 == cpeCount2) {
-287for (Identifier i : dependency1.getIdentifiers()) {
-288 matches |= dependency2.getIdentifiers().contains(i);
-289if (!matches) {
-290break;
-291 }
-292 }
-293 }
-294if (LogUtils.isVerboseLoggingEnabled()) {
-295final String msg = String.format("IdentifiersMatch=%s (%s, %s)", matches, dependency1.getFileName(), dependency2.getFileName());
-296 Logger.getLogger(DependencyBundlingAnalyzer.class.getName()).log(Level.FINE, msg);
-297 }
-298return matches;
-299 }
-300
-301/**
-302 * Determines if the two dependencies have the same base path.
-303 *
-304 * @param dependency1 a Dependency object
-305 * @param dependency2 a Dependency object
-306 * @return true if the base paths of the dependencies are identical
-307 */
-308privateboolean hasSameBasePath(Dependency dependency1, Dependency dependency2) {
-309if (dependency1 == null || dependency2 == null) {
-310return false;
+250boolean matches = false;
+251int cpeCount1 = 0;
+252int cpeCount2 = 0;
+253for (Identifier i : dependency1.getIdentifiers()) {
+254if ("cpe".equals(i.getType())) {
+255 cpeCount1 += 1;
+256 }
+257 }
+258for (Identifier i : dependency2.getIdentifiers()) {
+259if ("cpe".equals(i.getType())) {
+260 cpeCount2 += 1;
+261 }
+262 }
+263if (cpeCount1 > 0 && cpeCount1 == cpeCount2) {
+264for (Identifier i : dependency1.getIdentifiers()) {
+265 matches |= dependency2.getIdentifiers().contains(i);
+266if (!matches) {
+267break;
+268 }
+269 }
+270 }
+271if (LogUtils.isVerboseLoggingEnabled()) {
+272final String msg = String.format("IdentifiersMatch=%s (%s, %s)", matches, dependency1.getFileName(), dependency2.getFileName());
+273 Logger.getLogger(DependencyBundlingAnalyzer.class.getName()).log(Level.FINE, msg);
+274 }
+275return matches;
+276 }
+277
+278/**
+279 * Determines if the two dependencies have the same base path.
+280 *
+281 * @param dependency1 a Dependency object
+282 * @param dependency2 a Dependency object
+283 * @return true if the base paths of the dependencies are identical
+284 */
+285privateboolean hasSameBasePath(Dependency dependency1, Dependency dependency2) {
+286if (dependency1 == null || dependency2 == null) {
+287return false;
+288 }
+289final File lFile = new File(dependency1.getFilePath());
+290 String left = lFile.getParent();
+291final File rFile = new File(dependency2.getFilePath());
+292 String right = rFile.getParent();
+293if (left == null) {
+294return right == null;
+295 }
+296if (left.equalsIgnoreCase(right)) {
+297returntrue;
+298 }
+299if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) {
+300 left = getBaseRepoPath(left);
+301 right = getBaseRepoPath(right);
+302 }
+303if (left.equalsIgnoreCase(right)) {
+304returntrue;
+305 }
+306//new code
+307for (Dependency child : dependency2.getRelatedDependencies()) {
+308if (hasSameBasePath(dependency1, child)) {
+309returntrue;
+310 }
311 }
-312final File lFile = new File(dependency1.getFilePath());
-313 String left = lFile.getParent();
-314final File rFile = new File(dependency2.getFilePath());
-315 String right = rFile.getParent();
-316if (left == null) {
-317return right == null;
-318 }
-319if (left.equalsIgnoreCase(right)) {
-320returntrue;
-321 }
-322if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) {
-323 left = getBaseRepoPath(left);
-324 right = getBaseRepoPath(right);
-325 }
-326if (left.equalsIgnoreCase(right)) {
-327returntrue;
-328 }
-329//new code
-330for (Dependency child : dependency2.getRelatedDependencies()) {
-331if (hasSameBasePath(dependency1, child)) {
-332returntrue;
-333 }
-334 }
-335return false;
-336 }
-337
-338/**
-339 * This is likely a very broken attempt at determining if the 'left' dependency is the 'core' library in comparison
-340 * to the 'right' library.
-341 *
-342 * @param left the dependency to test
-343 * @param right the dependency to test against
-344 * @return a boolean indicating whether or not the left dependency should be considered the "core" version.
-345 */
-346boolean isCore(Dependency left, Dependency right) {
-347final String leftName = left.getFileName().toLowerCase();
-348final String rightName = right.getFileName().toLowerCase();
-349
-350finalboolean returnVal;
-351if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+")
-352 || rightName.contains("core") && !leftName.contains("core")
-353 || rightName.contains("kernel") && !leftName.contains("kernel")) {
-354 returnVal = false;
-355 } elseif (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+")
-356 || !rightName.contains("core") && leftName.contains("core")
-357 || !rightName.contains("kernel") && leftName.contains("kernel")) {
-358 returnVal = true;
-359 } else {
-360/*
-361 * considered splitting the names up and comparing the components,
-362 * but decided that the file name length should be sufficient as the
-363 * "core" component, if this follows a normal naming protocol should
-364 * be shorter:
-365 * axis2-saaj-1.4.1.jar
-366 * axis2-1.4.1.jar <-----
-367 * axis2-kernal-1.4.1.jar
-368 */
-369 returnVal = leftName.length() <= rightName.length();
-370 }
-371if (LogUtils.isVerboseLoggingEnabled()) {
-372final String msg = String.format("IsCore=%s (%s, %s)", returnVal, left.getFileName(), right.getFileName());
-373 Logger.getLogger(DependencyBundlingAnalyzer.class.getName()).log(Level.FINE, msg);
-374 }
-375return returnVal;
-376 }
-377
-378/**
-379 * Compares the SHA1 hashes of two dependencies to determine if they are equal.
-380 *
-381 * @param dependency1 a dependency object to compare
-382 * @param dependency2 a dependency object to compare
-383 * @return true if the sha1 hashes of the two dependencies match; otherwise false
-384 */
-385privateboolean hashesMatch(Dependency dependency1, Dependency dependency2) {
-386if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) {
-387return false;
-388 }
-389return dependency1.getSha1sum().equals(dependency2.getSha1sum());
-390 }
-391
-392/**
-393 * Determines if the jar is shaded and the created pom.xml identified the same CPE as the jar - if so, the pom.xml
-394 * dependency should be removed.
-395 *
-396 * @param dependency a dependency to check
-397 * @param nextDependency another dependency to check
-398 * @return true if on of the dependencies is a pom.xml and the identifiers between the two collections match;
-399 * otherwise false
-400 */
-401privateboolean isShadedJar(Dependency dependency, Dependency nextDependency) {
-402final String mainName = dependency.getFileName().toLowerCase();
-403final String nextName = nextDependency.getFileName().toLowerCase();
-404if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) {
-405return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers());
-406 } elseif (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) {
-407return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers());
-408 }
-409return false;
-410 }
-411 }
+312return false;
+313 }
+314
+315/**
+316 * This is likely a very broken attempt at determining if the 'left' dependency is the 'core' library in comparison
+317 * to the 'right' library.
+318 *
+319 * @param left the dependency to test
+320 * @param right the dependency to test against
+321 * @return a boolean indicating whether or not the left dependency should be considered the "core" version.
+322 */
+323boolean isCore(Dependency left, Dependency right) {
+324final String leftName = left.getFileName().toLowerCase();
+325final String rightName = right.getFileName().toLowerCase();
+326
+327finalboolean returnVal;
+328if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+")
+329 || rightName.contains("core") && !leftName.contains("core")
+330 || rightName.contains("kernel") && !leftName.contains("kernel")) {
+331 returnVal = false;
+332 } elseif (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+")
+333 || !rightName.contains("core") && leftName.contains("core")
+334 || !rightName.contains("kernel") && leftName.contains("kernel")) {
+335 returnVal = true;
+336 } else {
+337/*
+338 * considered splitting the names up and comparing the components,
+339 * but decided that the file name length should be sufficient as the
+340 * "core" component, if this follows a normal naming protocol should
+341 * be shorter:
+342 * axis2-saaj-1.4.1.jar
+343 * axis2-1.4.1.jar <-----
+344 * axis2-kernal-1.4.1.jar
+345 */
+346 returnVal = leftName.length() <= rightName.length();
+347 }
+348if (LogUtils.isVerboseLoggingEnabled()) {
+349final String msg = String.format("IsCore=%s (%s, %s)", returnVal, left.getFileName(), right.getFileName());
+350 Logger.getLogger(DependencyBundlingAnalyzer.class.getName()).log(Level.FINE, msg);
+351 }
+352return returnVal;
+353 }
+354
+355/**
+356 * Compares the SHA1 hashes of two dependencies to determine if they are equal.
+357 *
+358 * @param dependency1 a dependency object to compare
+359 * @param dependency2 a dependency object to compare
+360 * @return true if the sha1 hashes of the two dependencies match; otherwise false
+361 */
+362privateboolean hashesMatch(Dependency dependency1, Dependency dependency2) {
+363if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) {
+364return false;
+365 }
+366return dependency1.getSha1sum().equals(dependency2.getSha1sum());
+367 }
+368
+369/**
+370 * Determines if the jar is shaded and the created pom.xml identified the same CPE as the jar - if so, the pom.xml
+371 * dependency should be removed.
+372 *
+373 * @param dependency a dependency to check
+374 * @param nextDependency another dependency to check
+375 * @return true if on of the dependencies is a pom.xml and the identifiers between the two collections match;
+376 * otherwise false
+377 */
+378privateboolean isShadedJar(Dependency dependency, Dependency nextDependency) {
+379final String mainName = dependency.getFileName().toLowerCase();
+380final String nextName = nextDependency.getFileName().toLowerCase();
+381if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) {
+382return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers());
+383 } elseif (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) {
+384return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers());
+385 }
+386return false;
+387 }
+388 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html
index db906af33..ada0c4d73 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html
@@ -52,329 +52,306 @@
4445//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">46/**
-47 * The set of file extensions supported by this analyzer.
+47 * The name of the analyzer.48 */
-49privatestaticfinal Set<String> EXTENSIONS = null;
+49privatestaticfinal String ANALYZER_NAME = "False Positive Analyzer";
50/**
-51 * The name of the analyzer.
+51 * The phase that this analyzer is intended to run in.52 */
-53privatestaticfinal String ANALYZER_NAME = "False Positive Analyzer";
-54/**
-55 * The phase that this analyzer is intended to run in.
-56 */
-57privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_IDENTIFIER_ANALYSIS;
-58
-59/**
-60 * Returns a list of file EXTENSIONS supported by this analyzer.
-61 *
-62 * @return a list of file EXTENSIONS supported by this analyzer.
-63 */
-64public Set<String> getSupportedExtensions() {
-65return EXTENSIONS;
-66 }
-67
-68/**
-69 * Returns the name of the analyzer.
-70 *
-71 * @return the name of the analyzer.
-72 */
-73public String getName() {
-74return ANALYZER_NAME;
-75 }
-76
-77/**
-78 * Returns whether or not this analyzer can process the given extension.
-79 *
-80 * @param extension the file extension to test for support
-81 * @return whether or not the specified file extension is supported by this analyzer.
-82 */
-83publicboolean supportsExtension(String extension) {
-84returntrue;
-85 }
-86
-87/**
-88 * Returns the phase that the analyzer is intended to run in.
-89 *
-90 * @return the phase that the analyzer is intended to run in.
-91 */
-92publicAnalysisPhase getAnalysisPhase() {
-93return ANALYSIS_PHASE;
-94 }
-95//</editor-fold>
-96
-97/**
-98 * Analyzes the dependencies and removes bad/incorrect CPE associations based on various heuristics.
-99 *
-100 * @param dependency the dependency to analyze.
-101 * @param engine the engine that is scanning the dependencies
-102 * @throws AnalysisException is thrown if there is an error reading the JAR file.
-103 */
-104 @Override
-105publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-106 removeJreEntries(dependency);
-107 removeBadMatches(dependency);
-108 removeWrongVersionMatches(dependency);
-109 removeSpuriousCPE(dependency);
-110 addFalseNegativeCPEs(dependency);
-111 }
-112
-113/**
-114 * <p>
-115 * Intended to remove spurious CPE entries. By spurious we mean duplicate, less specific CPE entries.</p>
-116 * <p>
-117 * Example:</p>
-118 * <code>
-119 * cpe:/a:some-vendor:some-product
-120 * cpe:/a:some-vendor:some-product:1.5
-121 * cpe:/a:some-vendor:some-product:1.5.2
-122 * </code>
-123 * <p>
-124 * Should be trimmed to:</p>
-125 * <code>
-126 * cpe:/a:some-vendor:some-product:1.5.2
-127 * </code>
-128 *
-129 * @param dependency the dependency being analyzed
-130 */
-131 @SuppressWarnings("null")
-132privatevoid removeSpuriousCPE(Dependency dependency) {
-133final List<Identifier> ids = new ArrayList<Identifier>();
-134 ids.addAll(dependency.getIdentifiers());
-135 Collections.sort(ids);
-136final ListIterator<Identifier> mainItr = ids.listIterator();
-137while (mainItr.hasNext()) {
-138finalIdentifier currentId = mainItr.next();
-139finalVulnerableSoftware currentCpe = parseCpe(currentId.getType(), currentId.getValue());
-140if (currentCpe == null) {
-141continue;
-142 }
-143final ListIterator<Identifier> subItr = ids.listIterator(mainItr.nextIndex());
-144while (subItr.hasNext()) {
-145finalIdentifier nextId = subItr.next();
-146finalVulnerableSoftware nextCpe = parseCpe(nextId.getType(), nextId.getValue());
-147if (nextCpe == null) {
-148continue;
-149 }
-150//TODO fix the version problem below
-151if (currentCpe.getVendor().equals(nextCpe.getVendor())) {
-152if (currentCpe.getProduct().equals(nextCpe.getProduct())) {
-153// see if one is contained in the other.. remove the contained one from dependency.getIdentifier
-154final String currentVersion = currentCpe.getVersion();
-155final String nextVersion = nextCpe.getVersion();
-156if (currentVersion == null && nextVersion == null) {
-157//how did we get here?
-158 Logger.getLogger(FalsePositiveAnalyzer.class
-159 .getName()).log(Level.FINE, "currentVersion and nextVersion are both null?");
-160 } elseif (currentVersion == null && nextVersion != null) {
-161 dependency.getIdentifiers().remove(currentId);
-162 } elseif (nextVersion == null && currentVersion != null) {
-163 dependency.getIdentifiers().remove(nextId);
-164 } elseif (currentVersion.length() < nextVersion.length()) {
-165if (nextVersion.startsWith(currentVersion) || "-".equals(currentVersion)) {
-166 dependency.getIdentifiers().remove(currentId);
-167 }
-168 } else {
-169if (currentVersion.startsWith(nextVersion) || "-".equals(nextVersion)) {
-170 dependency.getIdentifiers().remove(nextId);
-171 }
-172 }
-173 }
-174 }
-175 }
-176 }
-177 }
-178/**
-179 * Regex to identify core java libraries and a few other commonly misidentified ones.
-180 */
-181publicstaticfinal Pattern CORE_JAVA = Pattern.compile("^cpe:/a:(sun|oracle|ibm):(j2[ems]e|"
-182 + "java(_platfrom_micro_edition|_runtime_environment|_se|virtual_machine|se_development_kit|fx)?|"
-183 + "jdk|jre|jsf|jsse)($|:.*)");
-184/**
-185 * Regex to identify core java library files. This is currently incomplete.
-186 */
-187publicstaticfinal Pattern CORE_FILES = Pattern.compile("^((alt[-])?rt|jsf[-].*|jsse|jfxrt|jfr|jce|javaws|deploy|charsets)\\.jar$");
-188
-189/**
-190 * Removes any CPE entries for the JDK/JRE unless the filename ends with rt.jar
-191 *
-192 * @param dependency the dependency to remove JRE CPEs from
-193 */
-194privatevoid removeJreEntries(Dependency dependency) {
-195final Set<Identifier> identifiers = dependency.getIdentifiers();
-196final Iterator<Identifier> itr = identifiers.iterator();
-197while (itr.hasNext()) {
-198finalIdentifier i = itr.next();
-199final Matcher coreCPE = CORE_JAVA.matcher(i.getValue());
-200final Matcher coreFiles = CORE_FILES.matcher(dependency.getFileName());
-201if (coreCPE.matches() && !coreFiles.matches()) {
-202 itr.remove();
-203 }
+53privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_IDENTIFIER_ANALYSIS;
+54
+55/**
+56 * Returns the name of the analyzer.
+57 *
+58 * @return the name of the analyzer.
+59 */
+60public String getName() {
+61return ANALYZER_NAME;
+62 }
+63
+64/**
+65 * Returns the phase that the analyzer is intended to run in.
+66 *
+67 * @return the phase that the analyzer is intended to run in.
+68 */
+69publicAnalysisPhase getAnalysisPhase() {
+70return ANALYSIS_PHASE;
+71 }
+72//</editor-fold>
+73
+74/**
+75 * Analyzes the dependencies and removes bad/incorrect CPE associations based on various heuristics.
+76 *
+77 * @param dependency the dependency to analyze.
+78 * @param engine the engine that is scanning the dependencies
+79 * @throws AnalysisException is thrown if there is an error reading the JAR file.
+80 */
+81 @Override
+82publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
+83 removeJreEntries(dependency);
+84 removeBadMatches(dependency);
+85 removeWrongVersionMatches(dependency);
+86 removeSpuriousCPE(dependency);
+87 addFalseNegativeCPEs(dependency);
+88 }
+89
+90/**
+91 * <p>
+92 * Intended to remove spurious CPE entries. By spurious we mean duplicate, less specific CPE entries.</p>
+93 * <p>
+94 * Example:</p>
+95 * <code>
+96 * cpe:/a:some-vendor:some-product
+97 * cpe:/a:some-vendor:some-product:1.5
+98 * cpe:/a:some-vendor:some-product:1.5.2
+99 * </code>
+100 * <p>
+101 * Should be trimmed to:</p>
+102 * <code>
+103 * cpe:/a:some-vendor:some-product:1.5.2
+104 * </code>
+105 *
+106 * @param dependency the dependency being analyzed
+107 */
+108 @SuppressWarnings("null")
+109privatevoid removeSpuriousCPE(Dependency dependency) {
+110final List<Identifier> ids = new ArrayList<Identifier>();
+111 ids.addAll(dependency.getIdentifiers());
+112 Collections.sort(ids);
+113final ListIterator<Identifier> mainItr = ids.listIterator();
+114while (mainItr.hasNext()) {
+115finalIdentifier currentId = mainItr.next();
+116finalVulnerableSoftware currentCpe = parseCpe(currentId.getType(), currentId.getValue());
+117if (currentCpe == null) {
+118continue;
+119 }
+120final ListIterator<Identifier> subItr = ids.listIterator(mainItr.nextIndex());
+121while (subItr.hasNext()) {
+122finalIdentifier nextId = subItr.next();
+123finalVulnerableSoftware nextCpe = parseCpe(nextId.getType(), nextId.getValue());
+124if (nextCpe == null) {
+125continue;
+126 }
+127//TODO fix the version problem below
+128if (currentCpe.getVendor().equals(nextCpe.getVendor())) {
+129if (currentCpe.getProduct().equals(nextCpe.getProduct())) {
+130// see if one is contained in the other.. remove the contained one from dependency.getIdentifier
+131final String currentVersion = currentCpe.getVersion();
+132final String nextVersion = nextCpe.getVersion();
+133if (currentVersion == null && nextVersion == null) {
+134//how did we get here?
+135 Logger.getLogger(FalsePositiveAnalyzer.class
+136 .getName()).log(Level.FINE, "currentVersion and nextVersion are both null?");
+137 } elseif (currentVersion == null && nextVersion != null) {
+138 dependency.getIdentifiers().remove(currentId);
+139 } elseif (nextVersion == null && currentVersion != null) {
+140 dependency.getIdentifiers().remove(nextId);
+141 } elseif (currentVersion.length() < nextVersion.length()) {
+142if (nextVersion.startsWith(currentVersion) || "-".equals(currentVersion)) {
+143 dependency.getIdentifiers().remove(currentId);
+144 }
+145 } else {
+146if (currentVersion.startsWith(nextVersion) || "-".equals(nextVersion)) {
+147 dependency.getIdentifiers().remove(nextId);
+148 }
+149 }
+150 }
+151 }
+152 }
+153 }
+154 }
+155/**
+156 * Regex to identify core java libraries and a few other commonly misidentified ones.
+157 */
+158publicstaticfinal Pattern CORE_JAVA = Pattern.compile("^cpe:/a:(sun|oracle|ibm):(j2[ems]e|"
+159 + "java(_platfrom_micro_edition|_runtime_environment|_se|virtual_machine|se_development_kit|fx)?|"
+160 + "jdk|jre|jsf|jsse)($|:.*)");
+161/**
+162 * Regex to identify core java library files. This is currently incomplete.
+163 */
+164publicstaticfinal Pattern CORE_FILES = Pattern.compile("^((alt[-])?rt|jsf[-].*|jsse|jfxrt|jfr|jce|javaws|deploy|charsets)\\.jar$");
+165
+166/**
+167 * Removes any CPE entries for the JDK/JRE unless the filename ends with rt.jar
+168 *
+169 * @param dependency the dependency to remove JRE CPEs from
+170 */
+171privatevoid removeJreEntries(Dependency dependency) {
+172final Set<Identifier> identifiers = dependency.getIdentifiers();
+173final Iterator<Identifier> itr = identifiers.iterator();
+174while (itr.hasNext()) {
+175finalIdentifier i = itr.next();
+176final Matcher coreCPE = CORE_JAVA.matcher(i.getValue());
+177final Matcher coreFiles = CORE_FILES.matcher(dependency.getFileName());
+178if (coreCPE.matches() && !coreFiles.matches()) {
+179 itr.remove();
+180 }
+181
+182//replacecd with the regex above.
+183// if (("cpe:/a:sun:java".equals(i.getValue())
+184// || "cpe:/a:oracle:java".equals(i.getValue())
+185// || "cpe:/a:ibm:java".equals(i.getValue())
+186// || "cpe:/a:sun:j2se".equals(i.getValue())
+187// || "cpe:/a:oracle:j2se".equals(i.getValue())
+188// || i.getValue().startsWith("cpe:/a:sun:java:")
+189// || i.getValue().startsWith("cpe:/a:sun:j2se:")
+190// || i.getValue().startsWith("cpe:/a:sun:java:jre")
+191// || i.getValue().startsWith("cpe:/a:sun:java:jdk")
+192// || i.getValue().startsWith("cpe:/a:sun:java_se")
+193// || i.getValue().startsWith("cpe:/a:oracle:java_se")
+194// || i.getValue().startsWith("cpe:/a:oracle:java:")
+195// || i.getValue().startsWith("cpe:/a:oracle:j2se:")
+196// || i.getValue().startsWith("cpe:/a:oracle:jre")
+197// || i.getValue().startsWith("cpe:/a:oracle:jdk")
+198// || i.getValue().startsWith("cpe:/a:ibm:java:"))
+199// && !dependency.getFileName().toLowerCase().endsWith("rt.jar")) {
+200// itr.remove();
+201// }
+202 }
+203 }
204
-205//replacecd with the regex above.
-206// if (("cpe:/a:sun:java".equals(i.getValue())
-207// || "cpe:/a:oracle:java".equals(i.getValue())
-208// || "cpe:/a:ibm:java".equals(i.getValue())
-209// || "cpe:/a:sun:j2se".equals(i.getValue())
-210// || "cpe:/a:oracle:j2se".equals(i.getValue())
-211// || i.getValue().startsWith("cpe:/a:sun:java:")
-212// || i.getValue().startsWith("cpe:/a:sun:j2se:")
-213// || i.getValue().startsWith("cpe:/a:sun:java:jre")
-214// || i.getValue().startsWith("cpe:/a:sun:java:jdk")
-215// || i.getValue().startsWith("cpe:/a:sun:java_se")
-216// || i.getValue().startsWith("cpe:/a:oracle:java_se")
-217// || i.getValue().startsWith("cpe:/a:oracle:java:")
-218// || i.getValue().startsWith("cpe:/a:oracle:j2se:")
-219// || i.getValue().startsWith("cpe:/a:oracle:jre")
-220// || i.getValue().startsWith("cpe:/a:oracle:jdk")
-221// || i.getValue().startsWith("cpe:/a:ibm:java:"))
-222// && !dependency.getFileName().toLowerCase().endsWith("rt.jar")) {
-223// itr.remove();
-224// }
-225 }
-226 }
-227
-228/**
-229 * Parses a CPE string into an IndexEntry.
-230 *
-231 * @param type the type of identifier
-232 * @param value the cpe identifier to parse
-233 * @return an VulnerableSoftware object constructed from the identifier
-234 */
-235privateVulnerableSoftware parseCpe(String type, String value) {
-236if (!"cpe".equals(type)) {
-237returnnull;
-238 }
-239finalVulnerableSoftware cpe = newVulnerableSoftware();
-240try {
-241 cpe.parseName(value);
-242 } catch (UnsupportedEncodingException ex) {
-243 Logger.getLogger(FalsePositiveAnalyzer.class.getName()).log(Level.FINEST, null, ex);
-244returnnull;
-245 }
-246return cpe;
-247 }
-248
-249/**
-250 * Removes bad CPE matches for a dependency. Unfortunately, right now these are hard-coded patches for specific
-251 * problems identified when testing this on a LARGE volume of jar files.
-252 *
-253 * @param dependency the dependency to analyze
-254 */
-255privatevoid removeBadMatches(Dependency dependency) {
-256final Set<Identifier> identifiers = dependency.getIdentifiers();
-257final Iterator<Identifier> itr = identifiers.iterator();
-258
-259/* TODO - can we utilize the pom's groupid and artifactId to filter??? most of
-260 * these are due to low quality data. Other idea would be to say any CPE
-261 * found based on LOW confidence evidence should have a different CPE type? (this
-262 * might be a better solution then just removing the URL for "best-guess" matches).
-263 */
-264//Set<Evidence> groupId = dependency.getVendorEvidence().getEvidence("pom", "groupid");
-265//Set<Evidence> artifactId = dependency.getVendorEvidence().getEvidence("pom", "artifactid");
-266while (itr.hasNext()) {
-267finalIdentifier i = itr.next();
-268//TODO move this startswith expression to a configuration file?
-269if ("cpe".equals(i.getType())) {
-270if ((i.getValue().matches(".*c\\+\\+.*")
-271 || i.getValue().startsWith("cpe:/a:jquery:jquery")
-272 || i.getValue().startsWith("cpe:/a:prototypejs:prototype")
-273 || i.getValue().startsWith("cpe:/a:yahoo:yui")
-274 || i.getValue().startsWith("cpe:/a:file:file")
-275 || i.getValue().startsWith("cpe:/a:mozilla:mozilla")
-276 || i.getValue().startsWith("cpe:/a:cvs:cvs")
-277 || i.getValue().startsWith("cpe:/a:ftp:ftp")
-278 || i.getValue().startsWith("cpe:/a:ssh:ssh"))
-279 && (dependency.getFileName().toLowerCase().endsWith(".jar")
-280 || dependency.getFileName().toLowerCase().endsWith("pom.xml"))) {
-281 itr.remove();
-282 } elseif (i.getValue().startsWith("cpe:/a:apache:maven")
-283 && !dependency.getFileName().toLowerCase().matches("maven-core-[\\d\\.]+\\.jar")) {
-284 itr.remove();
-285 } elseif (i.getValue().startsWith("cpe:/a:m-core:m-core")
-286 && !dependency.getEvidenceUsed().containsUsedString("m-core")) {
-287 itr.remove();
-288 } elseif (i.getValue().startsWith("cpe:/a:jboss:jboss")
-289 && !dependency.getFileName().toLowerCase().matches("jboss-[\\d\\.]+(GA)?\\.jar")) {
-290 itr.remove();
+205/**
+206 * Parses a CPE string into an IndexEntry.
+207 *
+208 * @param type the type of identifier
+209 * @param value the cpe identifier to parse
+210 * @return an VulnerableSoftware object constructed from the identifier
+211 */
+212privateVulnerableSoftware parseCpe(String type, String value) {
+213if (!"cpe".equals(type)) {
+214returnnull;
+215 }
+216finalVulnerableSoftware cpe = newVulnerableSoftware();
+217try {
+218 cpe.parseName(value);
+219 } catch (UnsupportedEncodingException ex) {
+220 Logger.getLogger(FalsePositiveAnalyzer.class.getName()).log(Level.FINEST, null, ex);
+221returnnull;
+222 }
+223return cpe;
+224 }
+225
+226/**
+227 * Removes bad CPE matches for a dependency. Unfortunately, right now these are hard-coded patches for specific
+228 * problems identified when testing this on a LARGE volume of jar files.
+229 *
+230 * @param dependency the dependency to analyze
+231 */
+232privatevoid removeBadMatches(Dependency dependency) {
+233final Set<Identifier> identifiers = dependency.getIdentifiers();
+234final Iterator<Identifier> itr = identifiers.iterator();
+235
+236/* TODO - can we utilize the pom's groupid and artifactId to filter??? most of
+237 * these are due to low quality data. Other idea would be to say any CPE
+238 * found based on LOW confidence evidence should have a different CPE type? (this
+239 * might be a better solution then just removing the URL for "best-guess" matches).
+240 */
+241//Set<Evidence> groupId = dependency.getVendorEvidence().getEvidence("pom", "groupid");
+242//Set<Evidence> artifactId = dependency.getVendorEvidence().getEvidence("pom", "artifactid");
+243while (itr.hasNext()) {
+244finalIdentifier i = itr.next();
+245//TODO move this startswith expression to a configuration file?
+246if ("cpe".equals(i.getType())) {
+247if ((i.getValue().matches(".*c\\+\\+.*")
+248 || i.getValue().startsWith("cpe:/a:jquery:jquery")
+249 || i.getValue().startsWith("cpe:/a:prototypejs:prototype")
+250 || i.getValue().startsWith("cpe:/a:yahoo:yui")
+251 || i.getValue().startsWith("cpe:/a:file:file")
+252 || i.getValue().startsWith("cpe:/a:mozilla:mozilla")
+253 || i.getValue().startsWith("cpe:/a:cvs:cvs")
+254 || i.getValue().startsWith("cpe:/a:ftp:ftp")
+255 || i.getValue().startsWith("cpe:/a:ssh:ssh"))
+256 && (dependency.getFileName().toLowerCase().endsWith(".jar")
+257 || dependency.getFileName().toLowerCase().endsWith("pom.xml"))) {
+258 itr.remove();
+259 } elseif (i.getValue().startsWith("cpe:/a:apache:maven")
+260 && !dependency.getFileName().toLowerCase().matches("maven-core-[\\d\\.]+\\.jar")) {
+261 itr.remove();
+262 } elseif (i.getValue().startsWith("cpe:/a:m-core:m-core")
+263 && !dependency.getEvidenceUsed().containsUsedString("m-core")) {
+264 itr.remove();
+265 } elseif (i.getValue().startsWith("cpe:/a:jboss:jboss")
+266 && !dependency.getFileName().toLowerCase().matches("jboss-[\\d\\.]+(GA)?\\.jar")) {
+267 itr.remove();
+268 }
+269 }
+270 }
+271 }
+272
+273/**
+274 * Removes CPE matches for the wrong version of a dependency. Currently, this only covers Axis 1 & 2.
+275 *
+276 * @param dependency the dependency to analyze
+277 */
+278privatevoid removeWrongVersionMatches(Dependency dependency) {
+279final Set<Identifier> identifiers = dependency.getIdentifiers();
+280final Iterator<Identifier> itr = identifiers.iterator();
+281
+282final String fileName = dependency.getFileName();
+283if (fileName != null && fileName.contains("axis2")) {
+284while (itr.hasNext()) {
+285finalIdentifier i = itr.next();
+286if ("cpe".equals(i.getType())) {
+287final String cpe = i.getValue();
+288if (cpe != null && (cpe.startsWith("cpe:/a:apache:axis:") || "cpe:/a:apache:axis".equals(cpe))) {
+289 itr.remove();
+290 }
291 }
292 }
-293 }
-294 }
-295
-296/**
-297 * Removes CPE matches for the wrong version of a dependency. Currently, this only covers Axis 1 & 2.
-298 *
-299 * @param dependency the dependency to analyze
-300 */
-301privatevoid removeWrongVersionMatches(Dependency dependency) {
-302final Set<Identifier> identifiers = dependency.getIdentifiers();
-303final Iterator<Identifier> itr = identifiers.iterator();
-304
-305final String fileName = dependency.getFileName();
-306if (fileName != null && fileName.contains("axis2")) {
-307while (itr.hasNext()) {
-308finalIdentifier i = itr.next();
-309if ("cpe".equals(i.getType())) {
-310final String cpe = i.getValue();
-311if (cpe != null && (cpe.startsWith("cpe:/a:apache:axis:") || "cpe:/a:apache:axis".equals(cpe))) {
-312 itr.remove();
-313 }
-314 }
-315 }
-316 } elseif (fileName != null && fileName.contains("axis")) {
-317while (itr.hasNext()) {
-318finalIdentifier i = itr.next();
-319if ("cpe".equals(i.getType())) {
-320final String cpe = i.getValue();
-321if (cpe != null && (cpe.startsWith("cpe:/a:apache:axis2:") || "cpe:/a:apache:axis2".equals(cpe))) {
-322 itr.remove();
-323 }
-324 }
-325 }
-326 }
-327 }
-328
-329/**
-330 * There are some known CPE entries, specifically regarding sun and oracle products due to the acquisition and
-331 * changes in product names, that based on given evidence we can add the related CPE entries to ensure a complete
-332 * list of CVE entries.
-333 *
-334 * @param dependency the dependency being analyzed
-335 */
-336privatevoid addFalseNegativeCPEs(Dependency dependency) {
-337final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
-338while (itr.hasNext()) {
-339finalIdentifier i = itr.next();
-340if ("cpe".equals(i.getType()) && i.getValue() != null
-341 && (i.getValue().startsWith("cpe:/a:oracle:opensso:")
-342 || i.getValue().startsWith("cpe:/a:oracle:opensso_enterprise:")
-343 || i.getValue().startsWith("cpe:/a:sun:opensso_enterprise:")
-344 || i.getValue().startsWith("cpe:/a:sun:opensso:"))) {
-345final String newCpe = String.format("cpe:/a:sun:opensso_enterprise:%s", i.getValue().substring(22));
-346final String newCpe2 = String.format("cpe:/a:oracle:opensso_enterprise:%s", i.getValue().substring(22));
-347final String newCpe3 = String.format("cpe:/a:sun:opensso:%s", i.getValue().substring(22));
-348final String newCpe4 = String.format("cpe:/a:oracle:opensso:%s", i.getValue().substring(22));
-349try {
-350 dependency.addIdentifier("cpe",
-351 newCpe,
-352 String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe, "UTF-8")));
-353 dependency.addIdentifier("cpe",
-354 newCpe2,
-355 String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe2, "UTF-8")));
-356 dependency.addIdentifier("cpe",
-357 newCpe3,
-358 String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe3, "UTF-8")));
-359 dependency.addIdentifier("cpe",
-360 newCpe4,
-361 String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe4, "UTF-8")));
-362 } catch (UnsupportedEncodingException ex) {
-363 Logger.getLogger(FalsePositiveAnalyzer.class
-364 .getName()).log(Level.FINE, null, ex);
-365 }
-366 }
-367 }
-368 }
-369 }
+293 } elseif (fileName != null && fileName.contains("axis")) {
+294while (itr.hasNext()) {
+295finalIdentifier i = itr.next();
+296if ("cpe".equals(i.getType())) {
+297final String cpe = i.getValue();
+298if (cpe != null && (cpe.startsWith("cpe:/a:apache:axis2:") || "cpe:/a:apache:axis2".equals(cpe))) {
+299 itr.remove();
+300 }
+301 }
+302 }
+303 }
+304 }
+305
+306/**
+307 * There are some known CPE entries, specifically regarding sun and oracle products due to the acquisition and
+308 * changes in product names, that based on given evidence we can add the related CPE entries to ensure a complete
+309 * list of CVE entries.
+310 *
+311 * @param dependency the dependency being analyzed
+312 */
+313privatevoid addFalseNegativeCPEs(Dependency dependency) {
+314final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
+315while (itr.hasNext()) {
+316finalIdentifier i = itr.next();
+317if ("cpe".equals(i.getType()) && i.getValue() != null
+318 && (i.getValue().startsWith("cpe:/a:oracle:opensso:")
+319 || i.getValue().startsWith("cpe:/a:oracle:opensso_enterprise:")
+320 || i.getValue().startsWith("cpe:/a:sun:opensso_enterprise:")
+321 || i.getValue().startsWith("cpe:/a:sun:opensso:"))) {
+322final String newCpe = String.format("cpe:/a:sun:opensso_enterprise:%s", i.getValue().substring(22));
+323final String newCpe2 = String.format("cpe:/a:oracle:opensso_enterprise:%s", i.getValue().substring(22));
+324final String newCpe3 = String.format("cpe:/a:sun:opensso:%s", i.getValue().substring(22));
+325final String newCpe4 = String.format("cpe:/a:oracle:opensso:%s", i.getValue().substring(22));
+326try {
+327 dependency.addIdentifier("cpe",
+328 newCpe,
+329 String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe, "UTF-8")));
+330 dependency.addIdentifier("cpe",
+331 newCpe2,
+332 String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe2, "UTF-8")));
+333 dependency.addIdentifier("cpe",
+334 newCpe3,
+335 String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe3, "UTF-8")));
+336 dependency.addIdentifier("cpe",
+337 newCpe4,
+338 String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(newCpe4, "UTF-8")));
+339 } catch (UnsupportedEncodingException ex) {
+340 Logger.getLogger(FalsePositiveAnalyzer.class
+341 .getName()).log(Level.FINE, null, ex);
+342 }
+343 }
+344 }
+345 }
+346 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html
index 914bd0225..30099b545 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html
@@ -25,126 +25,102 @@
17 */18package org.owasp.dependencycheck.analyzer;
19
-20import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
-21import java.io.File;
-22import java.util.Set;
-23import org.owasp.dependencycheck.Engine;
-24import org.owasp.dependencycheck.dependency.Confidence;
-25import org.owasp.dependencycheck.dependency.Dependency;
-26import org.owasp.dependencycheck.utils.DependencyVersion;
-27import org.owasp.dependencycheck.utils.DependencyVersionUtil;
-28
-29/**
-30 *
-31 * Takes a dependency and analyzes the filename and determines the hashes.
-32 *
-33 * @author Jeremy Long <jeremy.long@owasp.org>
-34 */
-35publicclassFileNameAnalyzerextendsAbstractAnalyzerimplementsAnalyzer {
-36
-37//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
-38/**
-39 * The name of the analyzer.
-40 */
-41privatestaticfinal String ANALYZER_NAME = "File Name Analyzer";
-42/**
-43 * The phase that this analyzer is intended to run in.
-44 */
-45privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
+20import java.io.File;
+21import org.owasp.dependencycheck.Engine;
+22import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+23import org.owasp.dependencycheck.dependency.Confidence;
+24import org.owasp.dependencycheck.dependency.Dependency;
+25import org.owasp.dependencycheck.utils.DependencyVersion;
+26import org.owasp.dependencycheck.utils.DependencyVersionUtil;
+27
+28/**
+29 *
+30 * Takes a dependency and analyzes the filename and determines the hashes.
+31 *
+32 * @author Jeremy Long <jeremy.long@owasp.org>
+33 */
+34publicclassFileNameAnalyzerextendsAbstractAnalyzerimplementsAnalyzer {
+35
+36//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
+37/**
+38 * The name of the analyzer.
+39 */
+40privatestaticfinal String ANALYZER_NAME = "File Name Analyzer";
+41/**
+42 * The phase that this analyzer is intended to run in.
+43 */
+44privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
+4546/**
-47 * The set of file extensions supported by this analyzer.
-48 */
-49privatestaticfinal Set<String> EXTENSIONS = null;
-50
-51/**
-52 * Returns a list of file EXTENSIONS supported by this analyzer.
-53 *
-54 * @return a list of file EXTENSIONS supported by this analyzer.
-55 */
-56public Set<String> getSupportedExtensions() {
-57return EXTENSIONS;
-58 }
-59
-60/**
-61 * Returns the name of the analyzer.
-62 *
-63 * @return the name of the analyzer.
-64 */
-65public String getName() {
-66return ANALYZER_NAME;
-67 }
-68
-69/**
-70 * Returns whether or not this analyzer can process the given extension.
-71 *
-72 * @param extension the file extension to test for support.
-73 * @return whether or not the specified file extension is supported by this analyzer.
-74 */
-75publicboolean supportsExtension(String extension) {
-76returntrue;
-77 }
+47 * Returns the name of the analyzer.
+48 *
+49 * @return the name of the analyzer.
+50 */
+51public String getName() {
+52return ANALYZER_NAME;
+53 }
+54
+55/**
+56 * Returns the phase that the analyzer is intended to run in.
+57 *
+58 * @return the phase that the analyzer is intended to run in.
+59 */
+60publicAnalysisPhase getAnalysisPhase() {
+61return ANALYSIS_PHASE;
+62 }
+63//</editor-fold>
+64
+65/**
+66 * Collects information about the file name.
+67 *
+68 * @param dependency the dependency to analyze.
+69 * @param engine the engine that is scanning the dependencies
+70 * @throws AnalysisException is thrown if there is an error reading the JAR file.
+71 */
+72 @Override
+73publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
+74
+75//strip any path information that may get added by ArchiveAnalyzer, etc.
+76final File f = new File(dependency.getFileName());
+77 String fileName = f.getName();
78
-79/**
-80 * Returns the phase that the analyzer is intended to run in.
-81 *
-82 * @return the phase that the analyzer is intended to run in.
-83 */
-84publicAnalysisPhase getAnalysisPhase() {
-85return ANALYSIS_PHASE;
-86 }
-87//</editor-fold>
-88
-89/**
-90 * Collects information about the file name.
-91 *
-92 * @param dependency the dependency to analyze.
-93 * @param engine the engine that is scanning the dependencies
-94 * @throws AnalysisException is thrown if there is an error reading the JAR file.
-95 */
-96 @Override
-97publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-98
-99//strip any path information that may get added by ArchiveAnalyzer, etc.
-100final File f = new File(dependency.getFileName());
-101 String fileName = f.getName();
-102
-103//remove file extension
-104finalint pos = fileName.lastIndexOf(".");
-105if (pos > 0) {
-106 fileName = fileName.substring(0, pos);
-107 }
-108
-109//add version evidence
-110finalDependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
-111if (version != null) {
-112// If the version number is just a number like 2 or 23, reduce the confidence
-113// a shade. This should hopefully correct for cases like log4j.jar or
-114// struts2-core.jar
-115if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
-116 dependency.getVersionEvidence().addEvidence("file", "name",
-117 version.toString(), Confidence.MEDIUM);
-118 } else {
-119 dependency.getVersionEvidence().addEvidence("file", "name",
-120 version.toString(), Confidence.HIGHEST);
-121 }
-122 dependency.getVersionEvidence().addEvidence("file", "name",
-123 fileName, Confidence.MEDIUM);
-124 }
-125
-126//add as vendor and product evidence
-127if (fileName.contains("-")) {
-128 dependency.getProductEvidence().addEvidence("file", "name",
-129 fileName, Confidence.HIGHEST);
-130 dependency.getVendorEvidence().addEvidence("file", "name",
-131 fileName, Confidence.HIGHEST);
-132 } else {
-133 dependency.getProductEvidence().addEvidence("file", "name",
-134 fileName, Confidence.HIGH);
-135 dependency.getVendorEvidence().addEvidence("file", "name",
-136 fileName, Confidence.HIGH);
-137 }
-138 }
-139 }
+79//remove file extension
+80finalint pos = fileName.lastIndexOf(".");
+81if (pos > 0) {
+82 fileName = fileName.substring(0, pos);
+83 }
+84
+85//add version evidence
+86finalDependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
+87if (version != null) {
+88// If the version number is just a number like 2 or 23, reduce the confidence
+89// a shade. This should hopefully correct for cases like log4j.jar or
+90// struts2-core.jar
+91if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
+92 dependency.getVersionEvidence().addEvidence("file", "name",
+93 version.toString(), Confidence.MEDIUM);
+94 } else {
+95 dependency.getVersionEvidence().addEvidence("file", "name",
+96 version.toString(), Confidence.HIGHEST);
+97 }
+98 dependency.getVersionEvidence().addEvidence("file", "name",
+99 fileName, Confidence.MEDIUM);
+100 }
+101
+102//add as vendor and product evidence
+103if (fileName.contains("-")) {
+104 dependency.getProductEvidence().addEvidence("file", "name",
+105 fileName, Confidence.HIGHEST);
+106 dependency.getVendorEvidence().addEvidence("file", "name",
+107 fileName, Confidence.HIGHEST);
+108 } else {
+109 dependency.getProductEvidence().addEvidence("file", "name",
+110 fileName, Confidence.HIGH);
+111 dependency.getVendorEvidence().addEvidence("file", "name",
+112 fileName, Confidence.HIGH);
+113 }
+114 }
+115 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileTypeAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileTypeAnalyzer.html
new file mode 100644
index 000000000..7da10cb07
--- /dev/null
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileTypeAnalyzer.html
@@ -0,0 +1,47 @@
+
+
+
+FileTypeAnalyzer xref
+
+
+
+
+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) 2014 Jeremy Long. All Rights Reserved.
+17 */
+18package org.owasp.dependencycheck.analyzer;
+19
+20/**
+21 * An Analyzer that scans specific file types.
+22 *
+23 * @author Jeremy Long <jeremy.long@owasp.org>
+24 */
+25publicinterfaceFileTypeAnalyzerextendsAnalyzer {
+26
+27/**
+28 * Returns whether or not this analyzer can process the given extension.
+29 *
+30 * @param extension the file extension to test for support.
+31 * @return whether or not the specified file extension is supported by this analyzer.
+32 */
+33boolean supportsExtension(String extension);
+34 }
+
+
+
+
+
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html
index 68f9ee5bc..1f598a589 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html
@@ -25,11 +25,11 @@
17 */18package org.owasp.dependencycheck.analyzer;
19
-20import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
-21import java.util.ArrayList;
-22import java.util.Iterator;
-23import java.util.Set;
-24import org.owasp.dependencycheck.Engine;
+20import java.util.ArrayList;
+21import java.util.Iterator;
+22import java.util.Set;
+23import org.owasp.dependencycheck.Engine;
+24import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
25import org.owasp.dependencycheck.dependency.Confidence;
26import org.owasp.dependencycheck.dependency.Dependency;
27import org.owasp.dependencycheck.dependency.Evidence;
@@ -49,104 +49,83 @@
41 * The phase that this analyzer is intended to run in.42 */43privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_IDENTIFIER_ANALYSIS;
-44/**
-45 * The set of file extensions supported by this analyzer.
-46 */
-47privatestaticfinal Set<String> EXTENSIONS = null;
-48
-49/**
-50 * Returns a list of file EXTENSIONS supported by this analyzer.
-51 *
-52 * @return a list of file EXTENSIONS supported by this analyzer.
-53 */
-54public Set<String> getSupportedExtensions() {
-55return EXTENSIONS;
-56 }
-57
-58/**
-59 * Returns the name of the analyzer.
-60 *
-61 * @return the name of the analyzer.
-62 */
-63public String getName() {
-64return ANALYZER_NAME;
-65 }
-66
-67/**
-68 * Returns whether or not this analyzer can process the given extension.
+44
+45/**
+46 * Returns the name of the analyzer.
+47 *
+48 * @return the name of the analyzer.
+49 */
+50 @Override
+51public String getName() {
+52return ANALYZER_NAME;
+53 }
+54
+55/**
+56 * Returns the phase that the analyzer is intended to run in.
+57 *
+58 * @return the phase that the analyzer is intended to run in.
+59 */
+60 @Override
+61publicAnalysisPhase getAnalysisPhase() {
+62return ANALYSIS_PHASE;
+63 }
+64//</editor-fold>
+65
+66/**
+67 * The HintAnalyzer uses knowledge about a dependency to add additional information to help in identification of
+68 * identifiers or vulnerabilities.69 *
-70 * @param extension the file extension to test for support.
-71 * @return whether or not the specified file extension is supported by this analyzer.
-72 */
-73publicboolean supportsExtension(String extension) {
-74returntrue;
-75 }
-76
-77/**
-78 * Returns the phase that the analyzer is intended to run in.
-79 *
-80 * @return the phase that the analyzer is intended to run in.
-81 */
-82publicAnalysisPhase getAnalysisPhase() {
-83return ANALYSIS_PHASE;
-84 }
-85//</editor-fold>
-86
-87/**
-88 * The HintAnalyzer uses knowledge about a dependency to add additional information to help in identification of
-89 * identifiers or vulnerabilities.
-90 *
-91 * @param dependency The dependency being analyzed
-92 * @param engine The scanning engine
-93 * @throws AnalysisException is thrown if there is an exception analyzing the dependency.
-94 */
-95 @Override
-96publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-97finalEvidence springTest1 = newEvidence("Manifest",
-98"Implementation-Title",
-99"Spring Framework",
-100 Confidence.HIGH);
-101
-102finalEvidence springTest2 = newEvidence("Manifest",
-103"Implementation-Title",
-104"org.springframework.core",
-105 Confidence.HIGH);
-106
-107finalEvidence springTest3 = newEvidence("Manifest",
-108"Bundle-Vendor",
-109"SpringSource",
-110 Confidence.HIGH);
-111
-112 Set<Evidence> evidence = dependency.getProductEvidence().getEvidence();
-113if (evidence.contains(springTest1) || evidence.contains(springTest2)) {
-114 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH);
-115 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH);
-116 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
+70 * @param dependency The dependency being analyzed
+71 * @param engine The scanning engine
+72 * @throws AnalysisException is thrown if there is an exception analyzing the dependency.
+73 */
+74 @Override
+75publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
+76finalEvidence springTest1 = newEvidence("Manifest",
+77"Implementation-Title",
+78"Spring Framework",
+79 Confidence.HIGH);
+80
+81finalEvidence springTest2 = newEvidence("Manifest",
+82"Implementation-Title",
+83"org.springframework.core",
+84 Confidence.HIGH);
+85
+86finalEvidence springTest3 = newEvidence("Manifest",
+87"Bundle-Vendor",
+88"SpringSource",
+89 Confidence.HIGH);
+90
+91 Set<Evidence> evidence = dependency.getProductEvidence().getEvidence();
+92if (evidence.contains(springTest1) || evidence.contains(springTest2)) {
+93 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH);
+94 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH);
+95 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
+96 }
+97
+98 evidence = dependency.getVendorEvidence().getEvidence();
+99if (evidence.contains(springTest3)) {
+100 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH);
+101 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
+102 }
+103final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator();
+104final ArrayList<Evidence> newEntries = new ArrayList<Evidence>();
+105while (itr.hasNext()) {
+106finalEvidence e = itr.next();
+107if ("sun".equalsIgnoreCase(e.getValue(false))) {
+108finalEvidence newEvidence = newEvidence(e.getSource() + " (hint)", e.getName(), "oracle", e.getConfidence());
+109 newEntries.add(newEvidence);
+110 } elseif ("oracle".equalsIgnoreCase(e.getValue(false))) {
+111finalEvidence newEvidence = newEvidence(e.getSource() + " (hint)", e.getName(), "sun", e.getConfidence());
+112 newEntries.add(newEvidence);
+113 }
+114 }
+115for (Evidence e : newEntries) {
+116 dependency.getVendorEvidence().addEvidence(e);
117 }
118
-119 evidence = dependency.getVendorEvidence().getEvidence();
-120if (evidence.contains(springTest3)) {
-121 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH);
-122 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
-123 }
-124final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator();
-125final ArrayList<Evidence> newEntries = new ArrayList<Evidence>();
-126while (itr.hasNext()) {
-127finalEvidence e = itr.next();
-128if ("sun".equalsIgnoreCase(e.getValue(false))) {
-129finalEvidence newEvidence = newEvidence(e.getSource() + " (hint)", e.getName(), "oracle", e.getConfidence());
-130 newEntries.add(newEvidence);
-131 } elseif ("oracle".equalsIgnoreCase(e.getValue(false))) {
-132finalEvidence newEvidence = newEvidence(e.getSource() + " (hint)", e.getName(), "sun", e.getConfidence());
-133 newEntries.add(newEvidence);
-134 }
-135 }
-136for (Evidence e : newEntries) {
-137 dependency.getVendorEvidence().addEvidence(e);
-138 }
-139
-140 }
-141 }
+119 }
+120 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html
index e585380cb..3c2a3205d 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html
@@ -87,1292 +87,1308 @@
79 *80 * @author Jeremy Long <jeremy.long@owasp.org>81 */
-82publicclassJarAnalyzerextendsAbstractAnalyzerimplementsAnalyzer {
+82publicclassJarAnalyzerextendsAbstractFileTypeAnalyzer {
8384//<editor-fold defaultstate="collapsed" desc="Constants and Member Variables">85/**
-86 * The buffer size to use when extracting files from the archive.
+86 * The logger.87 */
-88privatestaticfinalint BUFFER_SIZE = 4096;
+88privatestaticfinal Logger LOGGER = Logger.getLogger(JarAnalyzer.class.getName());
89/**
-90 * The count of directories created during analysis. This is used for creating temporary directories.
+90 * The buffer size to use when extracting files from the archive.91 */
-92privatestaticint dirCount = 0;
+92privatestaticfinalint BUFFER_SIZE = 4096;
93/**
-94 * The system independent newline character.
+94 * The count of directories created during analysis. This is used for creating temporary directories.95 */
-96privatestaticfinal String NEWLINE = System.getProperty("line.separator");
+96privatestaticint dirCount = 0;
97/**
-98 * A list of values in the manifest to ignore as they only result in false positives.
+98 * The system independent newline character.99 */
-100privatestaticfinal Set<String> IGNORE_VALUES = newHashSet(
-101"Sun Java System Application Server");
-102/**
-103 * A list of elements in the manifest to ignore.
-104 */
-105privatestaticfinal Set<String> IGNORE_KEYS = newHashSet(
-106"built-by",
-107"created-by",
-108"builtby",
-109"createdby",
-110"build-jdk",
-111"buildjdk",
-112"ant-version",
-113"antversion",
-114"import-package",
-115"export-package",
-116"importpackage",
-117"exportpackage",
-118"sealed",
-119"manifest-version",
-120"archiver-version",
-121"manifestversion",
-122"archiverversion",
-123"classpath",
-124"class-path",
-125"tool",
-126"bundle-manifestversion",
-127"bundlemanifestversion",
-128"include-resource");
-129/**
-130 * item in some manifest, should be considered medium confidence.
-131 */
-132privatestaticfinal String BUNDLE_VERSION = "Bundle-Version"; //: 2.1.2
-133/**
-134 * item in some manifest, should be considered medium confidence.
-135 */
-136privatestaticfinal String BUNDLE_DESCRIPTION = "Bundle-Description"; //: Apache Struts 2
-137/**
-138 * item in some manifest, should be considered medium confidence.
-139 */
-140privatestaticfinal String BUNDLE_NAME = "Bundle-Name"; //: Struts 2 Core
-141/**
-142 * item in some manifest, should be considered medium confidence.
-143 */
-144privatestaticfinal String BUNDLE_VENDOR = "Bundle-Vendor"; //: Apache Software Foundation
-145/**
-146 * A pattern to detect HTML within text.
-147 */
-148privatestaticfinal Pattern HTML_DETECTION_PATTERN = Pattern.compile("\\<[a-z]+.*/?\\>", Pattern.CASE_INSENSITIVE);
-149/**
-150 * The unmarshaller used to parse the pom.xml from a JAR file.
-151 */
-152private Unmarshaller pomUnmarshaller;
-153//</editor-fold>
-154
-155/**
-156 * Constructs a new JarAnalyzer.
-157 */
-158publicJarAnalyzer() {
-159try {
-160final JAXBContext jaxbContext = JAXBContext.newInstance("org.owasp.dependencycheck.jaxb.pom.generated");
-161 pomUnmarshaller = jaxbContext.createUnmarshaller();
-162 } catch (JAXBException ex) { //guess we will just have a null pointer exception later...
-163 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.SEVERE, "Unable to load parser. See the log for more details.");
-164 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
-165 }
-166 }
-167//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
+100privatestaticfinal String NEWLINE = System.getProperty("line.separator");
+101/**
+102 * A list of values in the manifest to ignore as they only result in false positives.
+103 */
+104privatestaticfinal Set<String> IGNORE_VALUES = newHashSet(
+105"Sun Java System Application Server");
+106/**
+107 * A list of elements in the manifest to ignore.
+108 */
+109privatestaticfinal Set<String> IGNORE_KEYS = newHashSet(
+110"built-by",
+111"created-by",
+112"builtby",
+113"createdby",
+114"build-jdk",
+115"buildjdk",
+116"ant-version",
+117"antversion",
+118"dynamicimportpackage",
+119"dynamicimport-package",
+120"dynamic-importpackage",
+121"dynamic-import-package",
+122"import-package",
+123"ignore-package",
+124"export-package",
+125"importpackage",
+126"ignorepackage",
+127"exportpackage",
+128"sealed",
+129"manifest-version",
+130"archiver-version",
+131"manifestversion",
+132"archiverversion",
+133"classpath",
+134"class-path",
+135"tool",
+136"bundle-manifestversion",
+137"bundlemanifestversion",
+138"include-resource",
+139"embed-dependency",
+140"ipojo-components",
+141"ipojo-extension");
+142/**
+143 * item in some manifest, should be considered medium confidence.
+144 */
+145privatestaticfinal String BUNDLE_VERSION = "Bundle-Version"; //: 2.1.2
+146/**
+147 * item in some manifest, should be considered medium confidence.
+148 */
+149privatestaticfinal String BUNDLE_DESCRIPTION = "Bundle-Description"; //: Apache Struts 2
+150/**
+151 * item in some manifest, should be considered medium confidence.
+152 */
+153privatestaticfinal String BUNDLE_NAME = "Bundle-Name"; //: Struts 2 Core
+154/**
+155 * item in some manifest, should be considered medium confidence.
+156 */
+157privatestaticfinal String BUNDLE_VENDOR = "Bundle-Vendor"; //: Apache Software Foundation
+158/**
+159 * A pattern to detect HTML within text.
+160 */
+161privatestaticfinal Pattern HTML_DETECTION_PATTERN = Pattern.compile("\\<[a-z]+.*/?\\>", Pattern.CASE_INSENSITIVE);
+162/**
+163 * The unmarshaller used to parse the pom.xml from a JAR file.
+164 */
+165private Unmarshaller pomUnmarshaller;
+166//</editor-fold>
+167168/**
-169 * The name of the analyzer.
+169 * Constructs a new JarAnalyzer.170 */
-171privatestaticfinal String ANALYZER_NAME = "Jar Analyzer";
-172/**
-173 * The phase that this analyzer is intended to run in.
-174 */
-175privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
-176/**
-177 * The set of file extensions supported by this analyzer.
-178 */
-179privatestaticfinal Set<String> EXTENSIONS = newHashSet("jar", "war");
+171publicJarAnalyzer() {
+172try {
+173final JAXBContext jaxbContext = JAXBContext.newInstance("org.owasp.dependencycheck.jaxb.pom.generated");
+174 pomUnmarshaller = jaxbContext.createUnmarshaller();
+175 } catch (JAXBException ex) { //guess we will just have a null pointer exception later...
+176 LOGGER.log(Level.SEVERE, "Unable to load parser. See the log for more details.");
+177 LOGGER.log(Level.FINE, null, ex);
+178 }
+179 }
180
-181/**
-182 * Returns a list of file EXTENSIONS supported by this analyzer.
-183 *
-184 * @return a list of file EXTENSIONS supported by this analyzer.
-185 */
-186public Set<String> getSupportedExtensions() {
-187return EXTENSIONS;
-188 }
-189
+181//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
+182/**
+183 * The name of the analyzer.
+184 */
+185privatestaticfinal String ANALYZER_NAME = "Jar Analyzer";
+186/**
+187 * The phase that this analyzer is intended to run in.
+188 */
+189privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
190/**
-191 * Returns the name of the analyzer.
-192 *
-193 * @return the name of the analyzer.
-194 */
-195public String getName() {
-196return ANALYZER_NAME;
-197 }
-198
-199/**
-200 * Returns whether or not this analyzer can process the given extension.
-201 *
-202 * @param extension the file extension to test for support.
-203 * @return whether or not the specified file extension is supported by this analyzer.
-204 */
-205publicboolean supportsExtension(String extension) {
-206return EXTENSIONS.contains(extension);
-207 }
-208
-209/**
-210 * Returns the phase that the analyzer is intended to run in.
-211 *
-212 * @return the phase that the analyzer is intended to run in.
-213 */
-214publicAnalysisPhase getAnalysisPhase() {
-215return ANALYSIS_PHASE;
-216 }
-217//</editor-fold>
-218
-219/**
-220 * Loads a specified JAR file and collects information from the manifest and checksums to identify the correct CPE
-221 * information.
-222 *
-223 * @param dependency the dependency to analyze.
-224 * @param engine the engine that is scanning the dependencies
-225 * @throws AnalysisException is thrown if there is an error reading the JAR file.
-226 */
-227 @Override
-228publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-229try {
-230final ArrayList<ClassNameInformation> classNames = collectClassNames(dependency);
-231final String fileName = dependency.getFileName().toLowerCase();
-232if (classNames.isEmpty()
-233 && (fileName.endsWith("-sources.jar")
-234 || fileName.endsWith("-javadoc.jar")
-235 || fileName.endsWith("-src.jar")
-236 || fileName.endsWith("-doc.jar"))) {
-237 engine.getDependencies().remove(dependency);
-238 }
-239finalboolean hasManifest = parseManifest(dependency, classNames);
-240finalboolean hasPOM = analyzePOM(dependency, classNames, engine);
-241finalboolean addPackagesAsEvidence = !(hasManifest && hasPOM);
-242 analyzePackageNames(classNames, dependency, addPackagesAsEvidence);
-243 } catch (IOException ex) {
-244thrownewAnalysisException("Exception occurred reading the JAR file.", ex);
-245 }
-246 }
-247
-248/**
-249 * Attempts to find a pom.xml within the JAR file. If found it extracts information and adds it to the evidence.
-250 * This will attempt to interpolate the strings contained within the pom.properties if one exists.
-251 *
-252 * @param dependency the dependency being analyzed
-253 * @param classes a collection of class name information
-254 * @param engine the analysis engine, used to add additional dependencies
-255 * @throws AnalysisException is thrown if there is an exception parsing the pom
-256 * @return whether or not evidence was added to the dependency
-257 */
-258protectedboolean analyzePOM(Dependency dependency, ArrayList<ClassNameInformation> classes, Engine engine) throws AnalysisException {
-259boolean foundSomething = false;
-260final JarFile jar;
-261try {
-262 jar = new JarFile(dependency.getActualFilePath());
-263 } catch (IOException ex) {
-264final String msg = String.format("Unable to read JarFile '%s'.", dependency.getActualFilePath());
-265//final AnalysisException ax = new AnalysisException(msg, ex);
-266 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
-267 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
-268return false;
-269 }
-270 List<String> pomEntries;
-271try {
-272 pomEntries = retrievePomListing(jar);
-273 } catch (IOException ex) {
-274final String msg = String.format("Unable to read Jar file entries in '%s'.", dependency.getActualFilePath());
-275//final AnalysisException ax = new AnalysisException(msg, ex);
-276 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
-277 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, msg, ex);
-278return false;
-279 }
-280if (pomEntries.isEmpty()) {
-281return false;
-282 }
-283for (String path : pomEntries) {
-284Properties pomProperties = null;
-285try {
-286 pomProperties = retrievePomProperties(path, jar);
-287 } catch (IOException ex) {
-288 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINEST, "ignore this, failed reading a non-existent pom.properties", ex);
-289 }
-290Model pom = null;
-291try {
-292if (pomEntries.size() > 1) {
-293//extract POM to its own directory and add it as its own dependency
-294finalDependency newDependency = newDependency();
-295 pom = extractPom(path, jar, newDependency);
-296
-297final String displayPath = String.format("%s%s%s",
-298 dependency.getFilePath(),
-299 File.separator,
-300 path); //.replaceAll("[\\/]", File.separator));
-301final String displayName = String.format("%s%s%s",
-302 dependency.getFileName(),
-303 File.separator,
-304 path); //.replaceAll("[\\/]", File.separator));
-305
-306 newDependency.setFileName(displayName);
-307 newDependency.setFilePath(displayPath);
-308 addPomEvidence(newDependency, pom, pomProperties);
-309 engine.getDependencies().add(newDependency);
-310 Collections.sort(engine.getDependencies());
-311 } else {
-312 pom = retrievePom(path, jar);
-313 foundSomething |= setPomEvidence(dependency, pom, pomProperties, classes);
-314 }
-315 } catch (AnalysisException ex) {
-316final String msg = String.format("An error occured while analyzing '%s'.", dependency.getActualFilePath());
-317 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
-318 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, "", ex);
-319 }
-320 }
-321return foundSomething;
-322 }
-323
-324/**
-325 * Given a path to a pom.xml within a JarFile, this method attempts to load a sibling pom.properties if one exists.
-326 *
-327 * @param path the path to the pom.xml within the JarFile
-328 * @param jar the JarFile to load the pom.properties from
-329 * @return a Properties object or null if no pom.properties was found
-330 * @throws IOException thrown if there is an exception reading the pom.properties
-331 */
-332 @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "OS_OPEN_STREAM",
-333 justification = "The reader is closed by closing the zipEntry")
-334privateProperties retrievePomProperties(String path, final JarFile jar) throws IOException {
-335Properties pomProperties = null;
-336final String propPath = path.substring(0, path.length() - 7) + "pom.properies";
-337final ZipEntry propEntry = jar.getEntry(propPath);
-338if (propEntry != null) {
-339final Reader reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8");
-340 pomProperties = newProperties();
-341 pomProperties.load(reader);
-342 }
-343return pomProperties;
-344 }
-345
-346/**
-347 * Searches a JarFile for pom.xml entries and returns a listing of these entries.
-348 *
-349 * @param jar the JarFile to search
-350 * @return a list of pom.xml entries
-351 * @throws IOException thrown if there is an exception reading a JarEntryf
-352 */
-353private List<String> retrievePomListing(final JarFile jar) throws IOException {
-354final List<String> pomEntries = new ArrayList<String>();
-355final Enumeration<JarEntry> entries = jar.entries();
-356while (entries.hasMoreElements()) {
-357final JarEntry entry = entries.nextElement();
-358final String entryName = (new File(entry.getName())).getName().toLowerCase();
-359if (!entry.isDirectory() && "pom.xml".equals(entryName)) {
-360 pomEntries.add(entry.getName());
-361 }
-362 }
-363return pomEntries;
-364 }
-365
-366/**
-367 * Retrieves the specified POM from a jar file and converts it to a Model.
-368 *
-369 * @param path the path to the pom.xml file within the jar file
-370 * @param jar the jar file to extract the pom from
-371 * @param dependency the dependency being analyzed
-372 * @return returns the POM object
-373 * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
-374 * {@link org.owasp.dependencycheck.jaxb.pom.generated.Model} object
-375 */
-376privateModel extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException {
-377 InputStream input = null;
-378 FileOutputStream fos = null;
-379 BufferedOutputStream bos = null;
-380final File tmpDir = getNextTempDirectory();
-381final File file = new File(tmpDir, "pom.xml");
-382try {
-383final ZipEntry entry = jar.getEntry(path);
-384 input = jar.getInputStream(entry);
-385 fos = new FileOutputStream(file);
-386 bos = new BufferedOutputStream(fos, BUFFER_SIZE);
-387int count;
-388final byte data[] = new byte[BUFFER_SIZE];
-389while ((count = input.read(data, 0, BUFFER_SIZE)) != -1) {
-390 bos.write(data, 0, count);
-391 }
-392 bos.flush();
-393 dependency.setActualFilePath(file.getAbsolutePath());
-394 } catch (IOException ex) {
-395 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.SEVERE, null, ex);
-396 } finally {
-397 closeStream(bos);
-398 closeStream(fos);
-399 closeStream(input);
-400 }
-401Model model = null;
-402 FileInputStream fis = null;
-403try {
-404 fis = new FileInputStream(file);
-405final InputStreamReader reader = new InputStreamReader(fis, "UTF-8");
-406final InputSource xml = new InputSource(reader);
-407final SAXSource source = new SAXSource(xml);
-408 model = readPom(source);
-409 } catch (FileNotFoundException ex) {
-410final String msg = String.format("Unable to parse pom '%s' in jar '%s' (File Not Found)", path, jar.getName());
-411 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
-412 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
-413thrownewAnalysisException(ex);
-414 } catch (UnsupportedEncodingException ex) {
-415final String msg = String.format("Unable to parse pom '%s' in jar '%s' (IO Exception)", path, jar.getName());
-416 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
-417 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
-418thrownewAnalysisException(ex);
-419 } catch (AnalysisException ex) {
-420final String msg = String.format("Unable to parse pom '%s' in jar '%s'", path, jar.getName());
-421 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
-422 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
-423throw ex;
-424 } finally {
-425 closeStream(fis);
-426 }
-427return model;
-428 }
-429
-430/**
-431 * Silently closes an input stream ignoring errors.
-432 *
-433 * @param stream an input stream to close
-434 */
-435privatevoid closeStream(InputStream stream) {
-436if (stream != null) {
-437try {
-438 stream.close();
-439 } catch (IOException ex) {
-440 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINEST, null, ex);
-441 }
-442 }
-443 }
-444
-445/**
-446 * Silently closes an output stream ignoring errors.
-447 *
-448 * @param stream an output stream to close
-449 */
-450privatevoid closeStream(OutputStream stream) {
-451if (stream != null) {
-452try {
-453 stream.close();
-454 } catch (IOException ex) {
-455 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINEST, null, ex);
-456 }
-457 }
-458 }
-459
-460/**
-461 * Retrieves the specified POM from a jar file and converts it to a Model.
-462 *
-463 * @param path the path to the pom.xml file within the jar file
-464 * @param jar the jar file to extract the pom from
-465 * @return returns a
-466 * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
-467 * {@link org.owasp.dependencycheck.jaxb.pom.generated.Model} object
-468 */
-469privateModel retrievePom(String path, JarFile jar) throws AnalysisException {
-470final ZipEntry entry = jar.getEntry(path);
-471Model model = null;
-472if (entry != null) { //should never be null
-473try {
-474finalNonClosingStream stream = newNonClosingStream(jar.getInputStream(entry));
-475final InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
-476final InputSource xml = new InputSource(reader);
-477final SAXSource source = new SAXSource(xml);
-478 model = readPom(source);
-479 } catch (SecurityException ex) {
-480final String msg = String.format("Unable to parse pom '%s' in jar '%s'; invalid signature", path, jar.getName());
-481 Logger
-482 .getLogger(JarAnalyzer.class
-483 .getName()).log(Level.WARNING, msg);
-484 Logger.getLogger(JarAnalyzer.class
-485 .getName()).log(Level.FINE, null, ex);
-486thrownewAnalysisException(ex);
-487 } catch (IOException ex) {
-488final String msg = String.format("Unable to parse pom '%s' in jar '%s' (IO Exception)", path, jar.getName());
-489 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
-490 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
-491thrownewAnalysisException(ex);
-492 } catch (Throwable ex) {
-493final String msg = String.format("Unexpected error during parsing of the pom '%s' in jar '%s'", path, jar.getName());
-494 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
-495 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
-496thrownewAnalysisException(ex);
-497 }
-498 }
-499return model;
-500 }
-501
-502/**
-503 * Retrieves the specified POM from a jar file and converts it to a Model.
-504 *
-505 * @param source the SAXSource input stream to read the POM from
-506 * @return returns the POM object
-507 * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
-508 * {@link org.owasp.dependencycheck.jaxb.pom.generated.Model} object
-509 */
-510privateModel readPom(SAXSource source) throws AnalysisException {
-511Model model = null;
-512try {
-513final XMLFilter filter = newMavenNamespaceFilter();
-514final SAXParserFactory spf = SAXParserFactory.newInstance();
-515final SAXParser sp = spf.newSAXParser();
-516final XMLReader xr = sp.getXMLReader();
-517 filter.setParent(xr);
-518final JAXBElement<Model> el = pomUnmarshaller.unmarshal(source, Model.class);
-519 model = el.getValue();
-520 } catch (SecurityException ex) {
-521thrownewAnalysisException(ex);
-522 } catch (ParserConfigurationException ex) {
-523thrownewAnalysisException(ex);
-524 } catch (SAXException ex) {
-525thrownewAnalysisException(ex);
-526 } catch (JAXBException ex) {
-527thrownewAnalysisException(ex);
-528 } catch (Throwable ex) {
-529thrownewAnalysisException(ex);
-530 }
-531return model;
-532 }
-533
-534/**
-535 * Sets evidence from the pom on the supplied dependency.
-536 *
-537 * @param dependency the dependency to set data on
-538 * @param pom the information from the pom
-539 * @param pomProperties the pom properties file (null if none exists)
-540 * @param classes a collection of ClassNameInformation - containing data about the fully qualified class names
-541 * within the JAR file being analyzed
-542 * @return true if there was evidence within the pom that we could use; otherwise false
-543 */
-544privateboolean setPomEvidence(Dependency dependency, Model pom, Properties pomProperties, ArrayList<ClassNameInformation> classes) {
-545boolean foundSomething = false;
-546if (pom == null) {
-547return foundSomething;
+191 * The set of file extensions supported by this analyzer.
+192 */
+193privatestaticfinal Set<String> EXTENSIONS = newHashSet("jar", "war");
+194
+195/**
+196 * Returns a list of file EXTENSIONS supported by this analyzer.
+197 *
+198 * @return a list of file EXTENSIONS supported by this analyzer.
+199 */
+200 @Override
+201public Set<String> getSupportedExtensions() {
+202return EXTENSIONS;
+203 }
+204
+205/**
+206 * Returns the name of the analyzer.
+207 *
+208 * @return the name of the analyzer.
+209 */
+210 @Override
+211public String getName() {
+212return ANALYZER_NAME;
+213 }
+214
+215/**
+216 * Returns the phase that the analyzer is intended to run in.
+217 *
+218 * @return the phase that the analyzer is intended to run in.
+219 */
+220publicAnalysisPhase getAnalysisPhase() {
+221return ANALYSIS_PHASE;
+222 }
+223//</editor-fold>
+224
+225/**
+226 * Returns the key used in the properties file to reference the analyzer's enabled property.
+227 *
+228 * @return the analyzer's enabled property setting key
+229 */
+230 @Override
+231protected String getAnalyzerEnabledSettingKey() {
+232return Settings.KEYS.ANALYZER_JAR_ENABLED;
+233 }
+234
+235/**
+236 * Loads a specified JAR file and collects information from the manifest and checksums to identify the correct CPE
+237 * information.
+238 *
+239 * @param dependency the dependency to analyze.
+240 * @param engine the engine that is scanning the dependencies
+241 * @throws AnalysisException is thrown if there is an error reading the JAR file.
+242 */
+243 @Override
+244publicvoid analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
+245try {
+246final ArrayList<ClassNameInformation> classNames = collectClassNames(dependency);
+247final String fileName = dependency.getFileName().toLowerCase();
+248if (classNames.isEmpty()
+249 && (fileName.endsWith("-sources.jar")
+250 || fileName.endsWith("-javadoc.jar")
+251 || fileName.endsWith("-src.jar")
+252 || fileName.endsWith("-doc.jar"))) {
+253 engine.getDependencies().remove(dependency);
+254 }
+255finalboolean hasManifest = parseManifest(dependency, classNames);
+256finalboolean hasPOM = analyzePOM(dependency, classNames, engine);
+257finalboolean addPackagesAsEvidence = !(hasManifest && hasPOM);
+258 analyzePackageNames(classNames, dependency, addPackagesAsEvidence);
+259 } catch (IOException ex) {
+260thrownewAnalysisException("Exception occurred reading the JAR file.", ex);
+261 }
+262 }
+263
+264/**
+265 * Attempts to find a pom.xml within the JAR file. If found it extracts information and adds it to the evidence.
+266 * This will attempt to interpolate the strings contained within the pom.properties if one exists.
+267 *
+268 * @param dependency the dependency being analyzed
+269 * @param classes a collection of class name information
+270 * @param engine the analysis engine, used to add additional dependencies
+271 * @throws AnalysisException is thrown if there is an exception parsing the pom
+272 * @return whether or not evidence was added to the dependency
+273 */
+274protectedboolean analyzePOM(Dependency dependency, ArrayList<ClassNameInformation> classes, Engine engine) throws AnalysisException {
+275boolean foundSomething = false;
+276final JarFile jar;
+277try {
+278 jar = new JarFile(dependency.getActualFilePath());
+279 } catch (IOException ex) {
+280final String msg = String.format("Unable to read JarFile '%s'.", dependency.getActualFilePath());
+281//final AnalysisException ax = new AnalysisException(msg, ex);
+282 LOGGER.log(Level.WARNING, msg);
+283 LOGGER.log(Level.FINE, "", ex);
+284return false;
+285 }
+286 List<String> pomEntries;
+287try {
+288 pomEntries = retrievePomListing(jar);
+289 } catch (IOException ex) {
+290final String msg = String.format("Unable to read Jar file entries in '%s'.", dependency.getActualFilePath());
+291//final AnalysisException ax = new AnalysisException(msg, ex);
+292 LOGGER.log(Level.WARNING, msg);
+293 LOGGER.log(Level.FINE, msg, ex);
+294return false;
+295 }
+296if (pomEntries.isEmpty()) {
+297return false;
+298 }
+299for (String path : pomEntries) {
+300Properties pomProperties = null;
+301try {
+302 pomProperties = retrievePomProperties(path, jar);
+303 } catch (IOException ex) {
+304 LOGGER.log(Level.FINEST, "ignore this, failed reading a non-existent pom.properties", ex);
+305 }
+306Model pom = null;
+307try {
+308if (pomEntries.size() > 1) {
+309//extract POM to its own directory and add it as its own dependency
+310finalDependency newDependency = newDependency();
+311 pom = extractPom(path, jar, newDependency);
+312
+313final String displayPath = String.format("%s%s%s",
+314 dependency.getFilePath(),
+315 File.separator,
+316 path); //.replaceAll("[\\/]", File.separator));
+317final String displayName = String.format("%s%s%s",
+318 dependency.getFileName(),
+319 File.separator,
+320 path); //.replaceAll("[\\/]", File.separator));
+321
+322 newDependency.setFileName(displayName);
+323 newDependency.setFilePath(displayPath);
+324 addPomEvidence(newDependency, pom, pomProperties);
+325 engine.getDependencies().add(newDependency);
+326 Collections.sort(engine.getDependencies());
+327 } else {
+328 pom = retrievePom(path, jar);
+329 foundSomething |= setPomEvidence(dependency, pom, pomProperties, classes);
+330 }
+331 } catch (AnalysisException ex) {
+332final String msg = String.format("An error occured while analyzing '%s'.", dependency.getActualFilePath());
+333 LOGGER.log(Level.WARNING, msg);
+334 LOGGER.log(Level.FINE, "", ex);
+335 }
+336 }
+337return foundSomething;
+338 }
+339
+340/**
+341 * Given a path to a pom.xml within a JarFile, this method attempts to load a sibling pom.properties if one exists.
+342 *
+343 * @param path the path to the pom.xml within the JarFile
+344 * @param jar the JarFile to load the pom.properties from
+345 * @return a Properties object or null if no pom.properties was found
+346 * @throws IOException thrown if there is an exception reading the pom.properties
+347 */
+348 @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "OS_OPEN_STREAM",
+349 justification = "The reader is closed by closing the zipEntry")
+350privateProperties retrievePomProperties(String path, final JarFile jar) throws IOException {
+351Properties pomProperties = null;
+352final String propPath = path.substring(0, path.length() - 7) + "pom.properies";
+353final ZipEntry propEntry = jar.getEntry(propPath);
+354if (propEntry != null) {
+355final Reader reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8");
+356 pomProperties = newProperties();
+357 pomProperties.load(reader);
+358 }
+359return pomProperties;
+360 }
+361
+362/**
+363 * Searches a JarFile for pom.xml entries and returns a listing of these entries.
+364 *
+365 * @param jar the JarFile to search
+366 * @return a list of pom.xml entries
+367 * @throws IOException thrown if there is an exception reading a JarEntryf
+368 */
+369private List<String> retrievePomListing(final JarFile jar) throws IOException {
+370final List<String> pomEntries = new ArrayList<String>();
+371final Enumeration<JarEntry> entries = jar.entries();
+372while (entries.hasMoreElements()) {
+373final JarEntry entry = entries.nextElement();
+374final String entryName = (new File(entry.getName())).getName().toLowerCase();
+375if (!entry.isDirectory() && "pom.xml".equals(entryName)) {
+376 pomEntries.add(entry.getName());
+377 }
+378 }
+379return pomEntries;
+380 }
+381
+382/**
+383 * Retrieves the specified POM from a jar file and converts it to a Model.
+384 *
+385 * @param path the path to the pom.xml file within the jar file
+386 * @param jar the jar file to extract the pom from
+387 * @param dependency the dependency being analyzed
+388 * @return returns the POM object
+389 * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
+390 * {@link org.owasp.dependencycheck.jaxb.pom.generated.Model} object
+391 */
+392privateModel extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException {
+393 InputStream input = null;
+394 FileOutputStream fos = null;
+395 BufferedOutputStream bos = null;
+396final File tmpDir = getNextTempDirectory();
+397final File file = new File(tmpDir, "pom.xml");
+398try {
+399final ZipEntry entry = jar.getEntry(path);
+400 input = jar.getInputStream(entry);
+401 fos = new FileOutputStream(file);
+402 bos = new BufferedOutputStream(fos, BUFFER_SIZE);
+403int count;
+404final byte data[] = new byte[BUFFER_SIZE];
+405while ((count = input.read(data, 0, BUFFER_SIZE)) != -1) {
+406 bos.write(data, 0, count);
+407 }
+408 bos.flush();
+409 dependency.setActualFilePath(file.getAbsolutePath());
+410 } catch (IOException ex) {
+411final String msg = String.format("An error occured reading '%s' from '%s'.", path, dependency.getFilePath());
+412 LOGGER.warning(msg);
+413 LOGGER.log(Level.SEVERE, "", ex);
+414 } finally {
+415 closeStream(bos);
+416 closeStream(fos);
+417 closeStream(input);
+418 }
+419Model model = null;
+420 FileInputStream fis = null;
+421try {
+422 fis = new FileInputStream(file);
+423final InputStreamReader reader = new InputStreamReader(fis, "UTF-8");
+424final InputSource xml = new InputSource(reader);
+425final SAXSource source = new SAXSource(xml);
+426 model = readPom(source);
+427 } catch (FileNotFoundException ex) {
+428final String msg = String.format("Unable to parse pom '%s' in jar '%s' (File Not Found)", path, jar.getName());
+429 LOGGER.log(Level.WARNING, msg);
+430 LOGGER.log(Level.FINE, "", ex);
+431thrownewAnalysisException(ex);
+432 } catch (UnsupportedEncodingException ex) {
+433final String msg = String.format("Unable to parse pom '%s' in jar '%s' (IO Exception)", path, jar.getName());
+434 LOGGER.log(Level.WARNING, msg);
+435 LOGGER.log(Level.FINE, "", ex);
+436thrownewAnalysisException(ex);
+437 } catch (AnalysisException ex) {
+438final String msg = String.format("Unable to parse pom '%s' in jar '%s'", path, jar.getName());
+439 LOGGER.log(Level.WARNING, msg);
+440 LOGGER.log(Level.FINE, "", ex);
+441throw ex;
+442 } finally {
+443 closeStream(fis);
+444 }
+445return model;
+446 }
+447
+448/**
+449 * Silently closes an input stream ignoring errors.
+450 *
+451 * @param stream an input stream to close
+452 */
+453privatevoid closeStream(InputStream stream) {
+454if (stream != null) {
+455try {
+456 stream.close();
+457 } catch (IOException ex) {
+458 LOGGER.log(Level.FINEST, null, ex);
+459 }
+460 }
+461 }
+462
+463/**
+464 * Silently closes an output stream ignoring errors.
+465 *
+466 * @param stream an output stream to close
+467 */
+468privatevoid closeStream(OutputStream stream) {
+469if (stream != null) {
+470try {
+471 stream.close();
+472 } catch (IOException ex) {
+473 LOGGER.log(Level.FINEST, null, ex);
+474 }
+475 }
+476 }
+477
+478/**
+479 * Retrieves the specified POM from a jar file and converts it to a Model.
+480 *
+481 * @param path the path to the pom.xml file within the jar file
+482 * @param jar the jar file to extract the pom from
+483 * @return returns a
+484 * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
+485 * {@link org.owasp.dependencycheck.jaxb.pom.generated.Model} object
+486 */
+487privateModel retrievePom(String path, JarFile jar) throws AnalysisException {
+488final ZipEntry entry = jar.getEntry(path);
+489Model model = null;
+490if (entry != null) { //should never be null
+491try {
+492finalNonClosingStream stream = newNonClosingStream(jar.getInputStream(entry));
+493final InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
+494final InputSource xml = new InputSource(reader);
+495final SAXSource source = new SAXSource(xml);
+496 model = readPom(source);
+497 } catch (SecurityException ex) {
+498final String msg = String.format("Unable to parse pom '%s' in jar '%s'; invalid signature", path, jar.getName());
+499 Logger
+500 .getLogger(JarAnalyzer.class
+501 .getName()).log(Level.WARNING, msg);
+502 Logger.getLogger(JarAnalyzer.class
+503 .getName()).log(Level.FINE, null, ex);
+504thrownewAnalysisException(ex);
+505 } catch (IOException ex) {
+506final String msg = String.format("Unable to parse pom '%s' in jar '%s' (IO Exception)", path, jar.getName());
+507 LOGGER.log(Level.WARNING, msg);
+508 LOGGER.log(Level.FINE, "", ex);
+509thrownewAnalysisException(ex);
+510 } catch (Throwable ex) {
+511final String msg = String.format("Unexpected error during parsing of the pom '%s' in jar '%s'", path, jar.getName());
+512 LOGGER.log(Level.WARNING, msg);
+513 LOGGER.log(Level.FINE, "", ex);
+514thrownewAnalysisException(ex);
+515 }
+516 }
+517return model;
+518 }
+519
+520/**
+521 * Retrieves the specified POM from a jar file and converts it to a Model.
+522 *
+523 * @param source the SAXSource input stream to read the POM from
+524 * @return returns the POM object
+525 * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
+526 * {@link org.owasp.dependencycheck.jaxb.pom.generated.Model} object
+527 */
+528privateModel readPom(SAXSource source) throws AnalysisException {
+529Model model = null;
+530try {
+531final XMLFilter filter = newMavenNamespaceFilter();
+532final SAXParserFactory spf = SAXParserFactory.newInstance();
+533final SAXParser sp = spf.newSAXParser();
+534final XMLReader xr = sp.getXMLReader();
+535 filter.setParent(xr);
+536final JAXBElement<Model> el = pomUnmarshaller.unmarshal(source, Model.class);
+537 model = el.getValue();
+538 } catch (SecurityException ex) {
+539thrownewAnalysisException(ex);
+540 } catch (ParserConfigurationException ex) {
+541thrownewAnalysisException(ex);
+542 } catch (SAXException ex) {
+543thrownewAnalysisException(ex);
+544 } catch (JAXBException ex) {
+545thrownewAnalysisException(ex);
+546 } catch (Throwable ex) {
+547thrownewAnalysisException(ex);
548 }
-549 String groupid = interpolateString(pom.getGroupId(), pomProperties);
-550if (groupid != null && !groupid.isEmpty()) {
-551if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
-552 groupid = groupid.substring(4);
-553 }
-554 foundSomething = true;
-555 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGH);
-556 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
-557 addMatchingValues(classes, groupid, dependency.getVendorEvidence());
-558 addMatchingValues(classes, groupid, dependency.getProductEvidence());
-559 }
-560 String artifactid = interpolateString(pom.getArtifactId(), pomProperties);
-561if (artifactid != null && !artifactid.isEmpty()) {
-562if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
-563 artifactid = artifactid.substring(4);
-564 }
-565 foundSomething = true;
-566 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGH);
-567 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
-568 addMatchingValues(classes, artifactid, dependency.getVendorEvidence());
-569 addMatchingValues(classes, artifactid, dependency.getProductEvidence());
-570 }
-571//version
-572final String version = interpolateString(pom.getVersion(), pomProperties);
-573if (version != null && !version.isEmpty()) {
-574 foundSomething = true;
-575 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST);
-576 }
-577// org name
-578finalOrganization org = pom.getOrganization();
-579if (org != null && org.getName() != null) {
-580 foundSomething = true;
-581final String orgName = interpolateString(org.getName(), pomProperties);
-582if (orgName != null && !orgName.isEmpty()) {
-583 dependency.getVendorEvidence().addEvidence("pom", "organization name", orgName, Confidence.HIGH);
-584 addMatchingValues(classes, orgName, dependency.getVendorEvidence());
-585 }
-586 }
-587//pom name
-588final String pomName = interpolateString(pom.getName(), pomProperties);
-589if (pomName != null && !pomName.isEmpty()) {
-590 foundSomething = true;
-591 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
-592 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
-593 addMatchingValues(classes, pomName, dependency.getVendorEvidence());
-594 addMatchingValues(classes, pomName, dependency.getProductEvidence());
-595 }
-596
-597//Description
-598if (pom.getDescription() != null) {
-599 foundSomething = true;
-600final String description = interpolateString(pom.getDescription(), pomProperties);
-601if (description != null && !description.isEmpty()) {
-602final String trimmedDescription = addDescription(dependency, description, "pom", "description");
-603 addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence());
-604 addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence());
-605 }
-606 }
-607 extractLicense(pom, pomProperties, dependency);
-608return foundSomething;
-609 }
-610
-611/**
-612 * Analyzes the path information of the classes contained within the JarAnalyzer to try and determine possible
-613 * vendor or product names. If any are found they are stored in the packageVendor and packageProduct hashSets.
-614 *
-615 * @param classNames a list of class names
-616 * @param dependency a dependency to analyze
-617 * @param addPackagesAsEvidence a flag indicating whether or not package names should be added as evidence.
-618 */
-619protectedvoid analyzePackageNames(ArrayList<ClassNameInformation> classNames,
-620Dependency dependency, boolean addPackagesAsEvidence) {
-621final HashMap<String, Integer> vendorIdentifiers = new HashMap<String, Integer>();
-622final HashMap<String, Integer> productIdentifiers = new HashMap<String, Integer>();
-623 analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers);
-624
-625finalint classCount = classNames.size();
-626finalEvidenceCollection vendor = dependency.getVendorEvidence();
-627finalEvidenceCollection product = dependency.getProductEvidence();
+549return model;
+550 }
+551
+552/**
+553 * Sets evidence from the pom on the supplied dependency.
+554 *
+555 * @param dependency the dependency to set data on
+556 * @param pom the information from the pom
+557 * @param pomProperties the pom properties file (null if none exists)
+558 * @param classes a collection of ClassNameInformation - containing data about the fully qualified class names
+559 * within the JAR file being analyzed
+560 * @return true if there was evidence within the pom that we could use; otherwise false
+561 */
+562privateboolean setPomEvidence(Dependency dependency, Model pom, Properties pomProperties, ArrayList<ClassNameInformation> classes) {
+563boolean foundSomething = false;
+564if (pom == null) {
+565return foundSomething;
+566 }
+567 String groupid = interpolateString(pom.getGroupId(), pomProperties);
+568if (groupid != null && !groupid.isEmpty()) {
+569if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
+570 groupid = groupid.substring(4);
+571 }
+572 foundSomething = true;
+573 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGH);
+574 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
+575 addMatchingValues(classes, groupid, dependency.getVendorEvidence());
+576 addMatchingValues(classes, groupid, dependency.getProductEvidence());
+577 }
+578 String artifactid = interpolateString(pom.getArtifactId(), pomProperties);
+579if (artifactid != null && !artifactid.isEmpty()) {
+580if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
+581 artifactid = artifactid.substring(4);
+582 }
+583 foundSomething = true;
+584 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGH);
+585 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
+586 addMatchingValues(classes, artifactid, dependency.getVendorEvidence());
+587 addMatchingValues(classes, artifactid, dependency.getProductEvidence());
+588 }
+589//version
+590final String version = interpolateString(pom.getVersion(), pomProperties);
+591if (version != null && !version.isEmpty()) {
+592 foundSomething = true;
+593 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST);
+594 }
+595// org name
+596finalOrganization org = pom.getOrganization();
+597if (org != null && org.getName() != null) {
+598 foundSomething = true;
+599final String orgName = interpolateString(org.getName(), pomProperties);
+600if (orgName != null && !orgName.isEmpty()) {
+601 dependency.getVendorEvidence().addEvidence("pom", "organization name", orgName, Confidence.HIGH);
+602 addMatchingValues(classes, orgName, dependency.getVendorEvidence());
+603 }
+604 }
+605//pom name
+606final String pomName = interpolateString(pom.getName(), pomProperties);
+607if (pomName != null && !pomName.isEmpty()) {
+608 foundSomething = true;
+609 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
+610 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
+611 addMatchingValues(classes, pomName, dependency.getVendorEvidence());
+612 addMatchingValues(classes, pomName, dependency.getProductEvidence());
+613 }
+614
+615//Description
+616if (pom.getDescription() != null) {
+617 foundSomething = true;
+618final String description = interpolateString(pom.getDescription(), pomProperties);
+619if (description != null && !description.isEmpty()) {
+620final String trimmedDescription = addDescription(dependency, description, "pom", "description");
+621 addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence());
+622 addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence());
+623 }
+624 }
+625 extractLicense(pom, pomProperties, dependency);
+626return foundSomething;
+627 }
628
-629for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) {
-630finalfloat ratio = entry.getValue() / (float) classCount;
-631if (ratio > 0.5) {
-632//TODO remove weighting
-633 vendor.addWeighting(entry.getKey());
-634if (addPackagesAsEvidence && entry.getKey().length() > 1) {
-635 vendor.addEvidence("jar", "package", entry.getKey(), Confidence.LOW);
-636 }
-637 }
-638 }
-639for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) {
-640finalfloat ratio = entry.getValue() / (float) classCount;
-641if (ratio > 0.5) {
-642 product.addWeighting(entry.getKey());
-643if (addPackagesAsEvidence && entry.getKey().length() > 1) {
-644 product.addEvidence("jar", "package", entry.getKey(), Confidence.LOW);
-645 }
-646 }
-647 }
-648 }
-649
-650/**
-651 * <p>
-652 * Reads the manifest from the JAR file and collects the entries. Some vendorKey entries are:</p>
-653 * <ul><li>Implementation Title</li>
-654 * <li>Implementation Version</li> <li>Implementation Vendor</li>
-655 * <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle Version</li> <li>Bundle Vendor</li> <li>Bundle
-656 * Description</li> <li>Main Class</li> </ul>
-657 * However, all but a handful of specific entries are read in.
-658 *
-659 * @param dependency A reference to the dependency
-660 * @param classInformation a collection of class information
-661 * @return whether evidence was identified parsing the manifest
-662 * @throws IOException if there is an issue reading the JAR file
-663 */
-664protectedboolean parseManifest(Dependency dependency, ArrayList<ClassNameInformation> classInformation) throws IOException {
-665boolean foundSomething = false;
-666 JarFile jar = null;
-667try {
-668 jar = new JarFile(dependency.getActualFilePath());
-669
-670final Manifest manifest = jar.getManifest();
-671
-672if (manifest == null) {
-673//don't log this for javadoc or sources jar files
-674if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar")
-675 && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar")
-676 && !dependency.getFileName().toLowerCase().endsWith("-src.jar")
-677 && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) {
-678 Logger.getLogger(JarAnalyzer.class
-679 .getName()).log(Level.INFO,
-680 String.format("Jar file '%s' does not contain a manifest.",
-681 dependency.getFileName()));
-682 }
-683return false;
-684 }
-685final Attributes atts = manifest.getMainAttributes();
-686
-687finalEvidenceCollection vendorEvidence = dependency.getVendorEvidence();
-688finalEvidenceCollection productEvidence = dependency.getProductEvidence();
-689finalEvidenceCollection versionEvidence = dependency.getVersionEvidence();
-690
-691final String source = "Manifest";
-692
-693for (Entry<Object, Object> entry : atts.entrySet()) {
-694 String key = entry.getKey().toString();
-695 String value = atts.getValue(key);
-696if (HTML_DETECTION_PATTERN.matcher(value).find()) {
-697 value = Jsoup.parse(value).text();
-698 }
-699if (IGNORE_VALUES.contains(value)) {
-700continue;
-701 } elseif (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
-702 foundSomething = true;
-703 productEvidence.addEvidence(source, key, value, Confidence.HIGH);
-704 addMatchingValues(classInformation, value, productEvidence);
-705 } elseif (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
-706 foundSomething = true;
-707 versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
-708 } elseif (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
-709 foundSomething = true;
-710 vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
-711 addMatchingValues(classInformation, value, vendorEvidence);
-712 } elseif (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR_ID.toString())) {
-713 foundSomething = true;
-714 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-715 addMatchingValues(classInformation, value, vendorEvidence);
-716 } elseif (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) {
-717 foundSomething = true;
-718 addDescription(dependency, value, "manifest", key);
-719//productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-720 addMatchingValues(classInformation, value, productEvidence);
-721 } elseif (key.equalsIgnoreCase(BUNDLE_NAME)) {
-722 foundSomething = true;
-723 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-724 addMatchingValues(classInformation, value, productEvidence);
-725 } elseif (key.equalsIgnoreCase(BUNDLE_VENDOR)) {
-726 foundSomething = true;
-727 vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
-728 addMatchingValues(classInformation, value, vendorEvidence);
-729 } elseif (key.equalsIgnoreCase(BUNDLE_VERSION)) {
-730 foundSomething = true;
-731 versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
-732 } elseif (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
-733continue;
-734//skipping main class as if this has important information to add
-735// it will be added during class name analysis... if other fields
-736// have the information from the class name then they will get added...
-737// foundSomething = true;
-738// productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-739// vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-740// addMatchingValues(classInformation, value, vendorEvidence);
-741// addMatchingValues(classInformation, value, productEvidence);
-742 } else {
-743 key = key.toLowerCase();
-744
-745if (!IGNORE_KEYS.contains(key)
-746 && !key.endsWith("jdk")
-747 && !key.contains("lastmodified")
-748 && !key.endsWith("package")
-749 && !key.endsWith("classpath")
-750 && !key.endsWith("class-path")
-751 && !key.endsWith("-scm") //todo change this to a regex?
-752 && !key.startsWith("scm-")
-753 && !isImportPackage(key, value)
-754 && !isPackage(key, value)) {
-755
-756 foundSomething = true;
-757if (key.contains("version")) {
-758if (key.contains("specification")) {
-759 versionEvidence.addEvidence(source, key, value, Confidence.LOW);
-760 } else {
-761 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-762 }
-763 } elseif ("build-id".equals(key)) {
-764int pos = value.indexOf('(');
-765if (pos >= 0) {
-766 value = value.substring(0, pos - 1);
-767 }
-768 pos = value.indexOf('[');
-769if (pos >= 0) {
-770 value = value.substring(0, pos - 1);
-771 }
-772 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-773 } elseif (key.contains("title")) {
-774 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-775 addMatchingValues(classInformation, value, productEvidence);
-776 } elseif (key.contains("vendor")) {
-777if (key.contains("specification")) {
-778 vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
-779 } else {
-780 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-781 addMatchingValues(classInformation, value, vendorEvidence);
-782 }
-783 } elseif (key.contains("name")) {
-784 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-785 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
-786 addMatchingValues(classInformation, value, vendorEvidence);
-787 addMatchingValues(classInformation, value, productEvidence);
-788 } elseif (key.contains("license")) {
-789 addLicense(dependency, value);
-790 } else {
-791if (key.contains("description")) {
-792 addDescription(dependency, value, "manifest", key);
-793 } else {
-794 productEvidence.addEvidence(source, key, value, Confidence.LOW);
-795 vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
-796 addMatchingValues(classInformation, value, vendorEvidence);
-797 addMatchingValues(classInformation, value, productEvidence);
-798if (value.matches(".*\\d.*")) {
-799final StringTokenizer tokenizer = new StringTokenizer(value, " ");
-800while (tokenizer.hasMoreElements()) {
-801final String s = tokenizer.nextToken();
-802if (s.matches("^[0-9.]+$")) {
-803 versionEvidence.addEvidence(source, key, s, Confidence.LOW);
-804 }
-805 }
-806 }
-807 }
-808 }
-809 }
-810 }
-811 }
-812 } finally {
-813if (jar != null) {
-814 jar.close();
-815 }
-816 }
-817return foundSomething;
-818 }
-819
-820/**
-821 * Adds a description to the given dependency. If the description contains one of the following strings beyond 100
-822 * characters, then the description used will be trimmed to that position:
-823 * <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses "</li></ul>
-824 *
-825 * @param dependency a dependency
-826 * @param description the description
-827 * @param source the source of the evidence
-828 * @param key the "name" of the evidence
-829 * @return if the description is trimmed, the trimmed version is returned; otherwise the original description is
-830 * returned
-831 */
-832private String addDescription(Dependency dependency, String description, String source, String key) {
-833if (dependency.getDescription() == null) {
-834 dependency.setDescription(description);
-835 }
-836 String desc;
-837if (HTML_DETECTION_PATTERN.matcher(description).find()) {
-838 desc = Jsoup.parse(description).text();
-839 } else {
-840 desc = description;
-841 }
-842 dependency.setDescription(desc);
-843if (desc.length() > 100) {
-844 desc = desc.replaceAll("\\s\\s+", " ");
-845finalint posSuchAs = desc.toLowerCase().indexOf("such as ", 100);
-846finalint posLike = desc.toLowerCase().indexOf("like ", 100);
-847finalint posWillUse = desc.toLowerCase().indexOf("will use ", 100);
-848finalint posUses = desc.toLowerCase().indexOf(" uses ", 100);
-849int pos = -1;
-850 pos = Math.max(pos, posSuchAs);
-851if (pos >= 0 && posLike >= 0) {
-852 pos = Math.min(pos, posLike);
-853 } else {
-854 pos = Math.max(pos, posLike);
-855 }
-856if (pos >= 0 && posWillUse >= 0) {
-857 pos = Math.min(pos, posWillUse);
-858 } else {
-859 pos = Math.max(pos, posWillUse);
-860 }
-861if (pos >= 0 && posUses >= 0) {
-862 pos = Math.min(pos, posUses);
-863 } else {
-864 pos = Math.max(pos, posUses);
-865 }
-866
-867if (pos > 0) {
-868final StringBuilder sb = new StringBuilder(pos + 3);
-869 sb.append(desc.substring(0, pos));
-870 sb.append("...");
-871 desc = sb.toString();
-872 }
-873 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.LOW);
-874 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.LOW);
-875 } else {
-876 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.MEDIUM);
-877 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.MEDIUM);
-878 }
-879return desc;
-880 }
-881
-882/**
-883 * Adds a license to the given dependency.
-884 *
-885 * @param d a dependency
-886 * @param license the license
-887 */
-888privatevoid addLicense(Dependency d, String license) {
-889if (d.getLicense() == null) {
-890 d.setLicense(license);
-891 } elseif (!d.getLicense().contains(license)) {
-892 d.setLicense(d.getLicense() + NEWLINE + license);
-893 }
-894 }
-895
-896/**
-897 * The parent directory for the individual directories per archive.
-898 */
-899private File tempFileLocation = null;
-900
-901/**
-902 * The initialize method does nothing for this Analyzer.
-903 *
-904 * @throws Exception is thrown if there is an exception creating a temporary directory
+629/**
+630 * Analyzes the path information of the classes contained within the JarAnalyzer to try and determine possible
+631 * vendor or product names. If any are found they are stored in the packageVendor and packageProduct hashSets.
+632 *
+633 * @param classNames a list of class names
+634 * @param dependency a dependency to analyze
+635 * @param addPackagesAsEvidence a flag indicating whether or not package names should be added as evidence.
+636 */
+637protectedvoid analyzePackageNames(ArrayList<ClassNameInformation> classNames,
+638Dependency dependency, boolean addPackagesAsEvidence) {
+639final HashMap<String, Integer> vendorIdentifiers = new HashMap<String, Integer>();
+640final HashMap<String, Integer> productIdentifiers = new HashMap<String, Integer>();
+641 analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers);
+642
+643finalint classCount = classNames.size();
+644finalEvidenceCollection vendor = dependency.getVendorEvidence();
+645finalEvidenceCollection product = dependency.getProductEvidence();
+646
+647for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) {
+648finalfloat ratio = entry.getValue() / (float) classCount;
+649if (ratio > 0.5) {
+650//TODO remove weighting
+651 vendor.addWeighting(entry.getKey());
+652if (addPackagesAsEvidence && entry.getKey().length() > 1) {
+653 vendor.addEvidence("jar", "package", entry.getKey(), Confidence.LOW);
+654 }
+655 }
+656 }
+657for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) {
+658finalfloat ratio = entry.getValue() / (float) classCount;
+659if (ratio > 0.5) {
+660 product.addWeighting(entry.getKey());
+661if (addPackagesAsEvidence && entry.getKey().length() > 1) {
+662 product.addEvidence("jar", "package", entry.getKey(), Confidence.LOW);
+663 }
+664 }
+665 }
+666 }
+667
+668/**
+669 * <p>
+670 * Reads the manifest from the JAR file and collects the entries. Some vendorKey entries are:</p>
+671 * <ul><li>Implementation Title</li>
+672 * <li>Implementation Version</li> <li>Implementation Vendor</li>
+673 * <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle Version</li> <li>Bundle Vendor</li> <li>Bundle
+674 * Description</li> <li>Main Class</li> </ul>
+675 * However, all but a handful of specific entries are read in.
+676 *
+677 * @param dependency A reference to the dependency
+678 * @param classInformation a collection of class information
+679 * @return whether evidence was identified parsing the manifest
+680 * @throws IOException if there is an issue reading the JAR file
+681 */
+682protectedboolean parseManifest(Dependency dependency, ArrayList<ClassNameInformation> classInformation) throws IOException {
+683boolean foundSomething = false;
+684 JarFile jar = null;
+685try {
+686 jar = new JarFile(dependency.getActualFilePath());
+687
+688final Manifest manifest = jar.getManifest();
+689
+690if (manifest == null) {
+691//don't log this for javadoc or sources jar files
+692if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar")
+693 && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar")
+694 && !dependency.getFileName().toLowerCase().endsWith("-src.jar")
+695 && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) {
+696 Logger.getLogger(JarAnalyzer.class
+697 .getName()).log(Level.INFO,
+698 String.format("Jar file '%s' does not contain a manifest.",
+699 dependency.getFileName()));
+700 }
+701return false;
+702 }
+703final Attributes atts = manifest.getMainAttributes();
+704
+705finalEvidenceCollection vendorEvidence = dependency.getVendorEvidence();
+706finalEvidenceCollection productEvidence = dependency.getProductEvidence();
+707finalEvidenceCollection versionEvidence = dependency.getVersionEvidence();
+708
+709final String source = "Manifest";
+710
+711for (Entry<Object, Object> entry : atts.entrySet()) {
+712 String key = entry.getKey().toString();
+713 String value = atts.getValue(key);
+714if (HTML_DETECTION_PATTERN.matcher(value).find()) {
+715 value = Jsoup.parse(value).text();
+716 }
+717if (IGNORE_VALUES.contains(value)) {
+718continue;
+719 } elseif (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
+720 foundSomething = true;
+721 productEvidence.addEvidence(source, key, value, Confidence.HIGH);
+722 addMatchingValues(classInformation, value, productEvidence);
+723 } elseif (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
+724 foundSomething = true;
+725 versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
+726 } elseif (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
+727 foundSomething = true;
+728 vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
+729 addMatchingValues(classInformation, value, vendorEvidence);
+730 } elseif (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR_ID.toString())) {
+731 foundSomething = true;
+732 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+733 addMatchingValues(classInformation, value, vendorEvidence);
+734 } elseif (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) {
+735 foundSomething = true;
+736 addDescription(dependency, value, "manifest", key);
+737//productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+738 addMatchingValues(classInformation, value, productEvidence);
+739 } elseif (key.equalsIgnoreCase(BUNDLE_NAME)) {
+740 foundSomething = true;
+741 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+742 addMatchingValues(classInformation, value, productEvidence);
+743 } elseif (key.equalsIgnoreCase(BUNDLE_VENDOR)) {
+744 foundSomething = true;
+745 vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
+746 addMatchingValues(classInformation, value, vendorEvidence);
+747 } elseif (key.equalsIgnoreCase(BUNDLE_VERSION)) {
+748 foundSomething = true;
+749 versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
+750 } elseif (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
+751continue;
+752//skipping main class as if this has important information to add
+753// it will be added during class name analysis... if other fields
+754// have the information from the class name then they will get added...
+755// foundSomething = true;
+756// productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+757// vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+758// addMatchingValues(classInformation, value, vendorEvidence);
+759// addMatchingValues(classInformation, value, productEvidence);
+760 } else {
+761 key = key.toLowerCase();
+762
+763if (!IGNORE_KEYS.contains(key)
+764 && !key.endsWith("jdk")
+765 && !key.contains("lastmodified")
+766 && !key.endsWith("package")
+767 && !key.endsWith("classpath")
+768 && !key.endsWith("class-path")
+769 && !key.endsWith("-scm") //todo change this to a regex?
+770 && !key.startsWith("scm-")
+771 && !isImportPackage(key, value)
+772 && !isPackage(key, value)) {
+773
+774 foundSomething = true;
+775if (key.contains("version")) {
+776if (key.contains("specification")) {
+777 versionEvidence.addEvidence(source, key, value, Confidence.LOW);
+778 } else {
+779 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+780 }
+781 } elseif ("build-id".equals(key)) {
+782int pos = value.indexOf('(');
+783if (pos >= 0) {
+784 value = value.substring(0, pos - 1);
+785 }
+786 pos = value.indexOf('[');
+787if (pos >= 0) {
+788 value = value.substring(0, pos - 1);
+789 }
+790 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+791 } elseif (key.contains("title")) {
+792 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+793 addMatchingValues(classInformation, value, productEvidence);
+794 } elseif (key.contains("vendor")) {
+795if (key.contains("specification")) {
+796 vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
+797 } else {
+798 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+799 addMatchingValues(classInformation, value, vendorEvidence);
+800 }
+801 } elseif (key.contains("name")) {
+802 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+803 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
+804 addMatchingValues(classInformation, value, vendorEvidence);
+805 addMatchingValues(classInformation, value, productEvidence);
+806 } elseif (key.contains("license")) {
+807 addLicense(dependency, value);
+808 } else {
+809if (key.contains("description")) {
+810 addDescription(dependency, value, "manifest", key);
+811 } else {
+812 productEvidence.addEvidence(source, key, value, Confidence.LOW);
+813 vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
+814 addMatchingValues(classInformation, value, vendorEvidence);
+815 addMatchingValues(classInformation, value, productEvidence);
+816if (value.matches(".*\\d.*")) {
+817final StringTokenizer tokenizer = new StringTokenizer(value, " ");
+818while (tokenizer.hasMoreElements()) {
+819final String s = tokenizer.nextToken();
+820if (s.matches("^[0-9.]+$")) {
+821 versionEvidence.addEvidence(source, key, s, Confidence.LOW);
+822 }
+823 }
+824 }
+825 }
+826 }
+827 }
+828 }
+829 }
+830 } finally {
+831if (jar != null) {
+832 jar.close();
+833 }
+834 }
+835return foundSomething;
+836 }
+837
+838/**
+839 * Adds a description to the given dependency. If the description contains one of the following strings beyond 100
+840 * characters, then the description used will be trimmed to that position:
+841 * <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses "</li></ul>
+842 *
+843 * @param dependency a dependency
+844 * @param description the description
+845 * @param source the source of the evidence
+846 * @param key the "name" of the evidence
+847 * @return if the description is trimmed, the trimmed version is returned; otherwise the original description is
+848 * returned
+849 */
+850private String addDescription(Dependency dependency, String description, String source, String key) {
+851if (dependency.getDescription() == null) {
+852 dependency.setDescription(description);
+853 }
+854 String desc;
+855if (HTML_DETECTION_PATTERN.matcher(description).find()) {
+856 desc = Jsoup.parse(description).text();
+857 } else {
+858 desc = description;
+859 }
+860 dependency.setDescription(desc);
+861if (desc.length() > 100) {
+862 desc = desc.replaceAll("\\s\\s+", " ");
+863finalint posSuchAs = desc.toLowerCase().indexOf("such as ", 100);
+864finalint posLike = desc.toLowerCase().indexOf("like ", 100);
+865finalint posWillUse = desc.toLowerCase().indexOf("will use ", 100);
+866finalint posUses = desc.toLowerCase().indexOf(" uses ", 100);
+867int pos = -1;
+868 pos = Math.max(pos, posSuchAs);
+869if (pos >= 0 && posLike >= 0) {
+870 pos = Math.min(pos, posLike);
+871 } else {
+872 pos = Math.max(pos, posLike);
+873 }
+874if (pos >= 0 && posWillUse >= 0) {
+875 pos = Math.min(pos, posWillUse);
+876 } else {
+877 pos = Math.max(pos, posWillUse);
+878 }
+879if (pos >= 0 && posUses >= 0) {
+880 pos = Math.min(pos, posUses);
+881 } else {
+882 pos = Math.max(pos, posUses);
+883 }
+884
+885if (pos > 0) {
+886final StringBuilder sb = new StringBuilder(pos + 3);
+887 sb.append(desc.substring(0, pos));
+888 sb.append("...");
+889 desc = sb.toString();
+890 }
+891 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.LOW);
+892 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.LOW);
+893 } else {
+894 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.MEDIUM);
+895 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.MEDIUM);
+896 }
+897return desc;
+898 }
+899
+900/**
+901 * Adds a license to the given dependency.
+902 *
+903 * @param d a dependency
+904 * @param license the license905 */
-906 @Override
-907publicvoid initialize() throws Exception {
-908final File baseDir = Settings.getTempDirectory();
-909if (!baseDir.exists()) {
-910if (!baseDir.mkdirs()) {
-911final String msg = String.format("Unable to make a temporary folder '%s'", baseDir.getPath());
-912thrownewAnalysisException(msg);
-913 }
-914 }
-915 tempFileLocation = File.createTempFile("check", "tmp", baseDir);
-916if (!tempFileLocation.delete()) {
-917final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
-918thrownewAnalysisException(msg);
-919 }
-920if (!tempFileLocation.mkdirs()) {
-921final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
-922thrownewAnalysisException(msg);
-923 }
-924 }
-925
-926/**
-927 * Deletes any files extracted from the JAR during analysis.
-928 */
-929 @Override
-930publicvoid close() {
-931if (tempFileLocation != null && tempFileLocation.exists()) {
-932 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, "Attempting to delete temporary files");
-933finalboolean success = FileUtils.delete(tempFileLocation);
-934if (!success) {
-935 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING,
-936"Failed to delete some temporary files, see the log for more details");
-937 }
-938 }
-939 }
-940
-941/**
-942 * <p>
-943 * A utility function that will interpolate strings based on values given in the properties file. It will also
-944 * interpolate the strings contained within the properties file so that properties can reference other
-945 * properties.</p>
-946 * <p>
-947 * <b>Note:</b> if there is no property found the reference will be removed. In other words, if the interpolated
-948 * string will be replaced with an empty string.
-949 * </p>
-950 * <p>
-951 * Example:</p>
-952 * <code>
-953 * Properties p = new Properties();
-954 * p.setProperty("key", "value");
-955 * String s = interpolateString("'${key}' and '${nothing}'", p);
-956 * System.out.println(s);
-957 * </code>
-958 * <p>
-959 * Will result in:</p>
-960 * <code>
-961 * 'value' and ''
-962 * </code>
-963 *
-964 * @param text the string that contains references to properties.
-965 * @param properties a collection of properties that may be referenced within the text.
-966 * @return the interpolated text.
-967 */
-968protected String interpolateString(String text, Properties properties) {
-969Properties props = properties;
-970if (text == null) {
-971return text;
-972 }
-973if (props == null) {
-974 props = newProperties();
-975 }
-976
-977finalint pos = text.indexOf("${");
-978if (pos < 0) {
-979return text;
-980 }
-981finalint end = text.indexOf("}");
-982if (end < pos) {
-983return text;
-984 }
-985
-986final String propName = text.substring(pos + 2, end);
-987 String propValue = interpolateString(props.getProperty(propName), props);
-988if (propValue == null) {
-989 propValue = "";
+906privatevoid addLicense(Dependency d, String license) {
+907if (d.getLicense() == null) {
+908 d.setLicense(license);
+909 } elseif (!d.getLicense().contains(license)) {
+910 d.setLicense(d.getLicense() + NEWLINE + license);
+911 }
+912 }
+913
+914/**
+915 * The parent directory for the individual directories per archive.
+916 */
+917private File tempFileLocation = null;
+918
+919/**
+920 * Initializes the JarAnalyzer.
+921 *
+922 * @throws Exception is thrown if there is an exception creating a temporary directory
+923 */
+924 @Override
+925publicvoid initializeFileTypeAnalyzer() throws Exception {
+926final File baseDir = Settings.getTempDirectory();
+927if (!baseDir.exists()) {
+928if (!baseDir.mkdirs()) {
+929final String msg = String.format("Unable to make a temporary folder '%s'", baseDir.getPath());
+930thrownewAnalysisException(msg);
+931 }
+932 }
+933 tempFileLocation = File.createTempFile("check", "tmp", baseDir);
+934if (!tempFileLocation.delete()) {
+935final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
+936thrownewAnalysisException(msg);
+937 }
+938if (!tempFileLocation.mkdirs()) {
+939final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
+940thrownewAnalysisException(msg);
+941 }
+942 }
+943
+944/**
+945 * Deletes any files extracted from the JAR during analysis.
+946 */
+947 @Override
+948publicvoid close() {
+949if (tempFileLocation != null && tempFileLocation.exists()) {
+950 LOGGER.log(Level.FINE, "Attempting to delete temporary files");
+951finalboolean success = FileUtils.delete(tempFileLocation);
+952if (!success) {
+953 LOGGER.log(Level.WARNING,
+954"Failed to delete some temporary files, see the log for more details");
+955 }
+956 }
+957 }
+958
+959/**
+960 * <p>
+961 * A utility function that will interpolate strings based on values given in the properties file. It will also
+962 * interpolate the strings contained within the properties file so that properties can reference other
+963 * properties.</p>
+964 * <p>
+965 * <b>Note:</b> if there is no property found the reference will be removed. In other words, if the interpolated
+966 * string will be replaced with an empty string.
+967 * </p>
+968 * <p>
+969 * Example:</p>
+970 * <code>
+971 * Properties p = new Properties();
+972 * p.setProperty("key", "value");
+973 * String s = interpolateString("'${key}' and '${nothing}'", p);
+974 * System.out.println(s);
+975 * </code>
+976 * <p>
+977 * Will result in:</p>
+978 * <code>
+979 * 'value' and ''
+980 * </code>
+981 *
+982 * @param text the string that contains references to properties.
+983 * @param properties a collection of properties that may be referenced within the text.
+984 * @return the interpolated text.
+985 */
+986protected String interpolateString(String text, Properties properties) {
+987Properties props = properties;
+988if (text == null) {
+989return text;
990 }
-991final StringBuilder sb = new StringBuilder(propValue.length() + text.length());
-992 sb.append(text.subSequence(0, pos));
-993 sb.append(propValue);
-994 sb.append(text.substring(end + 1));
-995return interpolateString(sb.toString(), props); //yes yes, this should be a loop...
-996 }
-997
-998/**
-999 * Determines if the key value pair from the manifest is for an "import" type entry for package names.
-1000 *
-1001 * @param key the key from the manifest
-1002 * @param value the value from the manifest
-1003 * @return true or false depending on if it is believed the entry is an "import" entry
-1004 */
-1005privateboolean isImportPackage(String key, String value) {
-1006final Pattern packageRx = Pattern.compile("^((([a-zA-Z_#\\$0-9]\\.)+)\\s*\\;\\s*)+$");
-1007if (packageRx.matcher(value).matches()) {
-1008return (key.contains("import") || key.contains("include"));
-1009 }
-1010return false;
-1011 }
-1012
-1013/**
-1014 * Cycles through an enumeration of JarEntries, contained within the dependency, and returns a list of the class
-1015 * names. This does not include core Java package names (i.e. java.* or javax.*).
-1016 *
-1017 * @param dependency the dependency being analyzed
-1018 * @return an list of fully qualified class names
-1019 */
-1020private ArrayList<ClassNameInformation> collectClassNames(Dependency dependency) {
-1021final ArrayList<ClassNameInformation> classNames = new ArrayList<ClassNameInformation>();
-1022 JarFile jar = null;
-1023try {
-1024 jar = new JarFile(dependency.getActualFilePath());
-1025final Enumeration entries = jar.entries();
-1026while (entries.hasMoreElements()) {
-1027final JarEntry entry = (JarEntry) entries.nextElement();
-1028final String name = entry.getName().toLowerCase();
-1029//no longer stripping "|com\\.sun" - there are some com.sun jar files with CVEs.
-1030if (name.endsWith(".class") && !name.matches("^javax?\\..*$")) {
-1031finalClassNameInformation className = newClassNameInformation(name.substring(0, name.length() - 6));
-1032 classNames.add(className);
-1033 }
-1034 }
-1035 } catch (IOException ex) {
-1036final String msg = String.format("Unable to open jar file '%s'.", dependency.getFileName());
-1037 Logger
-1038 .getLogger(JarAnalyzer.class
-1039 .getName()).log(Level.WARNING, msg);
-1040 Logger.getLogger(JarAnalyzer.class
-1041 .getName()).log(Level.FINE, null, ex);
-1042 } finally {
-1043if (jar != null) {
-1044try {
-1045 jar.close();
-1046 } catch (IOException ex) {
-1047 Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINEST, null, ex);
-1048 }
-1049 }
-1050 }
-1051return classNames;
-1052 }
-1053
-1054/**
-1055 * Cycles through the list of class names and places the package levels 0-3 into the provided maps for vendor and
-1056 * product. This is helpful when analyzing vendor/product as many times this is included in the package name.
-1057 *
-1058 * @param classNames a list of class names
-1059 * @param vendor HashMap of possible vendor names from package names (e.g. owasp)
-1060 * @param product HashMap of possible product names from package names (e.g. dependencycheck)
-1061 */
-1062privatevoid analyzeFullyQualifiedClassNames(ArrayList<ClassNameInformation> classNames,
-1063 HashMap<String, Integer> vendor, HashMap<String, Integer> product) {
-1064for (ClassNameInformation entry : classNames) {
-1065final ArrayList<String> list = entry.getPackageStructure();
-1066 addEntry(vendor, list.get(0));
-1067
-1068if (list.size() == 2) {
-1069 addEntry(product, list.get(1));
-1070 }
-1071if (list.size() == 3) {
-1072 addEntry(vendor, list.get(1));
-1073 addEntry(product, list.get(1));
-1074 addEntry(product, list.get(2));
-1075 }
-1076if (list.size() >= 4) {
-1077 addEntry(vendor, list.get(1));
-1078 addEntry(vendor, list.get(2));
-1079 addEntry(product, list.get(1));
-1080 addEntry(product, list.get(2));
-1081 addEntry(product, list.get(3));
-1082 }
-1083 }
-1084 }
-1085
-1086/**
-1087 * Adds an entry to the specified collection and sets the Integer (e.g. the count) to 1. If the entry already exists
-1088 * in the collection then the Integer is incremented by 1.
-1089 *
-1090 * @param collection a collection of strings and their occurrence count
-1091 * @param key the key to add to the collection
-1092 */
-1093privatevoid addEntry(HashMap<String, Integer> collection, String key) {
-1094if (collection.containsKey(key)) {
-1095 collection.put(key, collection.get(key) + 1);
-1096 } else {
-1097 collection.put(key, 1);
-1098 }
-1099 }
-1100
-1101/**
-1102 * Cycles through the collection of class name information to see if parts of the package names are contained in the
-1103 * provided value. If found, it will be added as the HIGHEST confidence evidence because we have more then one
-1104 * source corroborating the value.
+991if (props == null) {
+992 props = newProperties();
+993 }
+994
+995finalint pos = text.indexOf("${");
+996if (pos < 0) {
+997return text;
+998 }
+999finalint end = text.indexOf("}");
+1000if (end < pos) {
+1001return text;
+1002 }
+1003
+1004final String propName = text.substring(pos + 2, end);
+1005 String propValue = interpolateString(props.getProperty(propName), props);
+1006if (propValue == null) {
+1007 propValue = "";
+1008 }
+1009final StringBuilder sb = new StringBuilder(propValue.length() + text.length());
+1010 sb.append(text.subSequence(0, pos));
+1011 sb.append(propValue);
+1012 sb.append(text.substring(end + 1));
+1013return interpolateString(sb.toString(), props); //yes yes, this should be a loop...
+1014 }
+1015
+1016/**
+1017 * Determines if the key value pair from the manifest is for an "import" type entry for package names.
+1018 *
+1019 * @param key the key from the manifest
+1020 * @param value the value from the manifest
+1021 * @return true or false depending on if it is believed the entry is an "import" entry
+1022 */
+1023privateboolean isImportPackage(String key, String value) {
+1024final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$");
+1025finalboolean matches = packageRx.matcher(value).matches();
+1026return matches && (key.contains("import") || key.contains("include") || value.length() > 10);
+1027 }
+1028
+1029/**
+1030 * Cycles through an enumeration of JarEntries, contained within the dependency, and returns a list of the class
+1031 * names. This does not include core Java package names (i.e. java.* or javax.*).
+1032 *
+1033 * @param dependency the dependency being analyzed
+1034 * @return an list of fully qualified class names
+1035 */
+1036private ArrayList<ClassNameInformation> collectClassNames(Dependency dependency) {
+1037final ArrayList<ClassNameInformation> classNames = new ArrayList<ClassNameInformation>();
+1038 JarFile jar = null;
+1039try {
+1040 jar = new JarFile(dependency.getActualFilePath());
+1041final Enumeration entries = jar.entries();
+1042while (entries.hasMoreElements()) {
+1043final JarEntry entry = (JarEntry) entries.nextElement();
+1044final String name = entry.getName().toLowerCase();
+1045//no longer stripping "|com\\.sun" - there are some com.sun jar files with CVEs.
+1046if (name.endsWith(".class") && !name.matches("^javax?\\..*$")) {
+1047finalClassNameInformation className = newClassNameInformation(name.substring(0, name.length() - 6));
+1048 classNames.add(className);
+1049 }
+1050 }
+1051 } catch (IOException ex) {
+1052final String msg = String.format("Unable to open jar file '%s'.", dependency.getFileName());
+1053 Logger
+1054 .getLogger(JarAnalyzer.class
+1055 .getName()).log(Level.WARNING, msg);
+1056 Logger.getLogger(JarAnalyzer.class
+1057 .getName()).log(Level.FINE, null, ex);
+1058 } finally {
+1059if (jar != null) {
+1060try {
+1061 jar.close();
+1062 } catch (IOException ex) {
+1063 LOGGER.log(Level.FINEST, null, ex);
+1064 }
+1065 }
+1066 }
+1067return classNames;
+1068 }
+1069
+1070/**
+1071 * Cycles through the list of class names and places the package levels 0-3 into the provided maps for vendor and
+1072 * product. This is helpful when analyzing vendor/product as many times this is included in the package name.
+1073 *
+1074 * @param classNames a list of class names
+1075 * @param vendor HashMap of possible vendor names from package names (e.g. owasp)
+1076 * @param product HashMap of possible product names from package names (e.g. dependencycheck)
+1077 */
+1078privatevoid analyzeFullyQualifiedClassNames(ArrayList<ClassNameInformation> classNames,
+1079 HashMap<String, Integer> vendor, HashMap<String, Integer> product) {
+1080for (ClassNameInformation entry : classNames) {
+1081final ArrayList<String> list = entry.getPackageStructure();
+1082 addEntry(vendor, list.get(0));
+1083
+1084if (list.size() == 2) {
+1085 addEntry(product, list.get(1));
+1086 }
+1087if (list.size() == 3) {
+1088 addEntry(vendor, list.get(1));
+1089 addEntry(product, list.get(1));
+1090 addEntry(product, list.get(2));
+1091 }
+1092if (list.size() >= 4) {
+1093 addEntry(vendor, list.get(1));
+1094 addEntry(vendor, list.get(2));
+1095 addEntry(product, list.get(1));
+1096 addEntry(product, list.get(2));
+1097 addEntry(product, list.get(3));
+1098 }
+1099 }
+1100 }
+1101
+1102/**
+1103 * Adds an entry to the specified collection and sets the Integer (e.g. the count) to 1. If the entry already exists
+1104 * in the collection then the Integer is incremented by 1.1105 *
-1106 * @param classes a collection of class name information
-1107 * @param value the value to check to see if it contains a package name
-1108 * @param evidence the evidence collection to add new entries too
-1109 */
-1110privatevoid addMatchingValues(ArrayList<ClassNameInformation> classes, String value, EvidenceCollection evidence) {
-1111if (value == null || value.isEmpty()) {
-1112return;
-1113 }
-1114final String text = value.toLowerCase();
-1115for (ClassNameInformation cni : classes) {
-1116for (String key : cni.getPackageStructure()) {
-1117if (text.contains(key)) { //note, package structure elements are already lowercase.
-1118 evidence.addEvidence("jar", "package name", key, Confidence.HIGHEST);
-1119 }
-1120 }
-1121 }
-1122 }
-1123
-1124/**
-1125 * Simple check to see if the attribute from a manifest is just a package name.
-1126 *
-1127 * @param key the key of the value to check
-1128 * @param value the value to check
-1129 * @return true if the value looks like a java package name, otherwise false
-1130 */
-1131privateboolean isPackage(String key, String value) {
-1132
-1133return !key.matches(".*(version|title|vendor|name|license|description).*")
-1134 && value.matches("^([a-zA-Z_][a-zA-Z0-9_\\$]*(\\.[a-zA-Z_][a-zA-Z0-9_\\$]*)*)?$");
-1135
-1136 }
-1137
-1138/**
-1139 * Adds evidence from the POM to the dependency. This includes the GAV and in some situations the parent GAV if
-1140 * specified.
-1141 *
-1142 * @param dependency the dependency being analyzed
-1143 * @param pom the POM data
-1144 * @param pomProperties the properties file associated with the pom
-1145 */
-1146privatevoid addPomEvidence(Dependency dependency, Model pom, Properties pomProperties) {
-1147if (pom == null) {
-1148return;
-1149 }
-1150 String groupid = interpolateString(pom.getGroupId(), pomProperties);
-1151if (groupid != null && !groupid.isEmpty()) {
-1152if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
-1153 groupid = groupid.substring(4);
-1154 }
-1155 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGH);
-1156 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
-1157 }
-1158 String artifactid = interpolateString(pom.getArtifactId(), pomProperties);
-1159if (artifactid != null && !artifactid.isEmpty()) {
-1160if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
-1161 artifactid = artifactid.substring(4);
-1162 }
-1163 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGH);
-1164 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
+1106 * @param collection a collection of strings and their occurrence count
+1107 * @param key the key to add to the collection
+1108 */
+1109privatevoid addEntry(HashMap<String, Integer> collection, String key) {
+1110if (collection.containsKey(key)) {
+1111 collection.put(key, collection.get(key) + 1);
+1112 } else {
+1113 collection.put(key, 1);
+1114 }
+1115 }
+1116
+1117/**
+1118 * Cycles through the collection of class name information to see if parts of the package names are contained in the
+1119 * provided value. If found, it will be added as the HIGHEST confidence evidence because we have more then one
+1120 * source corroborating the value.
+1121 *
+1122 * @param classes a collection of class name information
+1123 * @param value the value to check to see if it contains a package name
+1124 * @param evidence the evidence collection to add new entries too
+1125 */
+1126privatevoid addMatchingValues(ArrayList<ClassNameInformation> classes, String value, EvidenceCollection evidence) {
+1127if (value == null || value.isEmpty()) {
+1128return;
+1129 }
+1130final String text = value.toLowerCase();
+1131for (ClassNameInformation cni : classes) {
+1132for (String key : cni.getPackageStructure()) {
+1133if (text.contains(key)) { //note, package structure elements are already lowercase.
+1134 evidence.addEvidence("jar", "package name", key, Confidence.HIGHEST);
+1135 }
+1136 }
+1137 }
+1138 }
+1139
+1140/**
+1141 * Simple check to see if the attribute from a manifest is just a package name.
+1142 *
+1143 * @param key the key of the value to check
+1144 * @param value the value to check
+1145 * @return true if the value looks like a java package name, otherwise false
+1146 */
+1147privateboolean isPackage(String key, String value) {
+1148
+1149return !key.matches(".*(version|title|vendor|name|license|description).*")
+1150 && value.matches("^([a-zA-Z_][a-zA-Z0-9_\\$]*(\\.[a-zA-Z_][a-zA-Z0-9_\\$]*)*)?$");
+1151
+1152 }
+1153
+1154/**
+1155 * Adds evidence from the POM to the dependency. This includes the GAV and in some situations the parent GAV if
+1156 * specified.
+1157 *
+1158 * @param dependency the dependency being analyzed
+1159 * @param pom the POM data
+1160 * @param pomProperties the properties file associated with the pom
+1161 */
+1162privatevoid addPomEvidence(Dependency dependency, Model pom, Properties pomProperties) {
+1163if (pom == null) {
+1164return;
1165 }
-1166final String version = interpolateString(pom.getVersion(), pomProperties);
-1167if (version != null && !version.isEmpty()) {
-1168 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST);
-1169 }
-1170
-1171finalParent parent = pom.getParent(); //grab parent GAV
-1172if (parent != null) {
-1173final String parentGroupId = interpolateString(parent.getGroupId(), pomProperties);
-1174if (parentGroupId != null && !parentGroupId.isEmpty()) {
-1175if (groupid == null || groupid.isEmpty()) {
-1176 dependency.getVendorEvidence().addEvidence("pom", "parent.groupid", parentGroupId, Confidence.HIGH);
-1177 } else {
-1178 dependency.getVendorEvidence().addEvidence("pom", "parent.groupid", parentGroupId, Confidence.MEDIUM);
-1179 }
-1180 dependency.getProductEvidence().addEvidence("pom", "parent.groupid", parentGroupId, Confidence.LOW);
-1181 }
-1182final String parentArtifactId = interpolateString(parent.getArtifactId(), pomProperties);
-1183if (parentArtifactId != null && !parentArtifactId.isEmpty()) {
-1184if (artifactid == null || artifactid.isEmpty()) {
-1185 dependency.getProductEvidence().addEvidence("pom", "parent.artifactid", parentArtifactId, Confidence.HIGH);
-1186 } else {
-1187 dependency.getProductEvidence().addEvidence("pom", "parent.artifactid", parentArtifactId, Confidence.MEDIUM);
-1188 }
-1189 dependency.getVendorEvidence().addEvidence("pom", "parent.artifactid", parentArtifactId, Confidence.LOW);
-1190 }
-1191final String parentVersion = interpolateString(parent.getVersion(), pomProperties);
-1192if (parentVersion != null && !parentVersion.isEmpty()) {
-1193if (version == null || version.isEmpty()) {
-1194 dependency.getVersionEvidence().addEvidence("pom", "parent.version", parentVersion, Confidence.HIGH);
-1195 } else {
-1196 dependency.getVersionEvidence().addEvidence("pom", "parent.version", parentVersion, Confidence.LOW);
-1197 }
-1198 }
-1199 }
-1200// org name
-1201finalOrganization org = pom.getOrganization();
-1202if (org != null && org.getName() != null) {
-1203final String orgName = interpolateString(org.getName(), pomProperties);
-1204if (orgName != null && !orgName.isEmpty()) {
-1205 dependency.getVendorEvidence().addEvidence("pom", "organization name", orgName, Confidence.HIGH);
+1166 String groupid = interpolateString(pom.getGroupId(), pomProperties);
+1167if (groupid != null && !groupid.isEmpty()) {
+1168if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
+1169 groupid = groupid.substring(4);
+1170 }
+1171 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGH);
+1172 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
+1173 }
+1174 String artifactid = interpolateString(pom.getArtifactId(), pomProperties);
+1175if (artifactid != null && !artifactid.isEmpty()) {
+1176if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
+1177 artifactid = artifactid.substring(4);
+1178 }
+1179 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGH);
+1180 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
+1181 }
+1182final String version = interpolateString(pom.getVersion(), pomProperties);
+1183if (version != null && !version.isEmpty()) {
+1184 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST);
+1185 }
+1186
+1187finalParent parent = pom.getParent(); //grab parent GAV
+1188if (parent != null) {
+1189final String parentGroupId = interpolateString(parent.getGroupId(), pomProperties);
+1190if (parentGroupId != null && !parentGroupId.isEmpty()) {
+1191if (groupid == null || groupid.isEmpty()) {
+1192 dependency.getVendorEvidence().addEvidence("pom", "parent.groupid", parentGroupId, Confidence.HIGH);
+1193 } else {
+1194 dependency.getVendorEvidence().addEvidence("pom", "parent.groupid", parentGroupId, Confidence.MEDIUM);
+1195 }
+1196 dependency.getProductEvidence().addEvidence("pom", "parent.groupid", parentGroupId, Confidence.LOW);
+1197 }
+1198final String parentArtifactId = interpolateString(parent.getArtifactId(), pomProperties);
+1199if (parentArtifactId != null && !parentArtifactId.isEmpty()) {
+1200if (artifactid == null || artifactid.isEmpty()) {
+1201 dependency.getProductEvidence().addEvidence("pom", "parent.artifactid", parentArtifactId, Confidence.HIGH);
+1202 } else {
+1203 dependency.getProductEvidence().addEvidence("pom", "parent.artifactid", parentArtifactId, Confidence.MEDIUM);
+1204 }
+1205 dependency.getVendorEvidence().addEvidence("pom", "parent.artifactid", parentArtifactId, Confidence.LOW);
1206 }
-1207 }
-1208//pom name
-1209final String pomName = interpolateString(pom.getName(), pomProperties);
-1210if (pomName != null && !pomName.isEmpty()) {
-1211 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
-1212 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
-1213 }
-1214
-1215//Description
-1216if (pom.getDescription() != null) {
-1217final String description = interpolateString(pom.getDescription(), pomProperties);
-1218if (description != null && !description.isEmpty()) {
-1219 addDescription(dependency, description, "pom", "description");
-1220 }
-1221 }
-1222 extractLicense(pom, pomProperties, dependency);
-1223 }
-1224
-1225/**
-1226 * Extracts the license information from the pom and adds it to the dependency.
-1227 *
-1228 * @param pom the pom object
-1229 * @param pomProperties the properties, used for string interpolation
-1230 * @param dependency the dependency to add license information too
-1231 */
-1232privatevoid extractLicense(Model pom, Properties pomProperties, Dependency dependency) {
-1233//license
-1234if (pom.getLicenses() != null) {
-1235 String license = null;
-1236for (License lic : pom.getLicenses().getLicense()) {
-1237 String tmp = null;
-1238if (lic.getName() != null) {
-1239 tmp = interpolateString(lic.getName(), pomProperties);
-1240 }
-1241if (lic.getUrl() != null) {
-1242if (tmp == null) {
-1243 tmp = interpolateString(lic.getUrl(), pomProperties);
-1244 } else {
-1245 tmp += ": " + interpolateString(lic.getUrl(), pomProperties);
-1246 }
-1247 }
-1248if (tmp == null) {
-1249continue;
-1250 }
-1251if (HTML_DETECTION_PATTERN.matcher(tmp).find()) {
-1252 tmp = Jsoup.parse(tmp).text();
-1253 }
-1254if (license == null) {
-1255 license = tmp;
-1256 } else {
-1257 license += "\n" + tmp;
-1258 }
-1259 }
-1260if (license != null) {
-1261 dependency.setLicense(license);
-1262 }
-1263 }
-1264 }
-1265
-1266/**
-1267 * Stores information about a class name.
-1268 */
-1269protectedstaticclassClassNameInformation {
-1270
-1271/**
-1272 * <p>
-1273 * Stores information about a given class name. This class will keep the fully qualified class name and a list
-1274 * of the important parts of the package structure. Up to the first four levels of the package structure are
-1275 * stored, excluding a leading "org" or "com". Example:</p>
-1276 * <code>ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer");
-1277 * System.out.println(obj.getName());
-1278 * for (String p : obj.getPackageStructure())
-1279 * System.out.println(p);
-1280 * </code>
-1281 * <p>
-1282 * Would result in:</p>
-1283 * <code>org.owasp.dependencycheck.analyzer.JarAnalyzer
-1284 * owasp
-1285 * dependencycheck
-1286 * analyzer
-1287 * jaranalyzer</code>
-1288 *
-1289 * @param className a fully qualified class name
-1290 */
-1291ClassNameInformation(String className) {
-1292 name = className;
-1293if (name.contains("/")) {
-1294final String[] tmp = className.toLowerCase().split("/");
-1295int start = 0;
-1296int end = 3;
-1297if ("com".equals(tmp[0]) || "org".equals(tmp[0])) {
-1298 start = 1;
-1299 end = 4;
-1300 }
-1301if (tmp.length <= end) {
-1302 end = tmp.length - 1;
-1303 }
-1304for (int i = start; i <= end; i++) {
-1305 packageStructure.add(tmp[i]);
-1306 }
-1307 } else {
-1308 packageStructure.add(name);
-1309 }
-1310 }
-1311/**
-1312 * The fully qualified class name.
-1313 */
-1314private String name;
-1315
-1316/**
-1317 * Get the value of name
-1318 *
-1319 * @return the value of name
-1320 */
-1321public String getName() {
-1322return name;
-1323 }
-1324
-1325/**
-1326 * Set the value of name
-1327 *
-1328 * @param name new value of name
+1207final String parentVersion = interpolateString(parent.getVersion(), pomProperties);
+1208if (parentVersion != null && !parentVersion.isEmpty()) {
+1209if (version == null || version.isEmpty()) {
+1210 dependency.getVersionEvidence().addEvidence("pom", "parent.version", parentVersion, Confidence.HIGH);
+1211 } else {
+1212 dependency.getVersionEvidence().addEvidence("pom", "parent.version", parentVersion, Confidence.LOW);
+1213 }
+1214 }
+1215 }
+1216// org name
+1217finalOrganization org = pom.getOrganization();
+1218if (org != null && org.getName() != null) {
+1219final String orgName = interpolateString(org.getName(), pomProperties);
+1220if (orgName != null && !orgName.isEmpty()) {
+1221 dependency.getVendorEvidence().addEvidence("pom", "organization name", orgName, Confidence.HIGH);
+1222 }
+1223 }
+1224//pom name
+1225final String pomName = interpolateString(pom.getName(), pomProperties);
+1226if (pomName != null && !pomName.isEmpty()) {
+1227 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
+1228 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
+1229 }
+1230
+1231//Description
+1232if (pom.getDescription() != null) {
+1233final String description = interpolateString(pom.getDescription(), pomProperties);
+1234if (description != null && !description.isEmpty()) {
+1235 addDescription(dependency, description, "pom", "description");
+1236 }
+1237 }
+1238 extractLicense(pom, pomProperties, dependency);
+1239 }
+1240
+1241/**
+1242 * Extracts the license information from the pom and adds it to the dependency.
+1243 *
+1244 * @param pom the pom object
+1245 * @param pomProperties the properties, used for string interpolation
+1246 * @param dependency the dependency to add license information too
+1247 */
+1248privatevoid extractLicense(Model pom, Properties pomProperties, Dependency dependency) {
+1249//license
+1250if (pom.getLicenses() != null) {
+1251 String license = null;
+1252for (License lic : pom.getLicenses().getLicense()) {
+1253 String tmp = null;
+1254if (lic.getName() != null) {
+1255 tmp = interpolateString(lic.getName(), pomProperties);
+1256 }
+1257if (lic.getUrl() != null) {
+1258if (tmp == null) {
+1259 tmp = interpolateString(lic.getUrl(), pomProperties);
+1260 } else {
+1261 tmp += ": " + interpolateString(lic.getUrl(), pomProperties);
+1262 }
+1263 }
+1264if (tmp == null) {
+1265continue;
+1266 }
+1267if (HTML_DETECTION_PATTERN.matcher(tmp).find()) {
+1268 tmp = Jsoup.parse(tmp).text();
+1269 }
+1270if (license == null) {
+1271 license = tmp;
+1272 } else {
+1273 license += "\n" + tmp;
+1274 }
+1275 }
+1276if (license != null) {
+1277 dependency.setLicense(license);
+1278 }
+1279 }
+1280 }
+1281
+1282/**
+1283 * Stores information about a class name.
+1284 */
+1285protectedstaticclassClassNameInformation {
+1286
+1287/**
+1288 * <p>
+1289 * Stores information about a given class name. This class will keep the fully qualified class name and a list
+1290 * of the important parts of the package structure. Up to the first four levels of the package structure are
+1291 * stored, excluding a leading "org" or "com". Example:</p>
+1292 * <code>ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer");
+1293 * System.out.println(obj.getName());
+1294 * for (String p : obj.getPackageStructure())
+1295 * System.out.println(p);
+1296 * </code>
+1297 * <p>
+1298 * Would result in:</p>
+1299 * <code>org.owasp.dependencycheck.analyzer.JarAnalyzer
+1300 * owasp
+1301 * dependencycheck
+1302 * analyzer
+1303 * jaranalyzer</code>
+1304 *
+1305 * @param className a fully qualified class name
+1306 */
+1307ClassNameInformation(String className) {
+1308 name = className;
+1309if (name.contains("/")) {
+1310final String[] tmp = className.toLowerCase().split("/");
+1311int start = 0;
+1312int end = 3;
+1313if ("com".equals(tmp[0]) || "org".equals(tmp[0])) {
+1314 start = 1;
+1315 end = 4;
+1316 }
+1317if (tmp.length <= end) {
+1318 end = tmp.length - 1;
+1319 }
+1320for (int i = start; i <= end; i++) {
+1321 packageStructure.add(tmp[i]);
+1322 }
+1323 } else {
+1324 packageStructure.add(name);
+1325 }
+1326 }
+1327/**
+1328 * The fully qualified class name.1329 */
-1330publicvoid setName(String name) {
-1331this.name = name;
-1332 }
-1333/**
-1334 * Up to the first four levels of the package structure, excluding a leading "org" or "com".
-1335 */
-1336privatefinal ArrayList<String> packageStructure = new ArrayList<String>();
-1337
-1338/**
-1339 * Get the value of packageStructure
-1340 *
-1341 * @return the value of packageStructure
-1342 */
-1343public ArrayList<String> getPackageStructure() {
-1344return packageStructure;
-1345 }
-1346 }
-1347
-1348/**
-1349 * Retrieves the next temporary directory to extract an archive too.
-1350 *
-1351 * @return a directory
-1352 * @throws AnalysisException thrown if unable to create temporary directory
-1353 */
-1354private File getNextTempDirectory() throws AnalysisException {
-1355 dirCount += 1;
-1356final File directory = new File(tempFileLocation, String.valueOf(dirCount));
-1357//getting an exception for some directories not being able to be created; might be because the directory already exists?
-1358if (directory.exists()) {
-1359return getNextTempDirectory();
-1360 }
-1361if (!directory.mkdirs()) {
-1362final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath());
-1363thrownewAnalysisException(msg);
-1364 }
-1365return directory;
-1366 }
-1367 }
+1330private String name;
+1331
+1332/**
+1333 * Get the value of name
+1334 *
+1335 * @return the value of name
+1336 */
+1337public String getName() {
+1338return name;
+1339 }
+1340
+1341/**
+1342 * Set the value of name
+1343 *
+1344 * @param name new value of name
+1345 */
+1346publicvoid setName(String name) {
+1347this.name = name;
+1348 }
+1349/**
+1350 * Up to the first four levels of the package structure, excluding a leading "org" or "com".
+1351 */
+1352privatefinal ArrayList<String> packageStructure = new ArrayList<String>();
+1353
+1354/**
+1355 * Get the value of packageStructure
+1356 *
+1357 * @return the value of packageStructure
+1358 */
+1359public ArrayList<String> getPackageStructure() {
+1360return packageStructure;
+1361 }
+1362 }
+1363
+1364/**
+1365 * Retrieves the next temporary directory to extract an archive too.
+1366 *
+1367 * @return a directory
+1368 * @throws AnalysisException thrown if unable to create temporary directory
+1369 */
+1370private File getNextTempDirectory() throws AnalysisException {
+1371 dirCount += 1;
+1372final File directory = new File(tempFileLocation, String.valueOf(dirCount));
+1373//getting an exception for some directories not being able to be created; might be because the directory already exists?
+1374if (directory.exists()) {
+1375return getNextTempDirectory();
+1376 }
+1377if (!directory.mkdirs()) {
+1378final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath());
+1379thrownewAnalysisException(msg);
+1380 }
+1381return directory;
+1382 }
+1383 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JavaScriptAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JavaScriptAnalyzer.html
index 0eabf943c..882cd69d4 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JavaScriptAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JavaScriptAnalyzer.html
@@ -37,107 +37,116 @@
29import org.owasp.dependencycheck.Engine;
30import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
31import org.owasp.dependencycheck.dependency.Dependency;
-32
-33/**
-34 *
-35 * Used to analyze a JavaScript file to gather information to aid in identification of a CPE identifier.
-36 *
-37 * @author Jeremy Long <jeremy.long@owasp.org>
-38 */
-39publicclassJavaScriptAnalyzerextendsAbstractAnalyzerimplementsAnalyzer {
-40
-41//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
+32import org.owasp.dependencycheck.utils.Settings;
+33
+34/**
+35 *
+36 * Used to analyze a JavaScript file to gather information to aid in identification of a CPE identifier.
+37 *
+38 * @author Jeremy Long <jeremy.long@owasp.org>
+39 */
+40publicclassJavaScriptAnalyzerextendsAbstractFileTypeAnalyzer {
+4142/**
-43 * The name of the analyzer.
+43 * The logger.44 */
-45privatestaticfinal String ANALYZER_NAME = "JavaScript Analyzer";
-46/**
-47 * The phase that this analyzer is intended to run in.
-48 */
-49privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
-50/**
-51 * The set of file extensions supported by this analyzer.
-52 */
-53privatestaticfinal Set<String> EXTENSIONS = newHashSet("js");
-54
-55/**
-56 * Returns a list of file EXTENSIONS supported by this analyzer.
-57 *
-58 * @return a list of file EXTENSIONS supported by this analyzer.
-59 */
-60 @Override
-61public Set<String> getSupportedExtensions() {
-62return EXTENSIONS;
-63 }
-64
-65/**
-66 * Returns the name of the analyzer.
-67 *
-68 * @return the name of the analyzer.
-69 */
-70 @Override
-71public String getName() {
-72return ANALYZER_NAME;
-73 }
-74
-75/**
-76 * Returns whether or not this analyzer can process the given extension.
-77 *
-78 * @param extension the file extension to test for support.
-79 * @return whether or not the specified file extension is supported by this analyzer.
-80 */
-81 @Override
-82publicboolean supportsExtension(String extension) {
-83return EXTENSIONS.contains(extension);
-84 }
-85
-86/**
-87 * Returns the phase that the analyzer is intended to run in.
-88 *
-89 * @return the phase that the analyzer is intended to run in.
-90 */
-91 @Override
-92publicAnalysisPhase getAnalysisPhase() {
-93return ANALYSIS_PHASE;
-94 }
-95//</editor-fold>
-96
-97/**
-98 * Loads a specified JavaScript file and collects information from the copyright information contained within.
-99 *
-100 * @param dependency the dependency to analyze.
-101 * @param engine the engine that is scanning the dependencies
-102 * @throws AnalysisException is thrown if there is an error reading the JavaScript file.
-103 */
-104 @Override
-105publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-106 BufferedReader fin = null;;
-107try {
-108// /\*([^\*][^/]|[\r\n\f])+?\*/
-109final Pattern extractComments = Pattern.compile("(/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/)|(//.*)", Pattern.MULTILINE);
-110 File file = dependency.getActualFile();
-111 fin = new BufferedReader(new FileReader(file));
-112 StringBuilder sb = new StringBuilder(2000);
-113 String text;
-114while ((text = fin.readLine()) != null) {
-115 sb.append(text);
-116 }
-117 } catch (FileNotFoundException ex) {
-118final String msg = String.format("Dependency file not found: '%s'", dependency.getActualFilePath());
-119thrownewAnalysisException(msg, ex);
-120 } catch (IOException ex) {
-121 Logger.getLogger(JavaScriptAnalyzer.class.getName()).log(Level.SEVERE, null, ex);
-122 } finally {
-123if (fin != null) {
-124try {
-125 fin.close();
-126 } catch (IOException ex) {
-127 Logger.getLogger(JavaScriptAnalyzer.class.getName()).log(Level.FINEST, null, ex);
-128 }
-129 }
-130 }
-131 }
-132 }
+45privatestaticfinal Logger LOGGER = Logger.getLogger(JavaScriptAnalyzer.class.getName());
+46
+47//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
+48/**
+49 * The name of the analyzer.
+50 */
+51privatestaticfinal String ANALYZER_NAME = "JavaScript Analyzer";
+52/**
+53 * The phase that this analyzer is intended to run in.
+54 */
+55privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
+56/**
+57 * The set of file extensions supported by this analyzer.
+58 */
+59privatestaticfinal Set<String> EXTENSIONS = newHashSet("js");
+60
+61/**
+62 * Returns a list of file EXTENSIONS supported by this analyzer.
+63 *
+64 * @return a list of file EXTENSIONS supported by this analyzer.
+65 */
+66 @Override
+67public Set<String> getSupportedExtensions() {
+68return EXTENSIONS;
+69 }
+70
+71/**
+72 * Returns the name of the analyzer.
+73 *
+74 * @return the name of the analyzer.
+75 */
+76 @Override
+77public String getName() {
+78return ANALYZER_NAME;
+79 }
+80
+81/**
+82 * Returns the phase that the analyzer is intended to run in.
+83 *
+84 * @return the phase that the analyzer is intended to run in.
+85 */
+86 @Override
+87publicAnalysisPhase getAnalysisPhase() {
+88return ANALYSIS_PHASE;
+89 }
+90//</editor-fold>
+91/**
+92 * Returns the key used in the properties file to reference the analyzer's enabled property.
+93 *
+94 * @return the analyzer's enabled property setting key
+95 */
+96 @Override
+97protected String getAnalyzerEnabledSettingKey() {
+98return Settings.KEYS.ANALYZER_JAVASCRIPT_ENABLED;
+99 }
+100
+101/**
+102 * Loads a specified JavaScript file and collects information from the copyright information contained within.
+103 *
+104 * @param dependency the dependency to analyze.
+105 * @param engine the engine that is scanning the dependencies
+106 * @throws AnalysisException is thrown if there is an error reading the JavaScript file.
+107 */
+108 @Override
+109publicvoid analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
+110 BufferedReader fin = null;;
+111try {
+112// /\*([^\*][^/]|[\r\n\f])+?\*/
+113final Pattern extractComments = Pattern.compile("(/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/)|(//.*)", Pattern.MULTILINE);
+114 File file = dependency.getActualFile();
+115 fin = new BufferedReader(new FileReader(file));
+116 StringBuilder sb = new StringBuilder(2000);
+117 String text;
+118while ((text = fin.readLine()) != null) {
+119 sb.append(text);
+120 }
+121 } catch (FileNotFoundException ex) {
+122final String msg = String.format("Dependency file not found: '%s'", dependency.getActualFilePath());
+123thrownewAnalysisException(msg, ex);
+124 } catch (IOException ex) {
+125 LOGGER.log(Level.SEVERE, null, ex);
+126 } finally {
+127if (fin != null) {
+128try {
+129 fin.close();
+130 } catch (IOException ex) {
+131 LOGGER.log(Level.FINEST, null, ex);
+132 }
+133 }
+134 }
+135 }
+136
+137 @Override
+138protectedvoid initializeFileTypeAnalyzer() throws Exception {
+139
+140 }
+141 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html
index 309fa9ce7..819504a89 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html
@@ -54,20 +54,20 @@
46 *47 * @author colezlaw48 */
-49publicclassNexusAnalyzerextendsAbstractAnalyzer {
+49publicclassNexusAnalyzerextendsAbstractFileTypeAnalyzer {
5051/**
-52 * The logger
+52 * The logger.53 */54privatestaticfinal Logger LOGGER = Logger.getLogger(NexusAnalyzer.class.getName());
5556/**
-57 * The name of the analyzer
+57 * The name of the analyzer.58 */59privatestaticfinal String ANALYZER_NAME = "Nexus Analyzer";
6061/**
-62 * The phase in which the analyzer runs
+62 * The phase in which the analyzer runs.63 */64privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
65
@@ -77,127 +77,113 @@
69privatestaticfinal Set<String> SUPPORTED_EXTENSIONS = newHashSet("jar");
7071/**
-72 * Whether this is actually enabled. Will get set during initialization.
+72 * The Nexus Search to be set up for this analyzer.73 */
-74privateboolean enabled = false;
+74privateNexusSearch searcher;
7576/**
-77 * The Nexus Search to be set up for this analyzer.
-78 */
-79privateNexusSearch searcher;
-80
-81/**
-82 * Initializes the analyzer once before any analysis is performed.
-83 *
-84 * @throws Exception if there's an error during initialization
-85 */
-86 @Override
-87publicvoid initialize() throws Exception {
-88 enabled = Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED);
-89 LOGGER.fine("Initializing Nexus Analyzer");
-90 LOGGER.fine(String.format("Nexus Analyzer enabled: %s", enabled));
-91if (enabled) {
-92final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
-93 LOGGER.fine(String.format("Nexus Analyzer URL: %s", searchUrl));
-94try {
-95 searcher = newNexusSearch(new URL(searchUrl));
-96if (!searcher.preflightRequest()) {
-97 LOGGER.warning("There was an issue getting Nexus status. Disabling analyzer.");
-98 enabled = false;
-99 }
-100 } catch (MalformedURLException mue) {
-101// I know that initialize can throw an exception, but we'll
-102// just disable the analyzer if the URL isn't valid
-103 LOGGER.warning(String.format("Property %s not a valid URL. Nexus Analyzer disabled", searchUrl));
-104 enabled = false;
-105 }
-106 }
-107 }
-108
-109/**
-110 * Returns the analyzer's name.
-111 *
-112 * @return the name of the analyzer
-113 */
-114 @Override
-115public String getName() {
-116return ANALYZER_NAME;
-117 }
-118
-119/**
-120 * Returns the analysis phase under which the analyzer runs.
-121 *
-122 * @return the phase under which this analyzer runs
-123 */
-124 @Override
-125publicAnalysisPhase getAnalysisPhase() {
-126return ANALYSIS_PHASE;
-127 }
-128
-129/**
-130 * Returns the extensions for which this Analyzer runs.
-131 *
-132 * @return the extensions for which this Analyzer runs
-133 */
-134 @Override
-135public Set<String> getSupportedExtensions() {
-136return SUPPORTED_EXTENSIONS;
-137 }
-138
-139/**
-140 * Determines whether the incoming extension is supported.
-141 *
-142 * @param extension the extension to check for support
-143 * @return whether the extension is supported
-144 */
-145 @Override
-146publicboolean supportsExtension(String extension) {
-147return SUPPORTED_EXTENSIONS.contains(extension);
-148 }
-149
-150/**
-151 * Performs the analysis.
-152 *
-153 * @param dependency the dependency to analyze
-154 * @param engine the engine
-155 * @throws AnalysisException when there's an exception during analysis
-156 */
-157 @Override
-158publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-159// Make a quick exit if this analyzer is disabled
-160if (!enabled) {
-161return;
-162 }
-163
-164try {
-165finalMavenArtifact ma = searcher.searchSha1(dependency.getSha1sum());
-166if (ma.getGroupId() != null && !"".equals(ma.getGroupId())) {
-167 dependency.getVendorEvidence().addEvidence("nexus", "groupid", ma.getGroupId(), Confidence.HIGH);
-168 }
-169if (ma.getArtifactId() != null && !"".equals(ma.getArtifactId())) {
-170 dependency.getProductEvidence().addEvidence("nexus", "artifactid", ma.getArtifactId(), Confidence.HIGH);
-171 }
-172if (ma.getVersion() != null && !"".equals(ma.getVersion())) {
-173 dependency.getVersionEvidence().addEvidence("nexus", "version", ma.getVersion(), Confidence.HIGH);
-174 }
-175if (ma.getArtifactUrl() != null && !"".equals(ma.getArtifactUrl())) {
-176 dependency.addIdentifier("maven", ma.toString(), ma.getArtifactUrl(), Confidence.HIGHEST);
-177 }
-178 } catch (IllegalArgumentException iae) {
-179//dependency.addAnalysisException(new AnalysisException("Invalid SHA-1"));
-180 LOGGER.info(String.format("invalid sha-1 hash on %s", dependency.getFileName()));
-181 } catch (FileNotFoundException fnfe) {
-182//dependency.addAnalysisException(new AnalysisException("Artifact not found on repository"));
-183 LOGGER.fine(String.format("Artificat not found in repository '%s'", dependency.getFileName()));
-184 LOGGER.log(Level.FINE, fnfe.getMessage(), fnfe);
-185 } catch (IOException ioe) {
-186//dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe));
-187 LOGGER.log(Level.FINE, "Could not connect to nexus repository", ioe);
-188 }
-189 }
-190 }
-191
-192// vim: cc=120:sw=4:ts=4:sts=4
+77 * Initializes the analyzer once before any analysis is performed.
+78 *
+79 * @throws Exception if there's an error during initialization
+80 */
+81 @Override
+82publicvoid initializeFileTypeAnalyzer() throws Exception {
+83 LOGGER.fine("Initializing Nexus Analyzer");
+84 LOGGER.fine(String.format("Nexus Analyzer enabled: %s", isEnabled()));
+85if (isEnabled()) {
+86final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
+87 LOGGER.fine(String.format("Nexus Analyzer URL: %s", searchUrl));
+88try {
+89 searcher = newNexusSearch(new URL(searchUrl));
+90if (!searcher.preflightRequest()) {
+91 LOGGER.warning("There was an issue getting Nexus status. Disabling analyzer.");
+92 setEnabled(false);
+93 }
+94 } catch (MalformedURLException mue) {
+95// I know that initialize can throw an exception, but we'll
+96// just disable the analyzer if the URL isn't valid
+97 LOGGER.warning(String.format("Property %s not a valid URL. Nexus Analyzer disabled", searchUrl));
+98 setEnabled(false);
+99 }
+100 }
+101 }
+102
+103/**
+104 * Returns the analyzer's name.
+105 *
+106 * @return the name of the analyzer
+107 */
+108 @Override
+109public String getName() {
+110return ANALYZER_NAME;
+111 }
+112
+113/**
+114 * Returns the key used in the properties file to reference the analyzer's enabled property.
+115 *
+116 * @return the analyzer's enabled property setting key
+117 */
+118 @Override
+119protected String getAnalyzerEnabledSettingKey() {
+120return Settings.KEYS.ANALYZER_NEXUS_ENABLED;
+121 }
+122
+123/**
+124 * Returns the analysis phase under which the analyzer runs.
+125 *
+126 * @return the phase under which this analyzer runs
+127 */
+128 @Override
+129publicAnalysisPhase getAnalysisPhase() {
+130return ANALYSIS_PHASE;
+131 }
+132
+133/**
+134 * Returns the extensions for which this Analyzer runs.
+135 *
+136 * @return the extensions for which this Analyzer runs
+137 */
+138 @Override
+139public Set<String> getSupportedExtensions() {
+140return SUPPORTED_EXTENSIONS;
+141 }
+142
+143/**
+144 * Performs the analysis.
+145 *
+146 * @param dependency the dependency to analyze
+147 * @param engine the engine
+148 * @throws AnalysisException when there's an exception during analysis
+149 */
+150 @Override
+151publicvoid analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
+152try {
+153finalMavenArtifact ma = searcher.searchSha1(dependency.getSha1sum());
+154if (ma.getGroupId() != null && !"".equals(ma.getGroupId())) {
+155 dependency.getVendorEvidence().addEvidence("nexus", "groupid", ma.getGroupId(), Confidence.HIGH);
+156 }
+157if (ma.getArtifactId() != null && !"".equals(ma.getArtifactId())) {
+158 dependency.getProductEvidence().addEvidence("nexus", "artifactid", ma.getArtifactId(), Confidence.HIGH);
+159 }
+160if (ma.getVersion() != null && !"".equals(ma.getVersion())) {
+161 dependency.getVersionEvidence().addEvidence("nexus", "version", ma.getVersion(), Confidence.HIGH);
+162 }
+163if (ma.getArtifactUrl() != null && !"".equals(ma.getArtifactUrl())) {
+164 dependency.addIdentifier("maven", ma.toString(), ma.getArtifactUrl(), Confidence.HIGHEST);
+165 }
+166 } catch (IllegalArgumentException iae) {
+167//dependency.addAnalysisException(new AnalysisException("Invalid SHA-1"));
+168 LOGGER.info(String.format("invalid sha-1 hash on %s", dependency.getFileName()));
+169 } catch (FileNotFoundException fnfe) {
+170//dependency.addAnalysisException(new AnalysisException("Artifact not found on repository"));
+171 LOGGER.fine(String.format("Artificat not found in repository '%s'", dependency.getFileName()));
+172 LOGGER.log(Level.FINE, fnfe.getMessage(), fnfe);
+173 } catch (IOException ioe) {
+174//dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe));
+175 LOGGER.log(Level.FINE, "Could not connect to nexus repository", ioe);
+176 }
+177 }
+178 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.html
index 84dbf4850..ed376853d 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.html
@@ -26,137 +26,142 @@
18package org.owasp.dependencycheck.analyzer;
1920import java.io.FileInputStream;
-21import java.util.Set;
-22import java.util.logging.Level;
-23import java.util.logging.Logger;
-24import org.owasp.dependencycheck.Engine;
-25import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
-26import org.owasp.dependencycheck.data.nuget.NugetPackage;
-27import org.owasp.dependencycheck.data.nuget.NuspecParser;
-28import org.owasp.dependencycheck.data.nuget.XPathNuspecParser;
-29import org.owasp.dependencycheck.dependency.Confidence;
-30import org.owasp.dependencycheck.dependency.Dependency;
-31
-32/**
-33 * Analyzer which will parse a Nuspec file to gather module information.
-34 *
-35 * @author colezlaw
-36 */
-37publicclassNuspecAnalyzerextendsAbstractAnalyzer {
-38
-39/**
-40 * The logger
-41 */
-42privatestaticfinal Logger LOGGER = Logger.getLogger(NuspecAnalyzer.class.getName());
-43
-44/**
-45 * The name of the analyzer
-46 */
-47privatestaticfinal String ANALYZER_NAME = "Nuspec Analyzer";
-48
-49/**
-50 * The phase in which the analyzer runs
-51 */
-52privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
-53
-54/**
-55 * The types of files on which this will work.
-56 */
-57privatestaticfinal Set<String> SUPPORTED_EXTENSIONS = newHashSet("nuspec");
-58
-59/**
-60 * Initializes the analyzer once before any analysis is performed.
-61 *
-62 * @throws Exception if there's an error during initialization
-63 */
-64 @Override
-65publicvoid initialize() throws Exception {
-66 }
-67
-68/**
-69 * Returns the analyzer's name.
-70 *
-71 * @return the name of the analyzer
-72 */
-73 @Override
-74public String getName() {
-75return ANALYZER_NAME;
-76 }
-77
-78/**
-79 * Returns the analysis phase under which the analyzer runs.
-80 *
-81 * @return the phase under which this analyzer runs
-82 */
-83 @Override
-84publicAnalysisPhase getAnalysisPhase() {
-85return ANALYSIS_PHASE;
-86 }
-87
-88/**
-89 * Returns the extensions for which this Analyzer runs.
-90 *
-91 * @return the extensions for which this Analyzer runs
-92 */
-93 @Override
-94public Set<String> getSupportedExtensions() {
-95return SUPPORTED_EXTENSIONS;
-96 }
-97
-98/**
-99 * Determines whether the incoming extension is supported.
-100 *
-101 * @param extension the extension to check for support
-102 * @return whether the extension is supported
-103 */
-104 @Override
-105publicboolean supportsExtension(String extension) {
-106return SUPPORTED_EXTENSIONS.contains(extension);
-107 }
-108
-109/**
-110 * Performs the analysis.
-111 *
-112 * @param dependency the dependency to analyze
-113 * @param engine the engine
-114 * @throws AnalysisException when there's an exception during analysis
-115 */
-116 @Override
-117publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-118 LOGGER.log(Level.INFO, "Checking Nuspec file {0}", dependency.toString());
-119try {
-120finalNuspecParser parser = newXPathNuspecParser();
-121NugetPackage np = null;
-122 FileInputStream fis = null;
-123try {
-124 fis = new FileInputStream(dependency.getActualFilePath());
-125 np = parser.parse(fis);
-126 } finally {
-127if (fis != null) {
-128try {
-129 fis.close();
-130 } catch (Throwable e) {
-131 LOGGER.fine("Error closing input stream");
-132 }
-133 }
-134 }
-135
-136if (np.getOwners() != null) {
-137 dependency.getVendorEvidence().addEvidence("nuspec", "owners", np.getOwners(), Confidence.HIGHEST);
-138 }
-139 dependency.getVendorEvidence().addEvidence("nuspec", "authors", np.getAuthors(), Confidence.HIGH);
-140 dependency.getVersionEvidence().addEvidence("nuspec", "version", np.getVersion(), Confidence.HIGHEST);
-141 dependency.getProductEvidence().addEvidence("nuspec", "id", np.getId(), Confidence.HIGHEST);
-142if (np.getTitle() != null) {
-143 dependency.getProductEvidence().addEvidence("nuspec", "title", np.getTitle(), Confidence.MEDIUM);
-144 }
-145 } catch (Throwable e) {
-146thrownewAnalysisException(e);
-147 }
-148 }
-149 }
-150
-151// vim: cc=120:sw=4:ts=4:sts=4
+21import java.io.FileNotFoundException;
+22import java.io.IOException;
+23import java.util.Set;
+24import java.util.logging.Level;
+25import java.util.logging.Logger;
+26import org.owasp.dependencycheck.Engine;
+27import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+28import org.owasp.dependencycheck.data.nuget.NugetPackage;
+29import org.owasp.dependencycheck.data.nuget.NuspecParseException;
+30import org.owasp.dependencycheck.data.nuget.NuspecParser;
+31import org.owasp.dependencycheck.data.nuget.XPathNuspecParser;
+32import org.owasp.dependencycheck.dependency.Confidence;
+33import org.owasp.dependencycheck.dependency.Dependency;
+34import org.owasp.dependencycheck.utils.Settings;
+35
+36/**
+37 * Analyzer which will parse a Nuspec file to gather module information.
+38 *
+39 * @author colezlaw
+40 */
+41publicclassNuspecAnalyzerextendsAbstractFileTypeAnalyzer {
+42
+43/**
+44 * The logger.
+45 */
+46privatestaticfinal Logger LOGGER = Logger.getLogger(NuspecAnalyzer.class.getName());
+47
+48/**
+49 * The name of the analyzer.
+50 */
+51privatestaticfinal String ANALYZER_NAME = "Nuspec Analyzer";
+52
+53/**
+54 * The phase in which the analyzer runs.
+55 */
+56privatestaticfinalAnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
+57
+58/**
+59 * The types of files on which this will work.
+60 */
+61privatestaticfinal Set<String> SUPPORTED_EXTENSIONS = newHashSet("nuspec");
+62
+63/**
+64 * Initializes the analyzer once before any analysis is performed.
+65 *
+66 * @throws Exception if there's an error during initialization
+67 */
+68 @Override
+69publicvoid initializeFileTypeAnalyzer() throws Exception {
+70 }
+71
+72/**
+73 * Returns the analyzer's name.
+74 *
+75 * @return the name of the analyzer
+76 */
+77 @Override
+78public String getName() {
+79return ANALYZER_NAME;
+80 }
+81
+82/**
+83 * Returns the key used in the properties file to reference the analyzer's enabled property.
+84 *
+85 * @return the analyzer's enabled property setting key
+86 */
+87 @Override
+88protected String getAnalyzerEnabledSettingKey() {
+89return Settings.KEYS.ANALYZER_NUSPEC_ENABLED;
+90 }
+91
+92/**
+93 * Returns the analysis phase under which the analyzer runs.
+94 *
+95 * @return the phase under which this analyzer runs
+96 */
+97 @Override
+98publicAnalysisPhase getAnalysisPhase() {
+99return ANALYSIS_PHASE;
+100 }
+101
+102/**
+103 * Returns the extensions for which this Analyzer runs.
+104 *
+105 * @return the extensions for which this Analyzer runs
+106 */
+107 @Override
+108public Set<String> getSupportedExtensions() {
+109return SUPPORTED_EXTENSIONS;
+110 }
+111
+112/**
+113 * Performs the analysis.
+114 *
+115 * @param dependency the dependency to analyze
+116 * @param engine the engine
+117 * @throws AnalysisException when there's an exception during analysis
+118 */
+119 @Override
+120publicvoid analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
+121 LOGGER.log(Level.FINE, "Checking Nuspec file {0}", dependency.toString());
+122try {
+123finalNuspecParser parser = newXPathNuspecParser();
+124NugetPackage np = null;
+125 FileInputStream fis = null;
+126try {
+127 fis = new FileInputStream(dependency.getActualFilePath());
+128 np = parser.parse(fis);
+129 } catch (NuspecParseException ex) {
+130thrownewAnalysisException(ex);
+131 } catch (FileNotFoundException ex) {
+132thrownewAnalysisException(ex);
+133 } finally {
+134if (fis != null) {
+135try {
+136 fis.close();
+137 } catch (IOException e) {
+138 LOGGER.fine("Error closing input stream");
+139 }
+140 }
+141 }
+142
+143if (np.getOwners() != null) {
+144 dependency.getVendorEvidence().addEvidence("nuspec", "owners", np.getOwners(), Confidence.HIGHEST);
+145 }
+146 dependency.getVendorEvidence().addEvidence("nuspec", "authors", np.getAuthors(), Confidence.HIGH);
+147 dependency.getVersionEvidence().addEvidence("nuspec", "version", np.getVersion(), Confidence.HIGHEST);
+148 dependency.getProductEvidence().addEvidence("nuspec", "id", np.getId(), Confidence.HIGHEST);
+149if (np.getTitle() != null) {
+150 dependency.getProductEvidence().addEvidence("nuspec", "title", np.getTitle(), Confidence.MEDIUM);
+151 }
+152 } catch (Throwable e) {
+153thrownewAnalysisException(e);
+154 }
+155 }
+156 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html
index b53144a7c..c95329854 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html
@@ -25,51 +25,51 @@
17 */18package org.owasp.dependencycheck.analyzer;
19
-20import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
-21import java.io.IOException;
-22import java.sql.SQLException;
-23import java.util.List;
-24import java.util.Set;
-25import org.owasp.dependencycheck.Engine;
-26import org.owasp.dependencycheck.data.nvdcve.CveDB;
-27import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
-28import org.owasp.dependencycheck.dependency.Dependency;
-29import org.owasp.dependencycheck.dependency.Identifier;
-30import org.owasp.dependencycheck.dependency.Vulnerability;
-31
-32/**
-33 * NvdCveAnalyzer is a utility class that takes a project dependency and attempts to discern if there is an associated
-34 * CVEs. It uses the the identifiers found by other analyzers to lookup the CVE data.
-35 *
-36 * @author Jeremy Long <jeremy.long@owasp.org>
-37 */
-38publicclassNvdCveAnalyzerimplementsAnalyzer {
-39
-40/**
-41 * The maximum number of query results to return.
-42 */
-43staticfinalint MAX_QUERY_RESULTS = 100;
-44/**
-45 * The CVE Index.
-46 */
-47privateCveDB cveDB;
-48
-49/**
-50 * Opens the data source.
-51 *
-52 * @throws SQLException thrown when there is a SQL Exception
-53 * @throws IOException thrown when there is an IO Exception
-54 * @throws DatabaseException thrown when there is a database exceptions
-55 * @throws ClassNotFoundException thrown if the h2 database driver cannot be loaded
-56 */
-57publicvoid open() throws SQLException, IOException, DatabaseException, ClassNotFoundException {
-58 cveDB = newCveDB();
-59 cveDB.open();
-60 }
-61
-62/**
-63 * Closes the data source.
-64 */
+20import java.io.IOException;
+21import java.sql.SQLException;
+22import java.util.List;
+23import org.owasp.dependencycheck.Engine;
+24import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+25import org.owasp.dependencycheck.data.nvdcve.CveDB;
+26import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
+27import org.owasp.dependencycheck.dependency.Dependency;
+28import org.owasp.dependencycheck.dependency.Identifier;
+29import org.owasp.dependencycheck.dependency.Vulnerability;
+30
+31/**
+32 * NvdCveAnalyzer is a utility class that takes a project dependency and attempts to discern if there is an associated
+33 * CVEs. It uses the the identifiers found by other analyzers to lookup the CVE data.
+34 *
+35 * @author Jeremy Long <jeremy.long@owasp.org>
+36 */
+37publicclassNvdCveAnalyzerimplementsAnalyzer {
+38
+39/**
+40 * The maximum number of query results to return.
+41 */
+42staticfinalint MAX_QUERY_RESULTS = 100;
+43/**
+44 * The CVE Index.
+45 */
+46privateCveDB cveDB;
+47
+48/**
+49 * Opens the data source.
+50 *
+51 * @throws SQLException thrown when there is a SQL Exception
+52 * @throws IOException thrown when there is an IO Exception
+53 * @throws DatabaseException thrown when there is a database exceptions
+54 * @throws ClassNotFoundException thrown if the h2 database driver cannot be loaded
+55 */
+56publicvoid open() throws SQLException, IOException, DatabaseException, ClassNotFoundException {
+57 cveDB = newCveDB();
+58 cveDB.open();
+59 }
+60
+61/**
+62 * Closes the data source.
+63 */
+64 @Override
65publicvoid close() {
66 cveDB.close();
67 cveDB = null;
@@ -104,66 +104,51 @@
96 * @param engine The analysis engine97 * @throws AnalysisException is thrown if there is an issue analyzing the dependency98 */
-99publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
-100for (Identifier id : dependency.getIdentifiers()) {
-101if ("cpe".equals(id.getType())) {
-102try {
-103final String value = id.getValue();
-104final List<Vulnerability> vulns = cveDB.getVulnerabilities(value);
-105 dependency.getVulnerabilities().addAll(vulns);
-106 } catch (DatabaseException ex) {
-107thrownewAnalysisException(ex);
-108 }
-109 }
-110 }
-111 }
-112
-113/**
-114 * Returns true because this analyzer supports all dependency types.
-115 *
-116 * @return true.
-117 */
-118public Set<String> getSupportedExtensions() {
-119returnnull;
-120 }
-121
-122/**
-123 * Returns the name of this analyzer.
-124 *
-125 * @return the name of this analyzer.
-126 */
-127public String getName() {
-128return"NVD CVE Analyzer";
-129 }
-130
-131/**
-132 * Returns true because this analyzer supports all dependency types.
-133 *
-134 * @param extension the file extension of the dependency being analyzed.
-135 * @return true.
-136 */
-137publicboolean supportsExtension(String extension) {
-138returntrue;
-139 }
-140
-141/**
-142 * Returns the analysis phase that this analyzer should run in.
-143 *
-144 * @return the analysis phase that this analyzer should run in.
-145 */
-146publicAnalysisPhase getAnalysisPhase() {
-147return AnalysisPhase.FINDING_ANALYSIS;
-148 }
-149
-150/**
-151 * Opens the NVD CVE Lucene Index.
-152 *
-153 * @throws Exception is thrown if there is an issue opening the index.
-154 */
-155publicvoid initialize() throws Exception {
-156this.open();
-157 }
-158 }
+99 @Override
+100publicvoid analyze(Dependency dependency, Engine engine) throws AnalysisException {
+101for (Identifier id : dependency.getIdentifiers()) {
+102if ("cpe".equals(id.getType())) {
+103try {
+104final String value = id.getValue();
+105final List<Vulnerability> vulns = cveDB.getVulnerabilities(value);
+106 dependency.getVulnerabilities().addAll(vulns);
+107 } catch (DatabaseException ex) {
+108thrownewAnalysisException(ex);
+109 }
+110 }
+111 }
+112 }
+113
+114/**
+115 * Returns the name of this analyzer.
+116 *
+117 * @return the name of this analyzer.
+118 */
+119 @Override
+120public String getName() {
+121return"NVD CVE Analyzer";
+122 }
+123
+124/**
+125 * Returns the analysis phase that this analyzer should run in.
+126 *
+127 * @return the analysis phase that this analyzer should run in.
+128 */
+129 @Override
+130publicAnalysisPhase getAnalysisPhase() {
+131return AnalysisPhase.FINDING_ANALYSIS;
+132 }
+133
+134/**
+135 * Opens the database used to gather NVD CVE data.
+136 *
+137 * @throws Exception is thrown if there is an issue opening the index.
+138 */
+139 @Override
+140publicvoid initialize() throws Exception {
+141this.open();
+142 }
+143 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html
index e76b18fd5..5ce658a44 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.analyzer.exception
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.analyzer.exception
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html
index 859b1d787..1fbe7cc98 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.analyzer.exception
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.analyzer.exception
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-frame.html
index 437d45fe2..87e4c72fa 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-frame.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-frame.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.analyzer
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.analyzer
@@ -17,6 +17,9 @@
+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) 2014 Jeremy Long. All Rights Reserved.
+17 */
+18package org.owasp.dependencycheck.exception;
+19
+20import java.io.IOException;
+21
+22/**
+23 * An exception used when using @{link DependencyCheckScanAgent} to conduct a scan and the scan fails.
+24 *
+25 * @author Steve Springett <steve.springett@owasp.org>
+26 */
+27publicclassScanAgentExceptionextends IOException {
+28
+29/**
+30 * The serial version uid.
+31 */
+32privatestaticfinallong serialVersionUID = 1L;
+33
+34/**
+35 * Creates a new ScanAgentException.
+36 */
+37publicScanAgentException() {
+38super();
+39 }
+40
+41/**
+42 * Creates a new ScanAgentException.
+43 *
+44 * @param msg a message for the exception.
+45 */
+46publicScanAgentException(String msg) {
+47super(msg);
+48 }
+49
+50/**
+51 * Creates a new NoDataException.
+52 *
+53 * @param ex the cause of the exception.
+54 */
+55publicScanAgentException(Throwable ex) {
+56super(ex);
+57 }
+58
+59/**
+60 * Creates a new ScanAgentException.
+61 *
+62 * @param msg a message for the exception.
+63 * @param ex the cause of the exception.
+64 */
+65publicScanAgentException(String msg, Throwable ex) {
+66super(msg, ex);
+67 }
+68 }
+
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/generated/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/generated/package-frame.html
index 2783ca381..85a9a3600 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/generated/package-frame.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/generated/package-frame.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.jaxb.pom.generated
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.jaxb.pom.generated
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/generated/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/generated/package-summary.html
index 24edce7d9..c3b2bf8c5 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/generated/package-summary.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/generated/package-summary.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.jaxb.pom.generated
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.jaxb.pom.generated
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/package-frame.html
index 0720ebca8..b83315002 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/package-frame.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/package-frame.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.jaxb.pom
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.jaxb.pom
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/package-summary.html
index caf134ec9..1743f75f8 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/package-summary.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/jaxb/pom/package-summary.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.jaxb.pom
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.jaxb.pom
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/package-frame.html
index d3ad2b196..17f723a17 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/package-frame.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/package-frame.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/package-summary.html
index c8df99068..376ffda5b 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/package-summary.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/package-summary.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/reporting/ReportGenerator.html b/dependency-check-core/xref/org/owasp/dependencycheck/reporting/ReportGenerator.html
index 120be5c7f..472b4f32d 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/reporting/ReportGenerator.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/reporting/ReportGenerator.html
@@ -148,13 +148,13 @@
140 */141publicvoid generateReports(String outputDir, Format format) throws IOException, Exception {
142if (format == Format.XML || format == Format.ALL) {
-143 generateReport("XmlReport", outputDir + File.separator + "DependencyCheck-Report.xml");
+143 generateReport("XmlReport", outputDir + File.separator + "dependency-check-report.xml");
144 }
145if (format == Format.HTML || format == Format.ALL) {
-146 generateReport("HtmlReport", outputDir + File.separator + "DependencyCheck-Report.html");
+146 generateReport("HtmlReport", outputDir + File.separator + "dependency-check-report.html");
147 }
148if (format == Format.VULN || format == Format.ALL) {
-149 generateReport("VulnerabilityReport", outputDir + File.separator + "DependencyCheck-Vulnerability.html");
+149 generateReport("VulnerabilityReport", outputDir + File.separator + "dependency-check-vulnerability.html");
150 }
151 }
152
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-frame.html
index 42df2610d..2f9df700b 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-frame.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-frame.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.reporting
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.reporting
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-summary.html
index aac27c85f..3eda49ead 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-summary.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-summary.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.reporting
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.reporting
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/suppression/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/suppression/package-frame.html
index 3aec21dc5..75c0cc187 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/suppression/package-frame.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/suppression/package-frame.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.suppression
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.suppression
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/suppression/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/suppression/package-summary.html
index 6ca6a12f4..bab3b485d 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/suppression/package-summary.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/suppression/package-summary.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.suppression
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.suppression
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/utils/FileUtils.html b/dependency-check-core/xref/org/owasp/dependencycheck/utils/FileUtils.html
index 296770bbc..ea1cb8813 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/utils/FileUtils.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/utils/FileUtils.html
@@ -49,205 +49,227 @@
41publicfinalclassFileUtils {
4243/**
-44 * The buffer size to use when extracting files from the archive.
+44 * Bit bucket for non-Windows systems45 */
-46privatestaticfinalint BUFFER_SIZE = 4096;
+46privatestaticfinal String BIT_BUCKET_UNIX = "/dev/null";
4748/**
-49 * Private constructor for a utility class.
+49 * Bit bucket for Windows systems (yes, only one 'L')50 */
-51privateFileUtils() {
-52 }
-53
-54/**
-55 * Returns the (lowercase) file extension for a specified file.
-56 *
-57 * @param fileName the file name to retrieve the file extension from.
-58 * @return the file extension.
-59 */
-60publicstatic String getFileExtension(String fileName) {
-61 String ret = null;
-62finalint pos = fileName.lastIndexOf(".");
-63if (pos >= 0) {
-64 ret = fileName.substring(pos + 1, fileName.length()).toLowerCase();
-65 }
-66return ret;
-67 }
-68
-69/**
-70 * Deletes a file. If the File is a directory it will recursively delete the contents.
-71 *
-72 * @param file the File to delete
-73 * @return true if the file was deleted successfully, otherwise false
-74 */
-75publicstaticboolean delete(File file) {
-76boolean success = true;
-77if (file.isDirectory()) { //some of this may duplicative of deleteQuietly....
-78for (File f : file.listFiles()) {
-79 success &= delete(f);
-80 }
-81 }
-82if (!org.apache.commons.io.FileUtils.deleteQuietly(file)) {
-83 success = false;
-84final String msg = String.format("Failed to delete file: %s", file.getPath());
-85 Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, msg);
-86 }
-87return success;
-88 }
-89
-90/**
-91 * Generates a new temporary file name that is guaranteed to be unique.
-92 *
-93 * @param prefix the prefix for the file name to generate
-94 * @param extension the extension of the generated file name
-95 * @return a temporary File
-96 */
-97publicstatic File getTempFile(String prefix, String extension) {
-98final File dir = Settings.getTempDirectory();
-99if (!dir.exists()) {
-100 dir.mkdirs();
-101 }
-102final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension);
-103final File tempFile = new File(dir, tempFileName);
-104if (tempFile.exists()) {
-105return getTempFile(prefix, extension);
-106 }
-107return tempFile;
-108 }
-109
-110/**
-111 * Returns the data directory. If a path was specified in dependencycheck.properties or was specified using the
-112 * Settings object, and the path exists, that path will be returned as a File object. If it does not exist, then a
-113 * File object will be created based on the file location of the JAR containing the specified class.
-114 *
-115 * @param configuredFilePath the configured relative or absolute path
-116 * @param clazz the class to resolve the path
-117 * @return a File object
-118 * @throws IOException is thrown if the path could not be decoded
-119 * @deprecated This method should no longer be used. See the implementation in dependency-check-cli/App.java to see
-120 * how the data directory should be set.
-121 */
-122 @java.lang.Deprecated
-123publicstatic File getDataDirectory(String configuredFilePath, Class clazz) throws IOException {
-124final File file = new File(configuredFilePath);
-125if (file.isDirectory() && file.canWrite()) {
-126returnnew File(file.getCanonicalPath());
-127 } else {
-128final File exePath = getPathToJar(clazz);
-129returnnew File(exePath, configuredFilePath);
-130 }
-131 }
-132
-133/**
-134 * Retrieves the physical path to the parent directory containing the provided class. For example, if a JAR file
-135 * contained a class org.something.clazz this method would return the parent directory of the JAR file.
-136 *
-137 * @param clazz the class to determine the parent directory of
-138 * @return the parent directory of the file containing the specified class.
-139 * @throws UnsupportedEncodingException thrown if UTF-8 is not supported.
-140 * @deprecated this should no longer be used.
-141 */
-142 @java.lang.Deprecated
-143publicstatic File getPathToJar(Class clazz) throws UnsupportedEncodingException {
-144final String filePath = clazz.getProtectionDomain().getCodeSource().getLocation().getPath();
-145final String decodedPath = URLDecoder.decode(filePath, "UTF-8");
-146final File jarPath = new File(decodedPath);
-147return jarPath.getParentFile();
-148 }
-149
-150/**
-151 * Extracts the contents of an archive into the specified directory.
-152 *
-153 * @param archive an archive file such as a WAR or EAR
-154 * @param extractTo a directory to extract the contents to
-155 * @throws ExtractionException thrown if an exception occurs while extracting the files
-156 */
-157publicstaticvoid extractFiles(File archive, File extractTo) throws ExtractionException {
-158 extractFiles(archive, extractTo, null);
-159 }
-160
-161/**
-162 * Extracts the contents of an archive into the specified directory. The files are only extracted if they are
-163 * supported by the analyzers loaded into the specified engine. If the engine is specified as null then all files
-164 * are extracted.
-165 *
-166 * @param archive an archive file such as a WAR or EAR
-167 * @param extractTo a directory to extract the contents to
-168 * @param engine the scanning engine
-169 * @throws ExtractionException thrown if there is an error extracting the files
-170 */
-171publicstaticvoid extractFiles(File archive, File extractTo, Engine engine) throws ExtractionException {
-172if (archive == null || extractTo == null) {
-173return;
-174 }
-175
-176 FileInputStream fis = null;
-177 ZipInputStream zis = null;
-178
-179try {
-180 fis = new FileInputStream(archive);
-181 } catch (FileNotFoundException ex) {
-182 Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, null, ex);
-183thrownewExtractionException("Archive file was not found.", ex);
-184 }
-185 zis = new ZipInputStream(new BufferedInputStream(fis));
-186 ZipEntry entry;
-187try {
-188while ((entry = zis.getNextEntry()) != null) {
-189if (entry.isDirectory()) {
-190final File d = new File(extractTo, entry.getName());
-191if (!d.exists() && !d.mkdirs()) {
-192final String msg = String.format("Unable to create '%s'.", d.getAbsolutePath());
-193thrownewExtractionException(msg);
-194 }
-195 } else {
-196final File file = new File(extractTo, entry.getName());
-197final String ext = getFileExtension(file.getName());
-198if (engine == null || engine.supportsExtension(ext)) {
-199 BufferedOutputStream bos = null;
-200 FileOutputStream fos;
-201try {
-202 fos = new FileOutputStream(file);
-203 bos = new BufferedOutputStream(fos, BUFFER_SIZE);
-204int count;
-205final byte data[] = new byte[BUFFER_SIZE];
-206while ((count = zis.read(data, 0, BUFFER_SIZE)) != -1) {
-207 bos.write(data, 0, count);
-208 }
-209 bos.flush();
-210 } catch (FileNotFoundException ex) {
-211 Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, null, ex);
-212final String msg = String.format("Unable to find file '%s'.", file.getName());
-213thrownewExtractionException(msg, ex);
-214 } catch (IOException ex) {
-215 Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, null, ex);
-216final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
-217thrownewExtractionException(msg, ex);
-218 } finally {
-219if (bos != null) {
-220try {
-221 bos.close();
-222 } catch (IOException ex) {
-223 Logger.getLogger(FileUtils.class.getName()).log(Level.FINEST, null, ex);
-224 }
-225 }
-226 }
-227 }
-228 }
-229 }
-230 } catch (IOException ex) {
-231final String msg = String.format("Exception reading archive '%s'.", archive.getName());
-232 Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, msg, ex);
-233thrownewExtractionException(msg, ex);
-234 } finally {
-235try {
-236 zis.close();
-237 } catch (IOException ex) {
-238 Logger.getLogger(FileUtils.class.getName()).log(Level.FINEST, null, ex);
-239 }
-240 }
-241 }
-242 }
+51privatestaticfinal String BIT_BUCKET_WIN = "NUL";
+52
+53/**
+54 * The buffer size to use when extracting files from the archive.
+55 */
+56privatestaticfinalint BUFFER_SIZE = 4096;
+57
+58/**
+59 * Private constructor for a utility class.
+60 */
+61privateFileUtils() {
+62 }
+63
+64/**
+65 * Returns the (lowercase) file extension for a specified file.
+66 *
+67 * @param fileName the file name to retrieve the file extension from.
+68 * @return the file extension.
+69 */
+70publicstatic String getFileExtension(String fileName) {
+71 String ret = null;
+72finalint pos = fileName.lastIndexOf(".");
+73if (pos >= 0) {
+74 ret = fileName.substring(pos + 1, fileName.length()).toLowerCase();
+75 }
+76return ret;
+77 }
+78
+79/**
+80 * Deletes a file. If the File is a directory it will recursively delete the contents.
+81 *
+82 * @param file the File to delete
+83 * @return true if the file was deleted successfully, otherwise false
+84 */
+85publicstaticboolean delete(File file) {
+86boolean success = true;
+87if (!org.apache.commons.io.FileUtils.deleteQuietly(file)) {
+88 success = false;
+89final String msg = String.format("Failed to delete file: %s; attempting to delete on exit.", file.getPath());
+90 Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, msg);
+91 file.deleteOnExit();
+92 }
+93return success;
+94 }
+95
+96/**
+97 * Generates a new temporary file name that is guaranteed to be unique.
+98 *
+99 * @param prefix the prefix for the file name to generate
+100 * @param extension the extension of the generated file name
+101 * @return a temporary File
+102 * @throws java.io.IOException thrown if the temporary folder could not be created
+103 */
+104publicstatic File getTempFile(String prefix, String extension) throws IOException {
+105final File dir = Settings.getTempDirectory();
+106if (!dir.exists()) {
+107if (!dir.mkdirs()) {
+108thrownew IOException("Unable to create temporary folder");
+109 }
+110 }
+111final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension);
+112final File tempFile = new File(dir, tempFileName);
+113if (tempFile.exists()) {
+114return getTempFile(prefix, extension);
+115 }
+116return tempFile;
+117 }
+118
+119/**
+120 * Returns the data directory. If a path was specified in dependencycheck.properties or was specified using the
+121 * Settings object, and the path exists, that path will be returned as a File object. If it does not exist, then a
+122 * File object will be created based on the file location of the JAR containing the specified class.
+123 *
+124 * @param configuredFilePath the configured relative or absolute path
+125 * @param clazz the class to resolve the path
+126 * @return a File object
+127 * @throws IOException is thrown if the path could not be decoded
+128 * @deprecated This method should no longer be used. See the implementation in dependency-check-cli/App.java to see
+129 * how the data directory should be set.
+130 */
+131 @java.lang.Deprecated
+132publicstatic File getDataDirectory(String configuredFilePath, Class clazz) throws IOException {
+133final File file = new File(configuredFilePath);
+134if (file.isDirectory() && file.canWrite()) {
+135returnnew File(file.getCanonicalPath());
+136 } else {
+137final File exePath = getPathToJar(clazz);
+138returnnew File(exePath, configuredFilePath);
+139 }
+140 }
+141
+142/**
+143 * Retrieves the physical path to the parent directory containing the provided class. For example, if a JAR file
+144 * contained a class org.something.clazz this method would return the parent directory of the JAR file.
+145 *
+146 * @param clazz the class to determine the parent directory of
+147 * @return the parent directory of the file containing the specified class.
+148 * @throws UnsupportedEncodingException thrown if UTF-8 is not supported.
+149 * @deprecated this should no longer be used.
+150 */
+151 @java.lang.Deprecated
+152publicstatic File getPathToJar(Class clazz) throws UnsupportedEncodingException {
+153final String filePath = clazz.getProtectionDomain().getCodeSource().getLocation().getPath();
+154final String decodedPath = URLDecoder.decode(filePath, "UTF-8");
+155final File jarPath = new File(decodedPath);
+156return jarPath.getParentFile();
+157 }
+158
+159/**
+160 * Extracts the contents of an archive into the specified directory.
+161 *
+162 * @param archive an archive file such as a WAR or EAR
+163 * @param extractTo a directory to extract the contents to
+164 * @throws ExtractionException thrown if an exception occurs while extracting the files
+165 */
+166publicstaticvoid extractFiles(File archive, File extractTo) throws ExtractionException {
+167 extractFiles(archive, extractTo, null);
+168 }
+169
+170/**
+171 * Extracts the contents of an archive into the specified directory. The files are only extracted if they are
+172 * supported by the analyzers loaded into the specified engine. If the engine is specified as null then all files
+173 * are extracted.
+174 *
+175 * @param archive an archive file such as a WAR or EAR
+176 * @param extractTo a directory to extract the contents to
+177 * @param engine the scanning engine
+178 * @throws ExtractionException thrown if there is an error extracting the files
+179 */
+180publicstaticvoid extractFiles(File archive, File extractTo, Engine engine) throws ExtractionException {
+181if (archive == null || extractTo == null) {
+182return;
+183 }
+184
+185 FileInputStream fis = null;
+186 ZipInputStream zis = null;
+187
+188try {
+189 fis = new FileInputStream(archive);
+190 } catch (FileNotFoundException ex) {
+191 Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, null, ex);
+192thrownewExtractionException("Archive file was not found.", ex);
+193 }
+194 zis = new ZipInputStream(new BufferedInputStream(fis));
+195 ZipEntry entry;
+196try {
+197while ((entry = zis.getNextEntry()) != null) {
+198if (entry.isDirectory()) {
+199final File d = new File(extractTo, entry.getName());
+200if (!d.exists() && !d.mkdirs()) {
+201final String msg = String.format("Unable to create '%s'.", d.getAbsolutePath());
+202thrownewExtractionException(msg);
+203 }
+204 } else {
+205final File file = new File(extractTo, entry.getName());
+206final String ext = getFileExtension(file.getName());
+207if (engine == null || engine.supportsExtension(ext)) {
+208 BufferedOutputStream bos = null;
+209 FileOutputStream fos;
+210try {
+211 fos = new FileOutputStream(file);
+212 bos = new BufferedOutputStream(fos, BUFFER_SIZE);
+213int count;
+214final byte data[] = new byte[BUFFER_SIZE];
+215while ((count = zis.read(data, 0, BUFFER_SIZE)) != -1) {
+216 bos.write(data, 0, count);
+217 }
+218 bos.flush();
+219 } catch (FileNotFoundException ex) {
+220 Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, null, ex);
+221final String msg = String.format("Unable to find file '%s'.", file.getName());
+222thrownewExtractionException(msg, ex);
+223 } catch (IOException ex) {
+224 Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, null, ex);
+225final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
+226thrownewExtractionException(msg, ex);
+227 } finally {
+228if (bos != null) {
+229try {
+230 bos.close();
+231 } catch (IOException ex) {
+232 Logger.getLogger(FileUtils.class.getName()).log(Level.FINEST, null, ex);
+233 }
+234 }
+235 }
+236 }
+237 }
+238 }
+239 } catch (IOException ex) {
+240final String msg = String.format("Exception reading archive '%s'.", archive.getName());
+241 Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, msg, ex);
+242thrownewExtractionException(msg, ex);
+243 } finally {
+244try {
+245 zis.close();
+246 } catch (IOException ex) {
+247 Logger.getLogger(FileUtils.class.getName()).log(Level.FINEST, null, ex);
+248 }
+249 }
+250 }
+251
+252/**
+253 * Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for Windows
+254 *
+255 * @return a String containing the bit bucket
+256 */
+257publicstatic String getBitBucket() {
+258if (System.getProperty("os.name").startsWith("Windows")) {
+259return BIT_BUCKET_WIN;
+260 } else {
+261return BIT_BUCKET_UNIX;
+262 }
+263 }
+264 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/utils/Settings.html b/dependency-check-core/xref/org/owasp/dependencycheck/utils/Settings.html
index 779b9eac9..7cd51248a 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/utils/Settings.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/utils/Settings.html
@@ -154,372 +154,416 @@
146 */147publicstaticfinal String SUPPRESSION_FILE = "suppression.file";
148/**
-149 * The properties key for whether the Nexus analyzer is enabled.
+149 * The properties key for whether the Jar Analyzer is enabled.150 */
-151publicstaticfinal String ANALYZER_NEXUS_ENABLED = "analyzer.nexus.enabled";
+151publicstaticfinal String ANALYZER_JAR_ENABLED = "analyzer.jar.enabled";
152/**
-153 * The properties key for the Nexus search URL.
+153 * The properties key for whether the Archive analyzer is enabled.154 */
-155publicstaticfinal String ANALYZER_NEXUS_URL = "analyzer.nexus.url";
+155publicstaticfinal String ANALYZER_ARCHIVE_ENABLED = "analyzer.archive.enabled";
156/**
-157 * The properties key for using the proxy to reach Nexus.
+157 * The properties key for whether the .NET Assembly analyzer is enabled.158 */
-159publicstaticfinal String ANALYZER_NEXUS_PROXY = "analyzer.nexus.proxy";
+159publicstaticfinal String ANALYZER_ASSEMBLY_ENABLED = "analyzer.assembly.enabled";
160/**
-161 * The path to mono, if available.
+161 * The properties key for whether the .NET Nuspec analyzer is enabled.162 */
-163publicstaticfinal String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path";
+163publicstaticfinal String ANALYZER_NUSPEC_ENABLED = "analyzer.nuspec.enabled";
164/**
-165 * The additional configured zip file extensions, if available.
+165 * The properties key for whether the JavaScript analyzer is enabled.166 */
-167publicstaticfinal String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip";
+167publicstaticfinal String ANALYZER_JAVASCRIPT_ENABLED = "analyzer.javascript.enabled";
168/**
-169 * The properties key for whether Test Scope dependencies should be skipped.
+169 * The properties key for whether the Nexus analyzer is enabled.170 */
-171publicstaticfinal String SKIP_TEST_SCOPE = "skip.test.scope";
+171publicstaticfinal String ANALYZER_NEXUS_ENABLED = "analyzer.nexus.enabled";
172/**
-173 * The properties key for whether Runtime Scope dependencies should be skipped.
+173 * The properties key for the Nexus search URL.174 */
-175publicstaticfinal String SKIP_RUNTIME_SCOPE = "skip.runtime.scope";
+175publicstaticfinal String ANALYZER_NEXUS_URL = "analyzer.nexus.url";
176/**
-177 * The properties key for whether Provided Scope dependencies should be skipped.
+177 * The properties key for using the proxy to reach Nexus.178 */
-179publicstaticfinal String SKIP_PROVIDED_SCOPE = "skip.provided.scope";
-180 }
-181/**
-182 * The properties file location.
-183 */
-184privatestaticfinal String PROPERTIES_FILE = "dependencycheck.properties";
-185/**
-186 * The singleton instance variable.
-187 */
-188privatestaticfinalSettings INSTANCE = newSettings();
-189/**
-190 * The properties.
-191 */
-192private Properties props = null;
-193
-194/**
-195 * Private constructor for the Settings class. This class loads the properties files.
-196 */
-197privateSettings() {
-198 InputStream in = null;
-199 props = new Properties();
-200try {
-201 in = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
-202 props.load(in);
-203 } catch (IOException ex) {
-204 Logger.getLogger(Settings.class.getName()).log(Level.SEVERE, "Unable to load default settings.");
-205 Logger.getLogger(Settings.class.getName()).log(Level.FINE, null, ex);
-206 } finally {
-207if (in != null) {
-208try {
-209 in.close();
-210 } catch (IOException ex) {
-211 Logger.getLogger(Settings.class.getName()).log(Level.FINEST, null, ex);
-212 }
-213 }
-214 }
-215 logProperties("Properties loaded", props);
-216 }
-217
-218/**
-219 * Logs the properties. This will not log any properties that contain 'password' in the key.
-220 *
-221 * @param header the header to print with the log message
-222 * @param properties the properties to log
-223 */
-224privatestaticvoid logProperties(String header, Properties properties) {
-225if (LOGGER.isLoggable(Level.FINE)) {
-226final StringWriter sw = new StringWriter();
-227 PrintWriter pw = null;
-228try {
-229 pw = new PrintWriter(sw);
-230 pw.format("%s:%n%n", header);
-231final Enumeration e = properties.propertyNames();
-232while (e.hasMoreElements()) {
-233final String key = (String) e.nextElement();
-234if (key.contains("password")) {
-235 pw.format("%s='*****'%n", key);
-236 } else {
-237final String value = properties.getProperty(key);
-238if (value != null) {
-239 pw.format("%s='%s'%n", key, value);
-240 }
-241 }
-242 }
-243 pw.flush();
-244 LOGGER.fine(sw.toString());
-245 } finally {
-246if (pw != null) {
-247 pw.close();
-248 }
-249 }
-250
-251 }
-252 }
-253
-254/**
-255 * Sets a property value.
-256 *
-257 * @param key the key for the property
-258 * @param value the value for the property
-259 */
-260publicstaticvoid setString(String key, String value) {
-261 INSTANCE.props.setProperty(key, value);
-262if (LOGGER.isLoggable(Level.FINE)) {
-263 LOGGER.fine(String.format("Setting: %s='%s'", key, value));
-264 }
-265 }
-266
-267/**
-268 * Sets a property value.
-269 *
-270 * @param key the key for the property
-271 * @param value the value for the property
-272 */
-273publicstaticvoid setBoolean(String key, boolean value) {
-274if (value) {
-275 INSTANCE.props.setProperty(key, Boolean.TRUE.toString());
-276 } else {
-277 INSTANCE.props.setProperty(key, Boolean.FALSE.toString());
-278 }
-279if (LOGGER.isLoggable(Level.FINE)) {
-280 LOGGER.fine(String.format("Setting: %s='%b'", key, value));
-281 }
-282 }
-283
-284/**
-285 * Merges a new properties file into the current properties. This method allows for the loading of a user provided
-286 * properties file.<br/><br/>
-287 * Note: even if using this method - system properties will be loaded before properties loaded from files.
-288 *
-289 * @param filePath the path to the properties file to merge.
-290 * @throws FileNotFoundException is thrown when the filePath points to a non-existent file
-291 * @throws IOException is thrown when there is an exception loading/merging the properties
+179publicstaticfinal String ANALYZER_NEXUS_PROXY = "analyzer.nexus.proxy";
+180/**
+181 * The path to mono, if available.
+182 */
+183publicstaticfinal String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path";
+184/**
+185 * The additional configured zip file extensions, if available.
+186 */
+187publicstaticfinal String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip";
+188/**
+189 * The properties key for whether Test Scope dependencies should be skipped.
+190 */
+191publicstaticfinal String SKIP_TEST_SCOPE = "skip.test.scope";
+192/**
+193 * The properties key for whether Runtime Scope dependencies should be skipped.
+194 */
+195publicstaticfinal String SKIP_RUNTIME_SCOPE = "skip.runtime.scope";
+196/**
+197 * The properties key for whether Provided Scope dependencies should be skipped.
+198 */
+199publicstaticfinal String SKIP_PROVIDED_SCOPE = "skip.provided.scope";
+200 }
+201/**
+202 * The properties file location.
+203 */
+204privatestaticfinal String PROPERTIES_FILE = "dependencycheck.properties";
+205/**
+206 * The singleton instance variable.
+207 */
+208privatestaticfinalSettings INSTANCE = newSettings();
+209/**
+210 * The properties.
+211 */
+212private Properties props = null;
+213
+214/**
+215 * Private constructor for the Settings class. This class loads the properties files.
+216 */
+217privateSettings() {
+218 InputStream in = null;
+219 props = new Properties();
+220try {
+221 in = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
+222 props.load(in);
+223 } catch (IOException ex) {
+224 Logger.getLogger(Settings.class.getName()).log(Level.SEVERE, "Unable to load default settings.");
+225 Logger.getLogger(Settings.class.getName()).log(Level.FINE, null, ex);
+226 } finally {
+227if (in != null) {
+228try {
+229 in.close();
+230 } catch (IOException ex) {
+231 Logger.getLogger(Settings.class.getName()).log(Level.FINEST, null, ex);
+232 }
+233 }
+234 }
+235 logProperties("Properties loaded", props);
+236 }
+237
+238/**
+239 * Logs the properties. This will not log any properties that contain 'password' in the key.
+240 *
+241 * @param header the header to print with the log message
+242 * @param properties the properties to log
+243 */
+244privatestaticvoid logProperties(String header, Properties properties) {
+245if (LOGGER.isLoggable(Level.FINE)) {
+246final StringWriter sw = new StringWriter();
+247 PrintWriter pw = null;
+248try {
+249 pw = new PrintWriter(sw);
+250 pw.format("%s:%n%n", header);
+251final Enumeration e = properties.propertyNames();
+252while (e.hasMoreElements()) {
+253final String key = (String) e.nextElement();
+254if (key.contains("password")) {
+255 pw.format("%s='*****'%n", key);
+256 } else {
+257final String value = properties.getProperty(key);
+258if (value != null) {
+259 pw.format("%s='%s'%n", key, value);
+260 }
+261 }
+262 }
+263 pw.flush();
+264 LOGGER.fine(sw.toString());
+265 } finally {
+266if (pw != null) {
+267 pw.close();
+268 }
+269 }
+270
+271 }
+272 }
+273
+274/**
+275 * Sets a property value.
+276 *
+277 * @param key the key for the property
+278 * @param value the value for the property
+279 */
+280publicstaticvoid setString(String key, String value) {
+281 INSTANCE.props.setProperty(key, value);
+282if (LOGGER.isLoggable(Level.FINE)) {
+283 LOGGER.fine(String.format("Setting: %s='%s'", key, value));
+284 }
+285 }
+286
+287/**
+288 * Sets a property value.
+289 *
+290 * @param key the key for the property
+291 * @param value the value for the property292 */
-293publicstaticvoid mergeProperties(File filePath) throws FileNotFoundException, IOException {
-294final FileInputStream fis = new FileInputStream(filePath);
-295 mergeProperties(fis);
-296 }
-297
-298/**
-299 * Merges a new properties file into the current properties. This method allows for the loading of a user provided
-300 * properties file.<br/><br/>
-301 * Note: even if using this method - system properties will be loaded before properties loaded from files.
-302 *
-303 * @param filePath the path to the properties file to merge.
-304 * @throws FileNotFoundException is thrown when the filePath points to a non-existent file
-305 * @throws IOException is thrown when there is an exception loading/merging the properties
-306 */
-307publicstaticvoid mergeProperties(String filePath) throws FileNotFoundException, IOException {
-308final FileInputStream fis = new FileInputStream(filePath);
-309 mergeProperties(fis);
-310 }
-311
-312/**
-313 * Merges a new properties file into the current properties. This method allows for the loading of a user provided
-314 * properties file.<br/><br/>
-315 * Note: even if using this method - system properties will be loaded before properties loaded from files.
-316 *
-317 * @param stream an Input Stream pointing at a properties file to merge
-318 * @throws IOException is thrown when there is an exception loading/merging the properties
-319 */
-320publicstaticvoid mergeProperties(InputStream stream) throws IOException {
-321 INSTANCE.props.load(stream);
-322 logProperties("Properties updated via merge", INSTANCE.props);
-323 }
-324
-325/**
-326 * Returns a value from the properties file as a File object. If the value was specified as a system property or
-327 * passed in via the -Dprop=value argument - this method will return the value from the system properties before the
-328 * values in the contained configuration file.
-329 *
-330 * @param key the key to lookup within the properties file
-331 * @return the property from the properties file converted to a File object
-332 */
-333publicstatic File getFile(String key) {
-334final String file = getString(key);
-335if (file == null) {
-336returnnull;
-337 }
-338returnnew File(file);
-339 }
-340
-341/**
-342 * Returns a value from the properties file as a File object. If the value was specified as a system property or
-343 * passed in via the -Dprop=value argument - this method will return the value from the system properties before the
-344 * values in the contained configuration file.
-345 *
-346 * This method will check the configured base directory and will use this as the base of the file path.
-347 * Additionally, if the base directory begins with a leading "[JAR]\" sequence with the path to the folder
-348 * containing the JAR file containing this class.
+293publicstaticvoid setBoolean(String key, boolean value) {
+294if (value) {
+295 INSTANCE.props.setProperty(key, Boolean.TRUE.toString());
+296 } else {
+297 INSTANCE.props.setProperty(key, Boolean.FALSE.toString());
+298 }
+299if (LOGGER.isLoggable(Level.FINE)) {
+300 LOGGER.fine(String.format("Setting: %s='%b'", key, value));
+301 }
+302 }
+303
+304/**
+305 * Merges a new properties file into the current properties. This method allows for the loading of a user provided
+306 * properties file.<br/><br/>
+307 * Note: even if using this method - system properties will be loaded before properties loaded from files.
+308 *
+309 * @param filePath the path to the properties file to merge.
+310 * @throws FileNotFoundException is thrown when the filePath points to a non-existent file
+311 * @throws IOException is thrown when there is an exception loading/merging the properties
+312 */
+313publicstaticvoid mergeProperties(File filePath) throws FileNotFoundException, IOException {
+314final FileInputStream fis = new FileInputStream(filePath);
+315 mergeProperties(fis);
+316 }
+317
+318/**
+319 * Merges a new properties file into the current properties. This method allows for the loading of a user provided
+320 * properties file.<br/><br/>
+321 * Note: even if using this method - system properties will be loaded before properties loaded from files.
+322 *
+323 * @param filePath the path to the properties file to merge.
+324 * @throws FileNotFoundException is thrown when the filePath points to a non-existent file
+325 * @throws IOException is thrown when there is an exception loading/merging the properties
+326 */
+327publicstaticvoid mergeProperties(String filePath) throws FileNotFoundException, IOException {
+328final FileInputStream fis = new FileInputStream(filePath);
+329 mergeProperties(fis);
+330 }
+331
+332/**
+333 * Merges a new properties file into the current properties. This method allows for the loading of a user provided
+334 * properties file.<br/><br/>
+335 * Note: even if using this method - system properties will be loaded before properties loaded from files.
+336 *
+337 * @param stream an Input Stream pointing at a properties file to merge
+338 * @throws IOException is thrown when there is an exception loading/merging the properties
+339 */
+340publicstaticvoid mergeProperties(InputStream stream) throws IOException {
+341 INSTANCE.props.load(stream);
+342 logProperties("Properties updated via merge", INSTANCE.props);
+343 }
+344
+345/**
+346 * Returns a value from the properties file as a File object. If the value was specified as a system property or
+347 * passed in via the -Dprop=value argument - this method will return the value from the system properties before the
+348 * values in the contained configuration file.349 *350 * @param key the key to lookup within the properties file351 * @return the property from the properties file converted to a File object352 */
-353publicstatic File getDataFile(String key) {
+353publicstatic File getFile(String key) {
354final String file = getString(key);
-355 Logger.getLogger(Settings.class.getName()).log(Level.FINE, String.format("Settings.getDataFile() - file: '%s'", file));
-356if (file == null) {
-357returnnull;
-358 }
-359if (file.startsWith("[JAR]")) {
-360 Logger.getLogger(Settings.class.getName()).log(Level.FINE, "Settings.getDataFile() - transforming filename");
-361final File jarPath = getJarPath();
-362 Logger.getLogger(Settings.class.getName()).log(Level.FINE, String.format("Settings.getDataFile() - jar file: '%s'", jarPath.toString()));
-363final File retVal = new File(jarPath, file.substring(6));
-364 Logger.getLogger(Settings.class.getName()).log(Level.FINE, String.format("Settings.getDataFile() - returning: '%s'", retVal.toString()));
-365return retVal;
-366 }
-367returnnew File(file);
-368 }
-369
-370/**
-371 * Attempts to retrieve the folder containing the Jar file containing the Settings class.
-372 *
-373 * @return a File object
-374 */
-375privatestatic File getJarPath() {
-376final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath();
-377 String decodedPath = ".";
-378try {
-379 decodedPath = URLDecoder.decode(jarPath, "UTF-8");
-380 } catch (UnsupportedEncodingException ex) {
-381 Logger.getLogger(Settings.class.getName()).log(Level.FINEST, null, ex);
-382 }
-383
-384final File path = new File(decodedPath);
-385if (path.getName().toLowerCase().endsWith(".jar")) {
-386return path.getParentFile();
-387 } else {
-388returnnew File(".");
-389 }
-390 }
-391
-392/**
-393 * Returns a value from the properties file. If the value was specified as a system property or passed in via the
-394 * -Dprop=value argument - this method will return the value from the system properties before the values in the
-395 * contained configuration file.
-396 *
-397 * @param key the key to lookup within the properties file
-398 * @param defaultValue the default value for the requested property
-399 * @return the property from the properties file
-400 */
-401publicstatic String getString(String key, String defaultValue) {
-402final String str = System.getProperty(key, INSTANCE.props.getProperty(key, defaultValue));
-403return str;
-404 }
-405
-406/**
-407 * Returns the temporary directory.
-408 *
-409 * @return the temporary directory
-410 */
-411publicstatic File getTempDirectory() {
-412returnnew File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")));
-413 }
-414
-415/**
-416 * Returns a value from the properties file. If the value was specified as a system property or passed in via the
-417 * -Dprop=value argument - this method will return the value from the system properties before the values in the
-418 * contained configuration file.
-419 *
-420 * @param key the key to lookup within the properties file
-421 * @return the property from the properties file
-422 */
-423publicstatic String getString(String key) {
-424return System.getProperty(key, INSTANCE.props.getProperty(key));
-425 }
-426
-427/**
-428 * Removes a property from the local properties collection. This is mainly used in test cases.
-429 *
-430 * @param key the property key to remove
-431 */
-432publicstaticvoid removeProperty(String key) {
-433 INSTANCE.props.remove(key);
-434 }
-435
-436/**
-437 * Returns an int value from the properties file. If the value was specified as a system property or passed in via
-438 * the -Dprop=value argument - this method will return the value from the system properties before the values in the
-439 * contained configuration file.
-440 *
-441 * @param key the key to lookup within the properties file
-442 * @return the property from the properties file
-443 * @throws InvalidSettingException is thrown if there is an error retrieving the setting
-444 */
-445publicstaticint getInt(String key) throws InvalidSettingException {
-446int value;
-447try {
-448 value = Integer.parseInt(Settings.getString(key));
-449 } catch (NumberFormatException ex) {
-450thrownewInvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
-451 }
-452return value;
-453 }
-454
-455/**
-456 * Returns an int value from the properties file. If the value was specified as a system property or passed in via
-457 * the -Dprop=value argument - this method will return the value from the system properties before the values in the
-458 * contained configuration file.
-459 *
-460 * @param key the key to lookup within the properties file
-461 * @param defaultValue the default value to return
-462 * @return the property from the properties file or the defaultValue if the property does not exist or cannot be
-463 * converted to an integer
+355if (file == null) {
+356returnnull;
+357 }
+358returnnew File(file);
+359 }
+360
+361/**
+362 * Returns a value from the properties file as a File object. If the value was specified as a system property or
+363 * passed in via the -Dprop=value argument - this method will return the value from the system properties before the
+364 * values in the contained configuration file.
+365 *
+366 * This method will check the configured base directory and will use this as the base of the file path.
+367 * Additionally, if the base directory begins with a leading "[JAR]\" sequence with the path to the folder
+368 * containing the JAR file containing this class.
+369 *
+370 * @param key the key to lookup within the properties file
+371 * @return the property from the properties file converted to a File object
+372 */
+373publicstatic File getDataFile(String key) {
+374final String file = getString(key);
+375 Logger.getLogger(Settings.class.getName()).log(Level.FINE, String.format("Settings.getDataFile() - file: '%s'", file));
+376if (file == null) {
+377returnnull;
+378 }
+379if (file.startsWith("[JAR]")) {
+380 Logger.getLogger(Settings.class.getName()).log(Level.FINE, "Settings.getDataFile() - transforming filename");
+381final File jarPath = getJarPath();
+382 Logger.getLogger(Settings.class.getName()).log(Level.FINE, String.format("Settings.getDataFile() - jar file: '%s'", jarPath.toString()));
+383final File retVal = new File(jarPath, file.substring(6));
+384 Logger.getLogger(Settings.class.getName()).log(Level.FINE, String.format("Settings.getDataFile() - returning: '%s'", retVal.toString()));
+385return retVal;
+386 }
+387returnnew File(file);
+388 }
+389
+390/**
+391 * Attempts to retrieve the folder containing the Jar file containing the Settings class.
+392 *
+393 * @return a File object
+394 */
+395privatestatic File getJarPath() {
+396final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath();
+397 String decodedPath = ".";
+398try {
+399 decodedPath = URLDecoder.decode(jarPath, "UTF-8");
+400 } catch (UnsupportedEncodingException ex) {
+401 Logger.getLogger(Settings.class.getName()).log(Level.FINEST, null, ex);
+402 }
+403
+404final File path = new File(decodedPath);
+405if (path.getName().toLowerCase().endsWith(".jar")) {
+406return path.getParentFile();
+407 } else {
+408returnnew File(".");
+409 }
+410 }
+411
+412/**
+413 * Returns a value from the properties file. If the value was specified as a system property or passed in via the
+414 * -Dprop=value argument - this method will return the value from the system properties before the values in the
+415 * contained configuration file.
+416 *
+417 * @param key the key to lookup within the properties file
+418 * @param defaultValue the default value for the requested property
+419 * @return the property from the properties file
+420 */
+421publicstatic String getString(String key, String defaultValue) {
+422final String str = System.getProperty(key, INSTANCE.props.getProperty(key, defaultValue));
+423return str;
+424 }
+425
+426/**
+427 * Returns the temporary directory.
+428 *
+429 * @return the temporary directory
+430 */
+431publicstatic File getTempDirectory() {
+432returnnew File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")));
+433 }
+434
+435/**
+436 * Returns a value from the properties file. If the value was specified as a system property or passed in via the
+437 * -Dprop=value argument - this method will return the value from the system properties before the values in the
+438 * contained configuration file.
+439 *
+440 * @param key the key to lookup within the properties file
+441 * @return the property from the properties file
+442 */
+443publicstatic String getString(String key) {
+444return System.getProperty(key, INSTANCE.props.getProperty(key));
+445 }
+446
+447/**
+448 * Removes a property from the local properties collection. This is mainly used in test cases.
+449 *
+450 * @param key the property key to remove
+451 */
+452publicstaticvoid removeProperty(String key) {
+453 INSTANCE.props.remove(key);
+454 }
+455
+456/**
+457 * Returns an int value from the properties file. If the value was specified as a system property or passed in via
+458 * the -Dprop=value argument - this method will return the value from the system properties before the values in the
+459 * contained configuration file.
+460 *
+461 * @param key the key to lookup within the properties file
+462 * @return the property from the properties file
+463 * @throws InvalidSettingException is thrown if there is an error retrieving the setting464 */
-465publicstaticint getInt(String key, int defaultValue) {
+465publicstaticint getInt(String key) throws InvalidSettingException {
466int value;
467try {
468 value = Integer.parseInt(Settings.getString(key));
469 } catch (NumberFormatException ex) {
-470final String msg = String.format("Could not convert property '%s' to an int.", key);
-471 Logger.getLogger(Settings.class.getName()).log(Level.FINEST, msg, ex);
-472 value = defaultValue;
-473 }
-474return value;
-475 }
-476
-477/**
-478 * Returns a long value from the properties file. If the value was specified as a system property or passed in via
-479 * the -Dprop=value argument - this method will return the value from the system properties before the values in the
-480 * contained configuration file.
-481 *
-482 * @param key the key to lookup within the properties file
-483 * @return the property from the properties file
-484 * @throws InvalidSettingException is thrown if there is an error retrieving the setting
-485 */
-486publicstaticlong getLong(String key) throws InvalidSettingException {
-487long value;
-488try {
-489 value = Long.parseLong(Settings.getString(key));
-490 } catch (NumberFormatException ex) {
-491thrownewInvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
-492 }
-493return value;
-494 }
-495
-496/**
-497 * Returns a boolean value from the properties file. If the value was specified as a system property or passed in
-498 * via the <code>-Dprop=value</code> argument this method will return the value from the system properties before
-499 * the values in the contained configuration file.
-500 *
-501 * @param key the key to lookup within the properties file
-502 * @return the property from the properties file
-503 * @throws InvalidSettingException is thrown if there is an error retrieving the setting
-504 */
-505publicstaticboolean getBoolean(String key) throws InvalidSettingException {
-506boolean value;
-507try {
-508 value = Boolean.parseBoolean(Settings.getString(key));
-509 } catch (NumberFormatException ex) {
-510thrownewInvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
-511 }
-512return value;
-513 }
-514 }
+470thrownewInvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
+471 }
+472return value;
+473 }
+474
+475/**
+476 * Returns an int value from the properties file. If the value was specified as a system property or passed in via
+477 * the -Dprop=value argument - this method will return the value from the system properties before the values in the
+478 * contained configuration file.
+479 *
+480 * @param key the key to lookup within the properties file
+481 * @param defaultValue the default value to return
+482 * @return the property from the properties file or the defaultValue if the property does not exist or cannot be
+483 * converted to an integer
+484 */
+485publicstaticint getInt(String key, int defaultValue) {
+486int value;
+487try {
+488 value = Integer.parseInt(Settings.getString(key));
+489 } catch (NumberFormatException ex) {
+490final String msg = String.format("Could not convert property '%s' to an int.", key);
+491 Logger.getLogger(Settings.class.getName()).log(Level.FINEST, msg, ex);
+492 value = defaultValue;
+493 }
+494return value;
+495 }
+496
+497/**
+498 * Returns a long value from the properties file. If the value was specified as a system property or passed in via
+499 * the -Dprop=value argument - this method will return the value from the system properties before the values in the
+500 * contained configuration file.
+501 *
+502 * @param key the key to lookup within the properties file
+503 * @return the property from the properties file
+504 * @throws InvalidSettingException is thrown if there is an error retrieving the setting
+505 */
+506publicstaticlong getLong(String key) throws InvalidSettingException {
+507long value;
+508try {
+509 value = Long.parseLong(Settings.getString(key));
+510 } catch (NumberFormatException ex) {
+511thrownewInvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
+512 }
+513return value;
+514 }
+515
+516/**
+517 * Returns a boolean value from the properties file. If the value was specified as a system property or passed in
+518 * via the <code>-Dprop=value</code> argument this method will return the value from the system properties before
+519 * the values in the contained configuration file.
+520 *
+521 * @param key the key to lookup within the properties file
+522 * @return the property from the properties file
+523 * @throws InvalidSettingException is thrown if there is an error retrieving the setting
+524 */
+525publicstaticboolean getBoolean(String key) throws InvalidSettingException {
+526boolean value;
+527try {
+528 value = Boolean.parseBoolean(Settings.getString(key));
+529 } catch (NumberFormatException ex) {
+530thrownewInvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
+531 }
+532return value;
+533 }
+534
+535/**
+536 * Returns a boolean value from the properties file. If the value was specified as a system property or passed in
+537 * via the <code>-Dprop=value</code> argument this method will return the value from the system properties before
+538 * the values in the contained configuration file.
+539 *
+540 * @param key the key to lookup within the properties file
+541 * @param defaultValue the default value to return if the setting does not exist
+542 * @return the property from the properties file
+543 * @throws InvalidSettingException is thrown if there is an error retrieving the setting
+544 */
+545publicstaticboolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException {
+546boolean value;
+547try {
+548final String strValue = Settings.getString(key);
+549if (strValue == null) {
+550return defaultValue;
+551 }
+552 value = Boolean.parseBoolean(strValue);
+553 } catch (NumberFormatException ex) {
+554thrownewInvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
+555 }
+556return value;
+557 }
+558 }
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-frame.html
index 2b3f9e9c4..4e4ecc8e6 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-frame.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-frame.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.utils
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.utils
diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-summary.html
index dd074b443..f34bafb51 100644
--- a/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-summary.html
+++ b/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-summary.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference Package org.owasp.dependencycheck.utils
+ Dependency-Check Core 1.1.4 Reference Package org.owasp.dependencycheck.utils
diff --git a/dependency-check-core/xref/overview-frame.html b/dependency-check-core/xref/overview-frame.html
index c8506168e..9c80cfa15 100644
--- a/dependency-check-core/xref/overview-frame.html
+++ b/dependency-check-core/xref/overview-frame.html
@@ -3,7 +3,7 @@
- Dependency-Check Core 1.1.3 Reference
+ Dependency-Check Core 1.1.4 Reference
@@ -17,6 +17,9 @@
@@ -260,7 +260,7 @@ plugin unless the externalReport is set to true. Default is HTML. Defaul
-
-
The output directory. Default value is: ${project.build.directory}.
+
The output directory. This generally maps to "target". Default value is: ${project.build.directory}.
@@ -272,7 +272,7 @@ plugin unless the externalReport is set to true. Default is HTML. Defaul
-
Specifies the destination directory for the generated
-Dependency-Check report. Default value is: ${project.reporting.outputDirectory}. User property is: reportOutputDirectory.
+Dependency-Check report. This generally maps to "target/site". Default value is: ${project.reporting.outputDirectory}. User property is: reportOutputDirectory.
@@ -295,6 +295,28 @@ Dependency-Check report. Default value is: ${project.reporting.o
@@ -449,7 +504,7 @@ the Maven Generated Reports page. Default value is: A report pro
Reports page. Default value is: Dependency-Check. User property is: name.
Sets whether auto-updating of the NVD CVE/CPE data is enabled. It
@@ -828,6 +911,20 @@ plugin unless the externalReport is set to true. Default is HTML.
The location to write the report(s). Note, this is not used if generating the report as part of a mvn site build
+
+
‘target’
+
+
+
+
failBuildOnCVSS
Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail.
@@ -196,7 +205,7 @@
11
-
+
format
@@ -205,7 +214,7 @@
HTML
-
+
logFile
@@ -214,7 +223,7 @@
-
+
suppressionFile
@@ -223,49 +232,76 @@
+
+
+
skipTestScope
+
+
Should be skip analysis for artifacts with Test Scope
+
+
true
+
+
-
connectionTimeout
+
skipProvidedScope
-
The Connection Timeout.
+
Should be skip analysis for artifacts with Provided Scope
-
+
false
-
proxyUrl
+
skipRuntimeScope
-
The Proxy URL.
+
Should be skip analysis for artifacts with Runtime Scope
-
+
false
+
+
+
Analyzer Configuration
+
The following properties are used to configure the various file type analyzers. These properties can be used to turn off specific analyzers if it is not needed. Note, that specific analyzers will automatically disable themselves if no file types that they support are detected - so specifically disabling them may not be needed.
+
+
+
+
+
+
+
Property
+
+
Description
+
+
Default Value
+
+
+
-
proxyPort
+
archiveAnalyzerEnabled
-
The Proxy Port.
+
Sets whether the Archive Analyzer will be used.
-
+
true
-
proxyUsername
+
zipExtensions
-
Defines the proxy user name.
+
A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed.
Sets whether or not the .NET Nuget Nuspec Analyzer will be used.
+
+
true
+
+
+
+
+
assemblyAnalyzerEnabled
+
+
Sets whether or not the .NET Assembly Analyzer should be used.
+
+
true
+
+
+
+
+
pathToMono
+
+
The path to Mono for .NET assembly analysis on non-windows systems
+
+
+
+
+
+
Advanced Configuration
+
The following properties can be configured in the plugin. However, they are less frequently changed. One exception may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment.
Data directory to hold SQL CVEs contents. This should generally not be changed.
+
+
+
+
+
+
databaseDriverName
The name of the database driver. Example: org.h2.Driver.
@@ -339,93 +474,57 @@
+
+
+
Deprecated Configuration
+
The following properties have been deprecated. These can stell be set in the dependency-check-maven plugin’s configuration. However, future versions will remove these properties. Instead using these properties you should use Maven’s settings to configure a proxy.
+
+
+
-
zipExtensions
+
Property
-
A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed.
+
Description
+
+
Default Value
+
+
+
+
+
+
+
proxyUrl
+
+
The Proxy URL.
+
+
+
+
+
+
+
proxyPort
+
+
The Proxy Port.
-
skipTestScope
+
proxyUsername
-
Should be skip analysis for artifacts with Test Scope
-
-
true
-
-
-
-
-
skipProvidedScope
-
-
Should be skip analysis for artifacts with Provided Scope
-
-
false
-
-
-
-
-
skipRuntimeScope
-
-
Should be skip analysis for artifacts with Runtime Scope
-
-
false
-
-
-
-
-
dataDirectory
-
-
Data directory to hold SQL CVEs contents. This should generally not be changed.
It is important to understand that the first time this task is executed it may take 20 minutes or more as it downloads and processes the data from the National Vulnerability Database (NVD) hosted by NIST: https://nvd.nist.gov
After the first batch download, as long as the plugin is executed at least once every seven days the update will only take a few seconds.
-
Example 1:
+
+
Example 1:
Create the DependencyCheck-report.html in the target directory