diff --git a/.travis.yml b/.travis.yml
index 75e4c7e78..ed2f38e1a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,11 +3,22 @@ jdk: oraclejdk7
script: mvn install -DreleaseTesting
env:
global:
- secure: ZUzhWfpXJw/oAeDlUkDFkEJMT0T7kCN3d7ah8urkL2B0KFfKOqQagkbXkgvDa1SYud8VdcnoGa69LfkEr5IrdqW7R4bEYZAiN5swm4Z0iO8t53szVspm2f+O9jQ44O/sfOfpfLxWUUuhdc7Vbrszp+tSszxdPmssWL+f5a/mfWs=
-
+ - secure: ZUzhWfpXJw/oAeDlUkDFkEJMT0T7kCN3d7ah8urkL2B0KFfKOqQagkbXkgvDa1SYud8VdcnoGa69LfkEr5IrdqW7R4bEYZAiN5swm4Z0iO8t53szVspm2f+O9jQ44O/sfOfpfLxWUUuhdc7Vbrszp+tSszxdPmssWL+f5a/mfWs=
+ - secure: pmFymoI7qH0Kna3NkcHrqLiTVWKmrhwqA4Z9U6XLhWDQxcs5g94wCCKpGB6Lkz9mkvRxBRFpZZelnXJa9W9mnuVOMIa5tQfS5gBuaNXOe7AXXdc+Y2975OR9sSfvf16FxLFvNJILmZq+bpMLs+EXaQvjYQHW2O6OWZdLhAPVG6A=
before_install:
- - sudo apt-get install jq
- - wget -O ~/codacy-coverage-reporter-assembly-latest.jar $(curl https://api.github.com/repos/codacy/codacy-coverage-reporter/releases/latest | jq -r .assets[0].browser_download_url)
-
+- wget -O ~/codacy-coverage-reporter-assembly.jar https://oss.sonatype.org/service/local/repositories/releases/content/com/codacy/codacy-coverage-reporter/1.0.13/codacy-coverage-reporter-1.0.13-assembly.jar
after_success:
- - java -cp ~/codacy-coverage-reporter-assembly-latest.jar com.codacy.CodacyCoverageReporter -l Java -r build-reporting/target/site/jacoco-aggregate/jacoco.xml
+- java -cp ~/codacy-coverage-reporter-assembly.jar com.codacy.CodacyCoverageReporter
+ -l Java -r build-reporting/target/coverage-reports/jacoco.xml
+matrix:
+ include:
+ - env: CRON_ONLY=1
+ addons:
+ coverity_scan:
+ project:
+ name: OWASP dependency-check
+ version: 1.0
+ description: A software composition analsis tools that detects publicly
+ disclosed vulnerabilities in application dependencies.
+ build_command: mvn -DskipTests=true package
+ branch_pattern: master
diff --git a/README.md b/README.md
index f14f03c16..eca8c088d 100644
--- a/README.md
+++ b/README.md
@@ -29,8 +29,8 @@ $ ./bin/dependency-check.sh --project Testing --out . --scan [path to jar files
```
On Windows
```
-> bin/dependency-check.bat -h
-> bin/dependency-check.bat --project Testing --out . --scan [path to jar files to be scanned]
+> .\bin\dependency-check.bat -h
+> .\bin\dependency-check.bat --project Testing --out . --scan [path to jar files to be scanned]
```
On Mac with [Homebrew](http://brew.sh)
```
diff --git a/build-reporting/pom.xml b/build-reporting/pom.xml
index d77663e2d..011fbb12a 100644
--- a/build-reporting/pom.xml
+++ b/build-reporting/pom.xml
@@ -20,10 +20,11 @@ Copyright (c) 2017 - Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 1.4.6-SNAPSHOT
+ 2.0.0-SNAPSHOT
-
+ Dependency-Check Build-Reportingbuild-reporting
+ pom
@@ -62,6 +63,13 @@ Copyright (c) 2017 - Jeremy Long. All Rights Reserved.
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+ org.jacocojacoco-maven-plugin
@@ -72,6 +80,13 @@ Copyright (c) 2017 - Jeremy Long. All Rights Reserved.
report-aggregate
+
+ target/coverage-reports/
+
+ target/coverage-reports/jacoco-ut.exec
+ target/coverage-reports/jacoco-it.exec
+
+
diff --git a/dependency-check-ant/pom.xml b/dependency-check-ant/pom.xml
index 9c7962954..6cb92aaf7 100644
--- a/dependency-check-ant/pom.xml
+++ b/dependency-check-ant/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 1.4.6-SNAPSHOT
+ 2.0.0-SNAPSHOTdependency-check-ant
diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
index d69b3ecbe..05bab0aae 100644
--- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
+++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
@@ -940,16 +940,7 @@ public class Check extends Update {
throw new BuildException(ex);
}
}
- DatabaseProperties prop = null;
- try (CveDB cve = CveDB.getInstance()) {
- prop = cve.getDatabaseProperties();
- } catch (DatabaseException ex) {
- //TODO shouldn't this be a fatal exception
- log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG);
- }
-
- final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop);
- reporter.generateReports(reportOutputDirectory, reportFormat);
+ engine.writeReports(getProjectName(),new File(reportOutputDirectory), reportFormat);
if (this.failBuildOnCVSS <= 10) {
checkForFailure(engine.getDependencies());
diff --git a/dependency-check-cli/pom.xml b/dependency-check-cli/pom.xml
index a1d13d0c2..03529b9a6 100644
--- a/dependency-check-cli/pom.xml
+++ b/dependency-check-cli/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 1.4.6-SNAPSHOT
+ 2.0.0-SNAPSHOTdependency-check-cli
diff --git a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
index 52c6fce77..8b7b709f3 100644
--- a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
+++ b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
@@ -281,18 +281,9 @@ public class App {
}
exCol = ex;
}
- final List dependencies = engine.getDependencies();
- DatabaseProperties prop = null;
- try (CveDB cve = CveDB.getInstance()) {
- prop = cve.getDatabaseProperties();
- } catch (DatabaseException ex) {
- //TODO shouldn't this be a fatal exception
- LOGGER.debug("Unable to retrieve DB Properties", ex);
- }
- final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
try {
- report.generateReports(reportDirectory, outputFormat);
+ engine.writeReports(applicationName, new File(reportDirectory), outputFormat);
} catch (ReportException ex) {
if (exCol != null) {
exCol.addException(ex);
@@ -306,7 +297,7 @@ public class App {
}
//Set the exit code based on whether we found a high enough vulnerability
- for (Dependency dep : dependencies) {
+ for (Dependency dep : engine.getDependencies()) {
if (!dep.getVulnerabilities().isEmpty()) {
for (Vulnerability vuln : dep.getVulnerabilities()) {
LOGGER.debug("VULNERABILITY FOUND " + dep.getDisplayFileName());
@@ -316,7 +307,6 @@ public class App {
}
}
}
-
return retCode;
} finally {
if (engine != null) {
@@ -353,8 +343,7 @@ public class App {
* @throws InvalidSettingException thrown when a user defined properties
* file is unable to be loaded.
*/
- private void populateSettings(CliParser cli) throws InvalidSettingException {
- final boolean autoUpdate = cli.isAutoUpdate();
+ protected void populateSettings(CliParser cli) throws InvalidSettingException {
final String connectionTimeout = cli.getConnectionTimeout();
final String proxyServer = cli.getProxyServer();
final String proxyPort = cli.getProxyPort();
@@ -377,7 +366,8 @@ public class App {
final String cveBase12 = cli.getBaseCve12Url();
final String cveBase20 = cli.getBaseCve20Url();
final Integer cveValidForHours = cli.getCveValidForHours();
- final boolean experimentalEnabled = cli.isExperimentalEnabled();
+ final Boolean autoUpdate = cli.isAutoUpdate();
+ final Boolean experimentalEnabled = cli.isExperimentalEnabled();
if (propertiesFile != null) {
try {
@@ -390,7 +380,7 @@ public class App {
}
// We have to wait until we've merged the properties before attempting to set whether we use
// the proxy for Nexus since it could be disabled in the properties, but not explicitly stated
- // on the command line
+ // on the command line. This is true of other boolean values set below not using the setBooleanIfNotNull.
final boolean nexusUsesProxy = cli.isNexusUsesProxy();
if (dataDirectory != null) {
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
@@ -404,7 +394,7 @@ public class App {
final File dataDir = new File(base, sub);
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
}
- Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
+ Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUser);
@@ -415,7 +405,8 @@ public class App {
Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
//File Type Analyzer Settings
- Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled);
+ Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled);
+
Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled());
diff --git a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
index c259e50d0..2ac6152c6 100644
--- a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
+++ b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
@@ -567,6 +567,32 @@ public final class CliParser {
return value;
}
+ /**
+ * Utility method to determine if one of the disable options has been set.
+ * If not set, this method will check the currently configured settings for
+ * the current value to return.
+ *
+ * Example given `--disableArchive` on the command line would cause this
+ * method to return true for the disable archive setting.
+ *
+ * @param argument the command line argument
+ * @param setting the corresponding settings key
+ * @return true if the disable option was set, if not set the currently
+ * configured value will be returned
+ */
+ private boolean hasDisableOption(String argument, String setting) {
+ if (line == null || !line.hasOption(argument)) {
+ try {
+ return !Settings.getBoolean(setting);
+ } catch (InvalidSettingException ise) {
+ LOGGER.warn("Invalid property setting '{}' defaulting to false", setting);
+ return false;
+ }
+ } else {
+ return true;
+ }
+ }
+
/**
* Returns true if the disableJar command line argument was specified.
*
@@ -574,7 +600,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isJarDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR);
+ return hasDisableOption(ARGUMENT.DISABLE_JAR, Settings.KEYS.ANALYZER_JAR_ENABLED);
}
/**
@@ -584,7 +610,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isArchiveDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE);
+ return hasDisableOption(ARGUMENT.DISABLE_ARCHIVE, Settings.KEYS.ANALYZER_ARCHIVE_ENABLED);
}
/**
@@ -594,7 +620,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isNuspecDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC);
+ return hasDisableOption(ARGUMENT.DISABLE_NUSPEC, Settings.KEYS.ANALYZER_NUSPEC_ENABLED);
}
/**
@@ -604,7 +630,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isAssemblyDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY);
+ return hasDisableOption(ARGUMENT.DISABLE_ASSEMBLY, Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED);
}
/**
@@ -615,7 +641,7 @@ public final class CliParser {
* specified; otherwise false
*/
public boolean isBundleAuditDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT);
+ return hasDisableOption(ARGUMENT.DISABLE_BUNDLE_AUDIT, Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED);
}
/**
@@ -625,7 +651,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isPythonDistributionDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST);
+ return hasDisableOption(ARGUMENT.DISABLE_PY_DIST, Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED);
}
/**
@@ -635,7 +661,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isPythonPackageDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG);
+ return hasDisableOption(ARGUMENT.DISABLE_PY_PKG, Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED);
}
/**
@@ -645,7 +671,7 @@ public final class CliParser {
* argument was specified; otherwise false
*/
public boolean isRubyGemspecDisabled() {
- return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS);
+ return hasDisableOption(ARGUMENT.DISABLE_RUBYGEMS, Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED);
}
/**
@@ -655,7 +681,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isCmakeDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE);
+ return hasDisableOption(ARGUMENT.DISABLE_CMAKE, Settings.KEYS.ANALYZER_CMAKE_ENABLED);
}
/**
@@ -665,7 +691,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isAutoconfDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF);
+ return hasDisableOption(ARGUMENT.DISABLE_AUTOCONF, Settings.KEYS.ANALYZER_AUTOCONF_ENABLED);
}
/**
@@ -675,7 +701,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isComposerDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER);
+ return hasDisableOption(ARGUMENT.DISABLE_COMPOSER, Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED);
}
/**
@@ -685,7 +711,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isNexusDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
+ return hasDisableOption(ARGUMENT.DISABLE_NEXUS, Settings.KEYS.ANALYZER_NEXUS_ENABLED);
}
/**
@@ -695,7 +721,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isOpenSSLDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL);
+ return hasDisableOption(ARGUMENT.DISABLE_OPENSSL, Settings.KEYS.ANALYZER_OPENSSL_ENABLED);
}
/**
@@ -705,7 +731,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isNodeJsDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS);
+ return hasDisableOption(ARGUMENT.DISABLE_NODE_JS, Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED);
}
/**
@@ -716,7 +742,7 @@ public final class CliParser {
* specified; otherwise false
*/
public boolean isCocoapodsAnalyzerDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_COCOAPODS);
+ return hasDisableOption(ARGUMENT.DISABLE_COCOAPODS, Settings.KEYS.ANALYZER_COCOAPODS_ENABLED);
}
/**
@@ -727,7 +753,7 @@ public final class CliParser {
* argument was specified; otherwise false
*/
public boolean isSwiftPackageAnalyzerDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_SWIFT);
+ return hasDisableOption(ARGUMENT.DISABLE_SWIFT, Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED);
}
/**
@@ -737,7 +763,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isCentralDisabled() {
- return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
+ return hasDisableOption(ARGUMENT.DISABLE_CENTRAL, Settings.KEYS.ANALYZER_CENTRAL_ENABLED);
}
/**
@@ -1029,10 +1055,10 @@ public final class CliParser {
* disabled via the command line this will return false.
*
* @return true if auto-update is allowed; otherwise
- * false
+ * null
*/
- public boolean isAutoUpdate() {
- return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
+ public Boolean isAutoUpdate() {
+ return (line != null && line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE)) ? false : null;
}
/**
@@ -1134,10 +1160,10 @@ public final class CliParser {
/**
* Returns true if the experimental analyzers are enabled.
*
- * @return true if the experimental analyzers are enabled; otherwise false
+ * @return true if the experimental analyzers are enabled; otherwise null
*/
- public boolean isExperimentalEnabled() {
- return line.hasOption(ARGUMENT.EXPERIMENTAL);
+ public Boolean isExperimentalEnabled() {
+ return (line != null && line.hasOption(ARGUMENT.EXPERIMENTAL)) ? true : null;
}
/**
diff --git a/dependency-check-cli/src/test/java/org/owasp/dependencycheck/AppTest.java b/dependency-check-cli/src/test/java/org/owasp/dependencycheck/AppTest.java
index fdadb0e39..9659c5241 100644
--- a/dependency-check-cli/src/test/java/org/owasp/dependencycheck/AppTest.java
+++ b/dependency-check-cli/src/test/java/org/owasp/dependencycheck/AppTest.java
@@ -13,18 +13,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (c) 2015 The OWASP Foundatio. All Rights Reserved.
+ * Copyright (c) 2017 The OWASP Foundatio. All Rights Reserved.
*/
package org.owasp.dependencycheck;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.UnrecognizedOptionException;
import org.junit.Test;
import static org.junit.Assert.*;
+import org.owasp.dependencycheck.utils.InvalidSettingException;
+import org.owasp.dependencycheck.utils.Settings;
/**
*
* @author jeremy
*/
public class AppTest {
+
/**
* Test of ensureCanonicalPath method, of class App.
*/
@@ -35,17 +45,83 @@ public class AppTest {
String result = instance.ensureCanonicalPath(file);
assertFalse(result.contains(".."));
assertTrue(result.endsWith("*.jar"));
- }
- /**
- * Test of ensureCanonicalPath method, of class App.
- */
- @Test
- public void testEnsureCanonicalPath2() {
- String file = "../some/skip/../path/file.txt";
- App instance = new App();
+ file = "../some/skip/../path/file.txt";
String expResult = "/some/path/file.txt";
- String result = instance.ensureCanonicalPath(file);
+ result = instance.ensureCanonicalPath(file);
assertTrue("result=" + result, result.endsWith(expResult));
}
+
+ @Test(expected = UnrecognizedOptionException.class)
+ public void testPopulateSettingsException() throws FileNotFoundException, ParseException, InvalidSettingException, URISyntaxException {
+ String[] args = {"-invalidPROPERTY"};
+ assertTrue(testBooleanProperties(args, null));
+ }
+
+ @Test
+ public void testPopulateSettings() throws FileNotFoundException, ParseException, InvalidSettingException, URISyntaxException {
+ File prop = new File(this.getClass().getClassLoader().getResource("sample.properties").toURI().getPath());
+ String[] args = {"-P", prop.getAbsolutePath()};
+ Map expected = new HashMap<>();
+ expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE);
+ expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.TRUE);
+
+ assertTrue(testBooleanProperties(args, expected));
+
+ String[] args2 = {"-n"};
+ expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE);
+ expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.TRUE);
+ assertTrue(testBooleanProperties(args2, expected));
+
+ String[] args3 = {"-h"};
+ expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.TRUE);
+ expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.TRUE);
+ assertTrue(testBooleanProperties(args3, expected));
+
+ String[] args4 = {"--disableArchive"};
+ expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.TRUE);
+ expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.FALSE);
+ assertTrue(testBooleanProperties(args4, expected));
+
+ String[] args5 = {"-P", prop.getAbsolutePath(), "--disableArchive"};
+ expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE);
+ expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.FALSE);
+ assertTrue(testBooleanProperties(args5, expected));
+
+ prop = new File(this.getClass().getClassLoader().getResource("sample2.properties").toURI().getPath());
+ String[] args6 = {"-P", prop.getAbsolutePath(), "--disableArchive"};
+ expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.TRUE);
+ expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.FALSE);
+ assertTrue(testBooleanProperties(args6, expected));
+
+ String[] args7 = {"-P", prop.getAbsolutePath(), "--noupdate"};
+ expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE);
+ expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.FALSE);
+ assertTrue(testBooleanProperties(args7, expected));
+
+ String[] args8 = {"-P", prop.getAbsolutePath(), "--noupdate", "--disableArchive"};
+ expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE);
+ expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.FALSE);
+ assertTrue(testBooleanProperties(args8, expected));
+
+
+ }
+
+ private boolean testBooleanProperties(String[] args, Map expected) throws URISyntaxException, FileNotFoundException, ParseException, InvalidSettingException {
+ Settings.initialize();
+ try {
+ final CliParser cli = new CliParser();
+ cli.parse(args);
+ App instance = new App();
+ instance.populateSettings(cli);
+ boolean results = true;
+ for (Map.Entry entry : expected.entrySet()) {
+ results &= Settings.getBoolean(entry.getKey()) == entry.getValue();
+ }
+
+ return results;
+ } finally {
+ Settings.cleanup();
+ }
+ }
}
diff --git a/dependency-check-cli/src/test/resources/sample.properties b/dependency-check-cli/src/test/resources/sample.properties
new file mode 100644
index 000000000..0b45d5d04
--- /dev/null
+++ b/dependency-check-cli/src/test/resources/sample.properties
@@ -0,0 +1,33 @@
+autoupdate=false
+
+analyzer.experimental.enabled=false
+analyzer.jar.enabled=true
+analyzer.archive.enabled=true
+analyzer.node.package.enabled=true
+analyzer.composer.lock.enabled=true
+analyzer.python.distribution.enabled=true
+analyzer.python.package.enabled=true
+analyzer.ruby.gemspec.enabled=true
+analyzer.autoconf.enabled=true
+analyzer.cmake.enabled=true
+analyzer.assembly.enabled=true
+analyzer.nuspec.enabled=true
+analyzer.openssl.enabled=true
+analyzer.central.enabled=true
+analyzer.nexus.enabled=false
+analyzer.cocoapods.enabled=true
+analyzer.swift.package.manager.enabled=true
+#whether the nexus analyzer uses the proxy
+analyzer.nexus.proxy=true
+analyzer.cpe.enabled=true
+analyzer.cpesuppression.enabled=true
+analyzer.dependencybundling.enabled=true
+analyzer.dependencymerging.enabled=true
+analyzer.falsepositive.enabled=true
+analyzer.filename.enabled=true
+analyzer.hint.enabled=true
+analyzer.nvdcve.enabled=true
+analyzer.vulnerabilitysuppression.enabled=true
+updater.nvdcve.enabled=true
+updater.versioncheck.enabled=true
+analyzer.versionfilter.enabled=true
\ No newline at end of file
diff --git a/dependency-check-cli/src/test/resources/sample2.properties b/dependency-check-cli/src/test/resources/sample2.properties
new file mode 100644
index 000000000..00d0e5a27
--- /dev/null
+++ b/dependency-check-cli/src/test/resources/sample2.properties
@@ -0,0 +1,33 @@
+autoupdate=true
+
+analyzer.experimental.enabled=true
+analyzer.jar.enabled=false
+analyzer.archive.enabled=false
+analyzer.node.package.enabled=false
+analyzer.composer.lock.enabled=false
+analyzer.python.distribution.enabled=false
+analyzer.python.package.enabled=false
+analyzer.ruby.gemspec.enabled=false
+analyzer.autoconf.enabled=false
+analyzer.cmake.enabled=false
+analyzer.assembly.enabled=false
+analyzer.nuspec.enabled=false
+analyzer.openssl.enabled=false
+analyzer.central.enabled=false
+analyzer.nexus.enabled=true
+analyzer.cocoapods.enabled=false
+analyzer.swift.package.manager.enabled=false
+#whether the nexus analyzer uses the proxy
+analyzer.nexus.proxy=false
+analyzer.cpe.enabled=false
+analyzer.cpesuppression.enabled=false
+analyzer.dependencybundling.enabled=false
+analyzer.dependencymerging.enabled=false
+analyzer.falsepositive.enabled=false
+analyzer.filename.enabled=false
+analyzer.hint.enabled=false
+analyzer.nvdcve.enabled=false
+analyzer.vulnerabilitysuppression.enabled=false
+updater.nvdcve.enabled=false
+updater.versioncheck.enabled=false
+analyzer.versionfilter.enabled=false
\ No newline at end of file
diff --git a/dependency-check-core/pom.xml b/dependency-check-core/pom.xml
index 47db9f89c..3425e4a16 100644
--- a/dependency-check-core/pom.xml
+++ b/dependency-check-core/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 1.4.6-SNAPSHOT
+ 2.0.0-SNAPSHOTdependency-check-core
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java
index bfbc066c8..6d7915e15 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java
@@ -54,6 +54,9 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
+import org.owasp.dependencycheck.exception.ReportException;
+import org.owasp.dependencycheck.reporting.ReportGenerator;
/**
* Scans files, directories, etc. for Dependencies. Analyzers are loaded and
@@ -796,4 +799,42 @@ public class Engine implements FileFilter {
exceptions.add(throwable);
throw new ExceptionCollection(message, exceptions, true);
}
+
+ /**
+ * Writes the report to the given output directory.
+ *
+ * @param applicationName the name of the application/project
+ * @param groupId the Maven groupId
+ * @param artifactId the Maven artifactId
+ * @param version the Maven version
+ * @param outputDir the path to the output directory (can include the full
+ * file name if the format is not ALL)
+ * @param format the report format (ALL, HTML, CSV, JSON, etc.)
+ * @throws ReportException thrown if there is an error generating the report
+ */
+ public void writeReports(String applicationName, String groupId, String artifactId,
+ String version, File outputDir, String format) throws ReportException {
+
+ final DatabaseProperties prop = database.getDatabaseProperties();
+ final ReportGenerator r = new ReportGenerator(applicationName, groupId, artifactId, version, dependencies, getAnalyzers(), prop);
+ try {
+ r.write(outputDir.getAbsolutePath(), format);
+ } catch (ReportException ex) {
+ final String msg = String.format("Error generating the report for %s", applicationName);
+ throw new ReportException(msg, ex);
+ }
+ }
+
+ /**
+ * Writes the report to the given output directory.
+ *
+ * @param applicationName the name of the application/project
+ * @param outputDir the path to the output directory (can include the full
+ * file name if the format is not ALL)
+ * @param format the report format (ALL, HTML, CSV, JSON, etc.)
+ * @throws ReportException thrown if there is an error generating the report
+ */
+ public void writeReports(String applicationName, File outputDir, String format) throws ReportException {
+ writeReports(applicationName, null, null, null, outputDir, format);
+ }
}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java
index 2ee63b1f6..e63c51214 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java
@@ -18,12 +18,9 @@
package org.owasp.dependencycheck.agent;
import java.io.File;
-import java.io.IOException;
import java.util.List;
import org.owasp.dependencycheck.Engine;
-import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
-import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.Vulnerability;
@@ -840,21 +837,15 @@ public class DependencyCheckScanAgent {
*
* @param engine a dependency-check engine
* @param outDirectory the directory to write the reports to
+ * @throw ScanAgentException thrown if there is an error generating the
+ * report
*/
- private void generateExternalReports(Engine engine, File outDirectory) {
- DatabaseProperties prop = null;
- try (CveDB cve = CveDB.getInstance()) {
- prop = cve.getDatabaseProperties();
- } catch (DatabaseException ex) {
- //TODO shouldn't this be a fatal exception
- LOGGER.debug("Unable to retrieve DB Properties", ex);
- }
- final ReportGenerator r = new ReportGenerator(this.applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
+ private void generateExternalReports(Engine engine, File outDirectory) throws ScanAgentException {
try {
- r.generateReports(outDirectory.getCanonicalPath(), this.reportFormat.name());
- } catch (IOException | ReportException ex) {
- LOGGER.error("Unexpected exception occurred during analysis; please see the verbose error log for more details.");
- LOGGER.debug("", ex);
+ engine.writeReports(applicationName, outDirectory, this.reportFormat.name());
+ } catch (ReportException ex) {
+ LOGGER.debug("Unexpected exception occurred during analysis; please see the verbose error log for more details.", ex);
+ throw new ScanAgentException("Error generating the report", ex);
}
}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java
index 7b42d82c3..d88a25119 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java
@@ -24,6 +24,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
@@ -36,6 +37,7 @@ import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
import javax.annotation.concurrent.ThreadSafe;
+import org.apache.commons.collections.map.ReferenceMap;
import org.owasp.dependencycheck.data.cwe.CweDB;
import org.owasp.dependencycheck.dependency.Reference;
import org.owasp.dependencycheck.dependency.Vulnerability;
@@ -48,6 +50,8 @@ import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.apache.commons.collections.map.AbstractReferenceMap.HARD;
+import static org.apache.commons.collections.map.AbstractReferenceMap.SOFT;
import static org.owasp.dependencycheck.data.nvdcve.CveDB.PreparedStatementCveDb.*;
/**
@@ -91,6 +95,12 @@ public final class CveDB implements AutoCloseable {
*/
private final EnumMap preparedStatements = new EnumMap<>(PreparedStatementCveDb.class);
+ /**
+ * Cache for CVE lookups; used to speed up the vulnerability search process.
+ */
+ @SuppressWarnings("unchecked")
+ private final Map> vulnerabilitiesForCpeCache = Collections.synchronizedMap(new ReferenceMap(HARD, SOFT));
+
/**
* The enum value names must match the keys of the statements in the
* statement bundles "dbStatements*.properties".
@@ -269,6 +279,7 @@ public final class CveDB implements AutoCloseable {
instance.usageCount -= 1;
if (instance.usageCount <= 0 && instance.isOpen()) {
instance.usageCount = 0;
+ clearCache();
instance.closeStatements();
try {
instance.connection.close();
@@ -474,6 +485,7 @@ public final class CveDB implements AutoCloseable {
* @param value the property value
*/
public synchronized void saveProperty(String key, String value) {
+ clearCache();
try {
try {
final PreparedStatement mergeProperty = getPreparedStatement(MERGE_PROPERTY);
@@ -498,6 +510,18 @@ public final class CveDB implements AutoCloseable {
}
}
+ /**
+ * Clears cache. Should be called whenever something is modified. While this
+ * is not the optimal cache eviction strategy, this is good enough for
+ * typical usage (update DB and then only read) and it is easier to maintain
+ * the code.
+ *
+ * It should be also called when DB is closed.
+ */
+ private void clearCache() {
+ vulnerabilitiesForCpeCache.clear();
+ }
+
/**
* Retrieves the vulnerabilities associated with the specified CPE.
*
@@ -506,6 +530,13 @@ public final class CveDB implements AutoCloseable {
* @throws DatabaseException thrown if there is an exception retrieving data
*/
public synchronized List getVulnerabilities(String cpeStr) throws DatabaseException {
+ final List cachedVulnerabilities = vulnerabilitiesForCpeCache.get(cpeStr);
+ if (cachedVulnerabilities != null) {
+ LOGGER.debug("Cache hit for {}", cpeStr);
+ return cachedVulnerabilities;
+ } else {
+ LOGGER.debug("Cache miss for {}", cpeStr);
+ }
final VulnerableSoftware cpe = new VulnerableSoftware();
try {
cpe.parseName(cpeStr);
@@ -554,6 +585,7 @@ public final class CveDB implements AutoCloseable {
} finally {
DBUtils.closeResultSet(rs);
}
+ vulnerabilitiesForCpeCache.put(cpeStr, vulnerabilities);
return vulnerabilities;
}
@@ -633,6 +665,7 @@ public final class CveDB implements AutoCloseable {
* @throws DatabaseException is thrown if the database
*/
public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException {
+ clearCache();
try {
int vulnerabilityId = 0;
final PreparedStatement selectVulnerabilityId = getPreparedStatement(SELECT_VULNERABILITY_ID);
@@ -799,6 +832,7 @@ public final class CveDB implements AutoCloseable {
* ensure orphan entries are removed.
*/
public synchronized void cleanupDatabase() {
+ clearCache();
try {
final PreparedStatement ps = getPreparedStatement(CLEANUP_ORPHANS);
if (ps != null) {
@@ -934,6 +968,7 @@ public final class CveDB implements AutoCloseable {
* Deletes unused dictionary entries from the database.
*/
public synchronized void deleteUnusedCpe() {
+ clearCache();
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE"));
@@ -956,6 +991,7 @@ public final class CveDB implements AutoCloseable {
* @param product the CPE product
*/
public synchronized void addCpe(String cpe, String vendor, String product) {
+ clearCache();
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(statementBundle.getString("ADD_DICT_CPE"));
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/EscapeTool.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/EscapeTool.java
index 48014183a..4eb456176 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/EscapeTool.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/EscapeTool.java
@@ -124,7 +124,7 @@ public class EscapeTool {
return "";
}
boolean addComma = false;
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
for (Identifier id : ids) {
if (!"cpe".equals(id.getType())) {
if (addComma) {
@@ -150,7 +150,7 @@ public class EscapeTool {
return "";
}
boolean addComma = false;
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
for (Identifier id : ids) {
if ("cpe".equals(id.getType())) {
if (addComma) {
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java
index b8acd2557..d31705519 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java
@@ -107,29 +107,8 @@ public class ReportGenerator {
*/
public ReportGenerator(String applicationName, List dependencies, List analyzers, DatabaseProperties properties) {
velocityEngine = createVelocityEngine();
- context = createContext();
-
velocityEngine.init();
- final EscapeTool enc = new EscapeTool();
-
- final DateTime dt = new DateTime();
- final DateTimeFormatter dateFormat = DateTimeFormat.forPattern("MMM d, yyyy 'at' HH:mm:ss z");
- final DateTimeFormatter dateFormatXML = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
-
-// final Date d = new Date();
-// final DateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy 'at' HH:mm:ss z");
-// final DateFormat dateFormatXML = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
- final String scanDate = dateFormat.print(dt);
- final String scanDateXML = dateFormatXML.print(dt);
-
- context.put("applicationName", applicationName);
- context.put("dependencies", dependencies);
- context.put("analyzers", analyzers);
- context.put("properties", properties);
- context.put("scanDate", scanDate);
- context.put("scanDateXML", scanDateXML);
- context.put("enc", enc);
- context.put("version", Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
+ context = createContext(applicationName, dependencies, analyzers, properties);
}
/**
@@ -148,9 +127,15 @@ public class ReportGenerator {
List dependencies, List analyzers, DatabaseProperties properties) {
this(applicationName, dependencies, analyzers, properties);
- context.put("applicationVersion", version);
- context.put("artifactID", artifactID);
- context.put("groupID", groupID);
+ if (version != null) {
+ context.put("applicationVersion", version);
+ }
+ if (artifactID != null) {
+ context.put("artifactID", artifactID);
+ }
+ if (groupID != null) {
+ context.put("groupID", groupID);
+ }
}
/**
@@ -166,67 +151,235 @@ public class ReportGenerator {
}
/**
- * Creates a new Velocity Context.
+ * Constructs the velocity context used to generate the dependency-check
+ * reports.
*
- * @return a Velocity Context
+ * @param applicationName the application name being analyzed
+ * @param dependencies the list of dependencies
+ * @param analyzers the list of analyzers used
+ * @param properties the database properties (containing timestamps of the
+ * NVD CVE data)
+ * @return the velocity context
*/
- private Context createContext() {
- return new VelocityContext();
+ private VelocityContext createContext(String applicationName, List dependencies, List analyzers, DatabaseProperties properties) {
+ final DateTime dt = new DateTime();
+ final DateTimeFormatter dateFormat = DateTimeFormat.forPattern("MMM d, yyyy 'at' HH:mm:ss z");
+ final DateTimeFormatter dateFormatXML = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+
+ final String scanDate = dateFormat.print(dt);
+ final String scanDateXML = dateFormatXML.print(dt);
+
+ final VelocityContext ctxt = new VelocityContext();
+ ctxt.put("applicationName", applicationName);
+ ctxt.put("dependencies", dependencies);
+ ctxt.put("analyzers", analyzers);
+ ctxt.put("properties", properties);
+ ctxt.put("scanDate", scanDate);
+ ctxt.put("scanDateXML", scanDateXML);
+ ctxt.put("enc", new EscapeTool());
+ ctxt.put("version", Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
+ return ctxt;
}
/**
- * Generates the Dependency Reports for the identified dependencies.
+ * Writes the dependency-check report to the given output location.
*
- * @param outputStream the OutputStream to send the generated report to
- * @param format the format the report should be written in
- * @throws IOException is thrown when the template file does not exist
- * @throws Exception is thrown if there is an error writing out the reports
- */
- public void generateReports(OutputStream outputStream, Format format) throws IOException, Exception {
- if (format == Format.XML || format == Format.ALL) {
- generateReport("XmlReport", outputStream);
- }
- if (format == Format.HTML || format == Format.ALL) {
- generateReport("HtmlReport", outputStream);
- }
- if (format == Format.VULN || format == Format.ALL) {
- generateReport("VulnerabilityReport", outputStream);
- }
- if (format == Format.JSON || format == Format.ALL) {
- generateReport("JsonReport", outputStream);
- }
- if (format == Format.CSV || format == Format.ALL) {
- generateReport("CsvReport", outputStream);
- }
- }
-
- /**
- * Generates the Dependency Reports for the identified dependencies.
- *
- * @param outputDir the path where the reports should be written
- * @param format the format the report should be written in
- * @throws ReportException is thrown if there is an error writing out the
+ * @param outputLocation the path where the reports should be written
+ * @param format the format the report should be written in (XML, HTML,
+ * JSON, CSV, ALL) or even the path to a custom velocity template (either
+ * fully qualified or the template name on the class path).
+ * @throws ReportException is thrown if there is an error creating out the
* reports
*/
- public void generateReports(String outputDir, Format format) throws ReportException {
- if (format == Format.XML || format == Format.ALL) {
- generateReport("XmlReport", outputDir + File.separator + "dependency-check-report.xml");
+ public void write(String outputLocation, String format) throws ReportException {
+ Format reportFormat = null;
+ try {
+ reportFormat = Format.valueOf(format.toUpperCase());
+ } catch (IllegalArgumentException ex) {
+ LOGGER.trace("ignore this exception", ex);
}
- if (format == Format.JSON || format == Format.ALL) {
- generateReport("JsonReport", outputDir + File.separator + "dependency-check-report.json");
- pretifyJson(outputDir + File.separator + "dependency-check-report.json");
+
+ if (reportFormat != null) {
+ write(outputLocation, reportFormat);
+ } else {
+ final File out = getReportFile(outputLocation, null);
+ if (out.isDirectory()) {
+ throw new ReportException("Unable to write non-standard VSL output to a directory, please specify a file name");
+ }
+ processTemplate(format, out);
}
- if (format == Format.CSV || format == Format.ALL) {
- generateReport("CsvReport", outputDir + File.separator + "dependency-check-report.csv");
- }
- if (format == Format.HTML || format == Format.ALL) {
- generateReport("HtmlReport", outputDir + File.separator + "dependency-check-report.html");
- }
- if (format == Format.VULN || format == Format.ALL) {
- generateReport("VulnerabilityReport", outputDir + File.separator + "dependency-check-vulnerability.html");
+
+ }
+
+ /**
+ * Writes the dependency-check report(s).
+ *
+ * @param outputLocation the path where the reports should be written
+ * @param format the format the report should be written in (XML, HTML, ALL)
+ * @throws ReportException is thrown if there is an error creating out the
+ * reports
+ */
+ public void write(String outputLocation, Format format) throws ReportException {
+ if (format == Format.ALL) {
+ for (Format f : Format.values()) {
+ if (f != Format.ALL) {
+ write(outputLocation, f);
+ }
+ }
+ } else {
+ final File out = getReportFile(outputLocation, format);
+ final String templateName = format.toString().toLowerCase() + "Report";
+ processTemplate(templateName, out);
+ if (format == Format.JSON) {
+ pretifyJson(out.getPath());
+ }
}
}
+// /**
+// * Writes the dependency-check report(s).
+// *
+// * @param outputStream the OutputStream to send the generated report to
+// * @param format the format the report should be written in
+// * @throws ReportException thrown if the report format is ALL
+// * @throws IOException is thrown when the template file does not exist
+// * @throws Exception is thrown if there is an error writing out the reports
+// */
+// public void write(OutputStream outputStream, Format format) throws ReportException, IOException, Exception {
+// if (format == Format.ALL) {
+// throw new ReportException("Unable to write ALL reports to a single output stream, please check the API");
+// }
+// final String templateName = format.toString().toLowerCase() + "Report";
+// processTemplate(templateName, outputStream);
+// }
+
+ /**
+ * Determines the report file name based on the give output location and
+ * format. If the output location contains a full file name that has the
+ * correct extension for the given report type then the output location is
+ * returned. However, if the output location is a directory, this method
+ * will generate the correct name for the given output format.
+ *
+ * @param outputLocation the specified output location
+ * @param format the report format
+ * @return the report File
+ */
+ protected File getReportFile(String outputLocation, Format format) {
+ File outFile = new File(outputLocation);
+ if (outFile.getParentFile() == null) {
+ outFile = new File(".", outputLocation);
+ }
+ final String pathToCheck = outputLocation.toLowerCase();
+ if (format == Format.XML && !pathToCheck.endsWith(".xml")) {
+ return new File(outFile, "dependency-check-report.xml");
+ }
+ if (format == Format.HTML && !pathToCheck.endsWith(".html") && !pathToCheck.endsWith(".htm")) {
+ return new File(outFile, "dependency-check-report.html");
+ }
+ if (format == Format.VULN && !pathToCheck.endsWith(".html") && !pathToCheck.endsWith(".htm")) {
+ return new File(outFile, "dependency-check-vulnerability.html");
+ }
+ if (format == Format.JSON && !pathToCheck.endsWith(".json")) {
+ return new File(outFile, "dependency-check-report.json");
+ }
+ if (format == Format.CSV && !pathToCheck.endsWith(".csv")) {
+ return new File(outFile, "dependency-check-report.csv");
+ }
+ return outFile;
+ }
+
+ /**
+ * Generates a report from a given Velocity Template. The template name
+ * provided can be the name of a template contained in the jar file, such as
+ * 'XmlReport' or 'HtmlReport', or the template name can be the path to a
+ * template file.
+ *
+ * @param template the name of the template to load
+ * @param file the output file to write the report to
+ * @throws ReportException is thrown when the report cannot be generated
+ */
+ protected void processTemplate(String template, File file) throws ReportException {
+ ensureParentDirectoryExists(file);
+ try (OutputStream output = new FileOutputStream(file)) {
+ processTemplate(template, output);
+ } catch (IOException ex) {
+ throw new ReportException(String.format("Unable to write to file: %s", file), ex);
+ }
+ }
+
+ /**
+ * Generates a report from a given Velocity Template. The template name
+ * provided can be the name of a template contained in the jar file, such as
+ * 'XmlReport' or 'HtmlReport', or the template name can be the path to a
+ * template file.
+ *
+ * @param templateName the name of the template to load
+ * @param outputStream the OutputStream to write the report to
+ * @throws ReportException is thrown when an exception occurs
+ */
+ protected void processTemplate(String templateName, OutputStream outputStream) throws ReportException {
+ InputStream input = null;
+ String logTag = null;
+ final File f = new File(templateName);
+ try {
+ if (f.isFile()) {
+ try {
+ logTag = templateName;
+ input = new FileInputStream(f);
+ } catch (FileNotFoundException ex) {
+ throw new ReportException("Unable to locate template file: " + templateName, ex);
+ }
+ } else {
+ logTag = "templates/" + templateName + ".vsl";
+ input = this.getClass().getClassLoader().getResourceAsStream(logTag);
+ }
+ if (input == null) {
+ logTag = templateName;
+ input = this.getClass().getClassLoader().getResourceAsStream(templateName);
+ }
+ if (input == null) {
+ throw new ReportException("Template file doesn't exist: " + logTag);
+ }
+
+ try (InputStreamReader reader = new InputStreamReader(input, "UTF-8");
+ OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8")) {
+ if (!velocityEngine.evaluate(context, writer, logTag, reader)) {
+ throw new ReportException("Failed to convert the template into html.");
+ }
+ writer.flush();
+ } catch (UnsupportedEncodingException ex) {
+ throw new ReportException("Unable to generate the report using UTF-8", ex);
+ } catch (IOException ex) {
+ throw new ReportException("Unable to write the report", ex);
+ }
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException ex) {
+ LOGGER.trace("Error closing input", ex);
+ }
+ }
+ }
+ }
+ /**
+ * Validates that the given file's parent directory exists. If the directory
+ * does not exist an attempt to create the necessary path is made; if that
+ * fails a ReportException will be raised.
+ *
+ * @param file the file or directory directory
+ * @throws ReportException thrown if the parent directory does not exist and
+ * cannot be created
+ */
+ private void ensureParentDirectoryExists(File file) throws ReportException {
+ if (!file.getParentFile().exists()) {
+ final boolean created = file.getParentFile().mkdirs();
+ if (!created) {
+ final String msg = String.format("Unable to create directory '%s'.", file.getParentFile().getAbsolutePath());
+ throw new ReportException(msg);
+ }
+ }
+ }
/**
* Reformats the given JSON file.
*
@@ -311,139 +464,4 @@ public class ReportGenerator {
}
}
}
-
- /**
- * Generates the Dependency Reports for the identified dependencies.
- *
- * @param outputDir the path where the reports should be written
- * @param outputFormat the format the report should be written in (XML,
- * HTML, ALL)
- * @throws ReportException is thrown if there is an error creating out the
- * reports
- */
- public void generateReports(String outputDir, String outputFormat) throws ReportException {
- final String format = outputFormat.toUpperCase();
- final String pathToCheck = outputDir.toLowerCase();
- if (format.matches("^(XML|HTML|VULN|JSON|ALL)$")) {
- if ("XML".equalsIgnoreCase(format)) {
- if (pathToCheck.endsWith(".xml")) {
- generateReport("XmlReport", outputDir);
- } else {
- generateReports(outputDir, Format.XML);
- }
- }
- if ("HTML".equalsIgnoreCase(format)) {
- if (pathToCheck.endsWith(".html") || pathToCheck.endsWith(".htm")) {
- generateReport("HtmlReport", outputDir);
- } else {
- generateReports(outputDir, Format.HTML);
- }
- }
- if ("VULN".equalsIgnoreCase(format)) {
- if (pathToCheck.endsWith(".html") || pathToCheck.endsWith(".htm")) {
- generateReport("VulnReport", outputDir);
- } else {
- generateReports(outputDir, Format.VULN);
- }
- }
- if ("JSON".equalsIgnoreCase(format)) {
- if (pathToCheck.endsWith(".json")) {
- generateReport("JsonReport", outputDir);
- pretifyJson(outputDir);
- } else {
- generateReports(outputDir, Format.JSON);
- }
- }
- if ("CSV".equalsIgnoreCase(format)) {
- if (pathToCheck.endsWith(".csv")) {
- generateReport("CsvReport", outputDir);
- } else {
- generateReports(outputDir, Format.JSON);
- }
- }
- if ("ALL".equalsIgnoreCase(format)) {
- generateReports(outputDir, Format.ALL);
- }
- }
- }
-
- /**
- * Generates a report from a given Velocity Template. The template name
- * provided can be the name of a template contained in the jar file, such as
- * 'XmlReport' or 'HtmlReport', or the template name can be the path to a
- * template file.
- *
- * @param templateName the name of the template to load
- * @param outputStream the OutputStream to write the report to
- * @throws ReportException is thrown when an exception occurs
- */
- protected void generateReport(String templateName, OutputStream outputStream) throws ReportException {
- InputStream input = null;
- String templatePath = null;
- final File f = new File(templateName);
- try {
- if (f.exists() && f.isFile()) {
- try {
- templatePath = templateName;
- input = new FileInputStream(f);
- } catch (FileNotFoundException ex) {
- throw new ReportException("Unable to locate template file: " + templateName, ex);
- }
- } else {
- templatePath = "templates/" + templateName + ".vsl";
- input = this.getClass().getClassLoader().getResourceAsStream(templatePath);
- }
- if (input == null) {
- throw new ReportException("Template file doesn't exist: " + templatePath);
- }
-
- try (InputStreamReader reader = new InputStreamReader(input, "UTF-8");
- OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8")) {
- if (!velocityEngine.evaluate(context, writer, templatePath, reader)) {
- throw new ReportException("Failed to convert the template into html.");
- }
- writer.flush();
- } catch (UnsupportedEncodingException ex) {
- throw new ReportException("Unable to generate the report using UTF-8", ex);
- } catch (IOException ex) {
- throw new ReportException("Unable to write the report", ex);
- }
- } finally {
- if (input != null) {
- try {
- input.close();
- } catch (IOException ex) {
- LOGGER.trace("Error closing input", ex);
- }
- }
- }
- }
-
- /**
- * Generates a report from a given Velocity Template. The template name
- * provided can be the name of a template contained in the jar file, such as
- * 'XmlReport' or 'HtmlReport', or the template name can be the path to a
- * template file.
- *
- * @param templateName the name of the template to load
- * @param outFileName the filename and path to write the report to
- * @throws ReportException is thrown when the report cannot be generated
- */
- protected void generateReport(String templateName, String outFileName) throws ReportException {
- File outFile = new File(outFileName);
- if (outFile.getParentFile() == null) {
- outFile = new File(".", outFileName);
- }
- if (!outFile.getParentFile().exists()) {
- final boolean created = outFile.getParentFile().mkdirs();
- if (!created) {
- throw new ReportException("Unable to create directory '" + outFile.getParentFile().getAbsolutePath() + "'.");
- }
- }
- try (OutputStream outputSteam = new FileOutputStream(outFile)) {
- generateReport(templateName, outputSteam);
- } catch (IOException ex) {
- throw new ReportException("Unable to write to file: " + outFile, ex);
- }
- }
}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlEntity.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlEntity.java
new file mode 100644
index 000000000..acad80fa7
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlEntity.java
@@ -0,0 +1,310 @@
+package org.owasp.dependencycheck.xml;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This is a utility class to convert named XML Entities (such as ø) into
+ * its HTML encoded Unicode code point (i.e. ø). This is a slightly
+ * modified (class/method rename) from an SO answer:
+ * https://stackoverflow.com/questions/7286428/help-the-java-sax-parser-to-understand-bad-xml
+ *
+ * @author https://stackoverflow.com/users/823393/oldcurmudgeon
+ */
+public class XmlEntity {
+ /**
+ * The map of HTML entities.
+ */
+ private static final Map SPECIALS;
+
+ //
+ /**
+ * Create a map HTML Named Entities to their numeric equivalent. Derived
+ * from Wikipedia
+ * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
+ */
+ static {
+ final Map map = new HashMap<>();
+ map.put("quot", 34);
+ map.put("amp", 38);
+ map.put("apos", 39);
+ map.put("lt", 60);
+ map.put("gt", 62);
+ map.put("nbsp", 160);
+ map.put("iexcl", 161);
+ map.put("cent", 162);
+ map.put("pound", 163);
+ map.put("curren", 164);
+ map.put("yen", 165);
+ map.put("brvbar", 166);
+ map.put("sect", 167);
+ map.put("uml", 168);
+ map.put("copy", 169);
+ map.put("ordf", 170);
+ map.put("laquo", 171);
+ map.put("not", 172);
+ map.put("shy", 173);
+ map.put("reg", 174);
+ map.put("macr", 175);
+ map.put("deg", 176);
+ map.put("plusmn", 177);
+ map.put("sup2", 178);
+ map.put("sup3", 179);
+ map.put("acute", 180);
+ map.put("micro", 181);
+ map.put("para", 182);
+ map.put("middot", 183);
+ map.put("cedil", 184);
+ map.put("sup1", 185);
+ map.put("ordm", 186);
+ map.put("raquo", 187);
+ map.put("frac14", 188);
+ map.put("frac12", 189);
+ map.put("frac34", 190);
+ map.put("iquest", 191);
+ map.put("Agrave", 192);
+ map.put("Aacute", 193);
+ map.put("Acirc", 194);
+ map.put("Atilde", 195);
+ map.put("Auml", 196);
+ map.put("Aring", 197);
+ map.put("AElig", 198);
+ map.put("Ccedil", 199);
+ map.put("Egrave", 200);
+ map.put("Eacute", 201);
+ map.put("Ecirc", 202);
+ map.put("Euml", 203);
+ map.put("Igrave", 204);
+ map.put("Iacute", 205);
+ map.put("Icirc", 206);
+ map.put("Iuml", 207);
+ map.put("ETH", 208);
+ map.put("Ntilde", 209);
+ map.put("Ograve", 210);
+ map.put("Oacute", 211);
+ map.put("Ocirc", 212);
+ map.put("Otilde", 213);
+ map.put("Ouml", 214);
+ map.put("times", 215);
+ map.put("Oslash", 216);
+ map.put("Ugrave", 217);
+ map.put("Uacute", 218);
+ map.put("Ucirc", 219);
+ map.put("Uuml", 220);
+ map.put("Yacute", 221);
+ map.put("THORN", 222);
+ map.put("szlig", 223);
+ map.put("agrave", 224);
+ map.put("aacute", 225);
+ map.put("acirc", 226);
+ map.put("atilde", 227);
+ map.put("auml", 228);
+ map.put("aring", 229);
+ map.put("aelig", 230);
+ map.put("ccedil", 231);
+ map.put("egrave", 232);
+ map.put("eacute", 233);
+ map.put("ecirc", 234);
+ map.put("euml", 235);
+ map.put("igrave", 236);
+ map.put("iacute", 237);
+ map.put("icirc", 238);
+ map.put("iuml", 239);
+ map.put("eth", 240);
+ map.put("ntilde", 241);
+ map.put("ograve", 242);
+ map.put("oacute", 243);
+ map.put("ocirc", 244);
+ map.put("otilde", 245);
+ map.put("ouml", 246);
+ map.put("divide", 247);
+ map.put("oslash", 248);
+ map.put("ugrave", 249);
+ map.put("uacute", 250);
+ map.put("ucirc", 251);
+ map.put("uuml", 252);
+ map.put("yacute", 253);
+ map.put("thorn", 254);
+ map.put("yuml", 255);
+ map.put("OElig", 338);
+ map.put("oelig", 339);
+ map.put("Scaron", 352);
+ map.put("scaron", 353);
+ map.put("Yuml", 376);
+ map.put("fnof", 402);
+ map.put("circ", 710);
+ map.put("tilde", 732);
+ map.put("Alpha", 913);
+ map.put("Beta", 914);
+ map.put("Gamma", 915);
+ map.put("Delta", 916);
+ map.put("Epsilon", 917);
+ map.put("Zeta", 918);
+ map.put("Eta", 919);
+ map.put("Theta", 920);
+ map.put("Iota", 921);
+ map.put("Kappa", 922);
+ map.put("Lambda", 923);
+ map.put("Mu", 924);
+ map.put("Nu", 925);
+ map.put("Xi", 926);
+ map.put("Omicron", 927);
+ map.put("Pi", 928);
+ map.put("Rho", 929);
+ map.put("Sigma", 931);
+ map.put("Tau", 932);
+ map.put("Upsilon", 933);
+ map.put("Phi", 934);
+ map.put("Chi", 935);
+ map.put("Psi", 936);
+ map.put("Omega", 937);
+ map.put("alpha", 945);
+ map.put("beta", 946);
+ map.put("gamma", 947);
+ map.put("delta", 948);
+ map.put("epsilon", 949);
+ map.put("zeta", 950);
+ map.put("eta", 951);
+ map.put("theta", 952);
+ map.put("iota", 953);
+ map.put("kappa", 954);
+ map.put("lambda", 955);
+ map.put("mu", 956);
+ map.put("nu", 957);
+ map.put("xi", 958);
+ map.put("omicron", 959);
+ map.put("pi", 960);
+ map.put("rho", 961);
+ map.put("sigmaf", 962);
+ map.put("sigma", 963);
+ map.put("tau", 964);
+ map.put("upsilon", 965);
+ map.put("phi", 966);
+ map.put("chi", 967);
+ map.put("psi", 968);
+ map.put("omega", 969);
+ map.put("thetasym", 977);
+ map.put("upsih", 978);
+ map.put("piv", 982);
+ map.put("ensp", 8194);
+ map.put("emsp", 8195);
+ map.put("thinsp", 8201);
+ map.put("zwnj", 8204);
+ map.put("zwj", 8205);
+ map.put("lrm", 8206);
+ map.put("rlm", 8207);
+ map.put("ndash", 8211);
+ map.put("mdash", 8212);
+ map.put("lsquo", 8216);
+ map.put("rsquo", 8217);
+ map.put("sbquo", 8218);
+ map.put("ldquo", 8220);
+ map.put("rdquo", 8221);
+ map.put("bdquo", 8222);
+ map.put("dagger", 8224);
+ map.put("Dagger", 8225);
+ map.put("bull", 8226);
+ map.put("hellip", 8230);
+ map.put("permil", 8240);
+ map.put("prime", 8242);
+ map.put("Prime", 8243);
+ map.put("lsaquo", 8249);
+ map.put("rsaquo", 8250);
+ map.put("oline", 8254);
+ map.put("frasl", 8260);
+ map.put("euro", 8364);
+ map.put("image", 8465);
+ map.put("weierp", 8472);
+ map.put("real", 8476);
+ map.put("trade", 8482);
+ map.put("alefsym", 8501);
+ map.put("larr", 8592);
+ map.put("uarr", 8593);
+ map.put("rarr", 8594);
+ map.put("darr", 8595);
+ map.put("harr", 8596);
+ map.put("crarr", 8629);
+ map.put("lArr", 8656);
+ map.put("uArr", 8657);
+ map.put("rArr", 8658);
+ map.put("dArr", 8659);
+ map.put("hArr", 8660);
+ map.put("forall", 8704);
+ map.put("part", 8706);
+ map.put("exist", 8707);
+ map.put("empty", 8709);
+ map.put("nabla", 8711);
+ map.put("isin", 8712);
+ map.put("notin", 8713);
+ map.put("ni", 8715);
+ map.put("prod", 8719);
+ map.put("sum", 8721);
+ map.put("minus", 8722);
+ map.put("lowast", 8727);
+ map.put("radic", 8730);
+ map.put("prop", 8733);
+ map.put("infin", 8734);
+ map.put("ang", 8736);
+ map.put("and", 8743);
+ map.put("or", 8744);
+ map.put("cap", 8745);
+ map.put("cup", 8746);
+ map.put("int", 8747);
+ map.put("there4", 8756);
+ map.put("sim", 8764);
+ map.put("cong", 8773);
+ map.put("asymp", 8776);
+ map.put("ne", 8800);
+ map.put("equiv", 8801);
+ map.put("le", 8804);
+ map.put("ge", 8805);
+ map.put("sub", 8834);
+ map.put("sup", 8835);
+ map.put("nsub", 8836);
+ map.put("sube", 8838);
+ map.put("supe", 8839);
+ map.put("oplus", 8853);
+ map.put("otimes", 8855);
+ map.put("perp", 8869);
+ map.put("sdot", 8901);
+ map.put("lceil", 8968);
+ map.put("rceil", 8969);
+ map.put("lfloor", 8970);
+ map.put("rfloor", 8971);
+ map.put("lang", 10216);
+ map.put("rang", 10217);
+ map.put("loz", 9674);
+ map.put("spades", 9824);
+ map.put("clubs", 9827);
+ map.put("hearts", 9829);
+ map.put("diams", 9830);
+ SPECIALS = Collections.unmodifiableMap(map);
+ }
+ //
+
+ /**
+ * Private constructor for a utility class.
+ */
+ private XmlEntity() {
+ }
+
+ /**
+ * Converts a named XML entity into its HTML encoded Unicode code point.
+ *
+ * @param s the named entity (note, this should not include the leading '&'
+ * or trailing ';'
+ * @return the HTML encoded Unicode code point representation of the named
+ * entity
+ */
+ public static String fromNamedReference(CharSequence s) {
+ if (s == null) {
+ return null;
+ }
+ final Integer code = SPECIALS.get(s.toString());
+ if (code != null) {
+ return "" + code + ";";
+ }
+ return null;
+ }
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlInputStream.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlInputStream.java
new file mode 100644
index 000000000..2879c2baf
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlInputStream.java
@@ -0,0 +1,269 @@
+package org.owasp.dependencycheck.xml;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Cleans up often very bad XML. Primarily, this will convert named HTM entities
+ * into their HTM encoded Unicode code point representation.
+ *
+ *
+ *
Strips leading white space
+ *
Recodes £ etc to &#...;
+ *
Recodes lone & as &
+ *
+ *
+ * This is a slightly modified (class/method rename) from an SO answer:
+ * https://stackoverflow.com/questions/7286428/help-the-java-sax-parser-to-understand-bad-xml
+ *
+ * @author https://stackoverflow.com/users/823393/oldcurmudgeon
+ */
+public class XmlInputStream extends FilterInputStream {
+
+ /**
+ * The logger.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(XmlInputStream.class);
+ /**
+ * The minimum length of characters to read.
+ */
+ private static final int MIN_LENGTH = 2;
+ /**
+ * Holder for everything we've read.
+ */
+ private StringBuilder red = new StringBuilder();
+ /**
+ * Data that needs to be pushed back.
+ */
+ private StringBuilder pushBack = new StringBuilder();
+ /**
+ * How much we've given them.
+ */
+ private int given = 0;
+ /**
+ * How much we've read.
+ */
+ private int pulled = 0;
+
+ /**
+ * Constructs a new XML Input Stream.
+ *
+ * @param in the base input stream
+ */
+ public XmlInputStream(InputStream in) {
+ super(in);
+ }
+
+ /**
+ * NB: This is a Troll length (i.e. it goes 1, 2, many) so 2 actually means
+ * "at least 2"
+ *
+ * @return the length
+ */
+ public int length() {
+ try {
+ final StringBuilder s = read(MIN_LENGTH);
+ pushBack.append(s);
+ return s.length();
+ } catch (IOException ex) {
+ LOGGER.warn("Oops ", ex);
+ }
+ return 0;
+ }
+
+ /**
+ * Read n characters.
+ *
+ * @param n the number of characters to read
+ * @return the characters read
+ * @throws IOException thrown when an error occurs
+ */
+ private StringBuilder read(int n) throws IOException {
+ // Input stream finished?
+ boolean eof = false;
+ // Read that many.
+ final StringBuilder s = new StringBuilder(n);
+ while (s.length() < n && !eof) {
+ // Always get from the pushBack buffer.
+ if (pushBack.length() == 0) {
+ // Read something from the stream into pushBack.
+ eof = readIntoPushBack();
+ }
+
+ // Pushback only contains deliverable codes.
+ if (pushBack.length() > 0) {
+ // Grab one character
+ s.append(pushBack.charAt(0));
+ // Remove it from pushBack
+ pushBack.deleteCharAt(0);
+ }
+
+ }
+ return s;
+ }
+
+ /**
+ * Might not actually push back anything but usually will.
+ *
+ * @return true if at end-of-file
+ * @throws IOException thrown if there is an IO exception in the underlying
+ * steam
+ */
+ private boolean readIntoPushBack() throws IOException {
+ // File finished?
+ boolean eof = false;
+ // Next char.
+ final int ch = in.read();
+ if (ch >= 0) {
+ // Discard whitespace at start?
+ if (!(pulled == 0 && isWhiteSpace(ch))) {
+ // Good code.
+ pulled += 1;
+ // Parse out the &stuff;
+ if (ch == '&') {
+ // Process the &
+ readAmpersand();
+ } else {
+ // Not an '&', just append.
+ pushBack.append((char) ch);
+ }
+ }
+ } else {
+ // Hit end of file.
+ eof = true;
+ }
+ return eof;
+ }
+
+ /**
+ * Deal with an ampersand in the stream.
+ *
+ * @throws IOException thrown if an unknown entity is encountered
+ */
+ private void readAmpersand() throws IOException {
+ // Read the whole word, up to and including the ;
+ final StringBuilder reference = new StringBuilder();
+ int ch;
+ // Should end in a ';'
+ for (ch = in.read(); isAlphaNumeric(ch); ch = in.read()) {
+ reference.append((char) ch);
+ }
+ // Did we tidily finish?
+ if (ch == ';') {
+ // Yes! Translate it into a nnn; code.
+ final String code = XmlEntity.fromNamedReference(reference);
+ if (code != null) {
+ // Keep it.
+ pushBack.append(code);
+ } else {
+ throw new IOException("Invalid/Unknown reference '&" + reference + ";'");
+ }
+ } else {
+ // Did not terminate properly!
+ // Perhaps an & on its own or a malformed reference.
+ // Either way, escape the &
+ pushBack.append("&").append(reference).append((char) ch);
+ }
+ }
+
+ /**
+ * Keep track of what we've given them.
+ *
+ * @param s the sequence of characters given
+ * @param wanted the number of characters wanted
+ * @param got the number of characters given
+ */
+ private void given(CharSequence s, int wanted, int got) {
+ red.append(s);
+ given += got;
+ LOGGER.trace("Given: [" + wanted + "," + got + "]-" + s);
+ }
+
+ /**
+ * Reads the next byte.
+ *
+ * @return the byte read
+ * @throws IOException thrown when there is an problem reading
+ */
+ @Override
+ public int read() throws IOException {
+ final StringBuilder s = read(1);
+ given(s, 1, 1);
+ return s.length() > 0 ? s.charAt(0) : -1;
+ }
+
+ /**
+ * Reads the next length of bytes from the stream into the given byte array
+ * at the given offset.
+ *
+ * @param data the buffer to store the data read
+ * @param offset the offset in the buffer to start writing
+ * @param length the length of data to read
+ * @return the number of bytes read
+ * @throws IOException thrown when there is an issue with the underlying
+ * stream
+ */
+ @Override
+ public int read(byte[] data, int offset, int length) throws IOException {
+ final StringBuilder s = read(length);
+ int n = 0;
+ for (int i = 0; i < Math.min(length, s.length()); i++) {
+ data[offset + i] = (byte) s.charAt(i);
+ n += 1;
+ }
+ given(s, length, n);
+ return n > 0 ? n : -1;
+ }
+
+ /**
+ * To string implementation.
+ *
+ * @return a string representation of the data given and read from the
+ * stream.
+ */
+ @Override
+ public String toString() {
+ final String s = red.toString();
+ final StringBuilder h = new StringBuilder();
+ // Hex dump the small ones.
+ if (s.length() < 8) {
+ for (int i = 0; i < s.length(); i++) {
+ h.append(" ").append(Integer.toHexString(s.charAt(i)));
+ }
+ }
+ return "[" + given + "]-\"" + s + "\"" + (h.length() > 0 ? " (" + h.toString() + ")" : "");
+ }
+
+ /**
+ * Determines if the character is whitespace.
+ *
+ * @param ch the character to check
+ * @return true if the character is whitespace; otherwise false
+ */
+ private boolean isWhiteSpace(int ch) {
+ switch (ch) {
+ case ' ':
+ case '\r':
+ case '\n':
+ case '\t':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Checks if the given character is alpha-numeric.
+ *
+ * @param ch the character to check
+ * @return true if the character is alpha-numeric; otherwise false.
+ */
+ private boolean isAlphaNumeric(int ch) {
+ return ('a' <= ch && ch <= 'z')
+ || ('A' <= ch && ch <= 'Z')
+ || ('0' <= ch && ch <= '9');
+ }
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java
index 8de5bcb2e..155b0048a 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java
@@ -29,6 +29,7 @@ import javax.xml.parsers.SAXParser;
import org.apache.commons.io.ByteOrderMark;
import org.apache.commons.io.input.BOMInputStream;
import org.owasp.dependencycheck.utils.XmlUtils;
+import org.owasp.dependencycheck.xml.XmlInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -80,7 +81,8 @@ public class PomParser {
final SAXParser saxParser = XmlUtils.buildSecureSaxParser();
final XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setContentHandler(handler);
- final BOMInputStream bomStream = new BOMInputStream(inputStream);
+
+ final BOMInputStream bomStream = new BOMInputStream(new XmlInputStream(inputStream));
final ByteOrderMark bom = bomStream.getBOM();
final String defaultEncoding = "UTF-8";
final String charsetName = bom == null ? defaultEncoding : bom.getCharsetName();
diff --git a/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml b/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml
index a4d0c1d32..e210335ca 100644
--- a/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml
+++ b/dependency-check-core/src/main/resources/dependencycheck-base-suppression.xml
@@ -1,19 +1,19 @@
-
- .*Microsoft\.VisualStudio\.QualityTools\.UnitTestFramework*\.dll
- CVE-2014-3802
+ .*Microsoft\.VisualStudio\.QualityTools\.UnitTestFramework*\.dll
+ CVE-2014-3802
-
- .*EntityFramework\.SqlServer*\.dll
- cpe:/a:microsoft:server:6.0.0.0
- cpe:/a:microsoft:sql_server:6.0
+ .*EntityFramework\.SqlServer*\.dll
+ cpe:/a:microsoft:server:6.0.0.0
+ cpe:/a:microsoft:sql_server:6.0^com\.splunk:splunk:.*$cpe:/a:splunk:splunk
-
-
+
+ ^org\.openid4java:openid4java:.*$cpe:/a:openid:openidcpe:/a:openid:openid4java
-
-
+
+ ^org\.springframework\.cloud:spring-cloud-netflix-core:.*$cpe:/a:pivotal:spring_frameworkcpe:/a:pivotal_software:spring_framework
-
-
+
+
@@ -607,5 +607,20 @@
cpe:/a:pivotal:spring_frameworkcpe:/a:pivotal_software:spring_frameworkcpe:/a:context_project:context
-
+
+
+
+ ^com\.artofsolving:jodconverter:.*$
+ cpe:/a:openoffice:openoffice.org
+ cpe:/a:openoffice:openoffice
+
+
+
+ ^org\.xerial:sqlite-jdbc:.*$
+ CVE-2015-3717
+
diff --git a/dependency-check-core/src/main/resources/templates/CsvReport.vsl b/dependency-check-core/src/main/resources/templates/csvReport.vsl
similarity index 100%
rename from dependency-check-core/src/main/resources/templates/CsvReport.vsl
rename to dependency-check-core/src/main/resources/templates/csvReport.vsl
diff --git a/dependency-check-core/src/main/resources/templates/HtmlReport.vsl b/dependency-check-core/src/main/resources/templates/htmlReport.vsl
similarity index 100%
rename from dependency-check-core/src/main/resources/templates/HtmlReport.vsl
rename to dependency-check-core/src/main/resources/templates/htmlReport.vsl
diff --git a/dependency-check-core/src/main/resources/templates/JsonReport.vsl b/dependency-check-core/src/main/resources/templates/jsonReport.vsl
similarity index 100%
rename from dependency-check-core/src/main/resources/templates/JsonReport.vsl
rename to dependency-check-core/src/main/resources/templates/jsonReport.vsl
diff --git a/dependency-check-core/src/main/resources/templates/VulnerabilityReport.vsl b/dependency-check-core/src/main/resources/templates/vulnReport.vsl
similarity index 100%
rename from dependency-check-core/src/main/resources/templates/VulnerabilityReport.vsl
rename to dependency-check-core/src/main/resources/templates/vulnReport.vsl
diff --git a/dependency-check-core/src/main/resources/templates/XmlReport.vsl b/dependency-check-core/src/main/resources/templates/xmlReport.vsl
similarity index 100%
rename from dependency-check-core/src/main/resources/templates/XmlReport.vsl
rename to dependency-check-core/src/main/resources/templates/xmlReport.vsl
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java
index 1df3dc7cf..ba2877e19 100644
--- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java
@@ -17,6 +17,7 @@
*/
package org.owasp.dependencycheck;
+import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
@@ -79,12 +80,7 @@ public class EngineIT extends BaseDBTestCase {
}
}
}
- DatabaseProperties prop = null;
- try (CveDB cve = CveDB.getInstance()) {
- prop = cve.getDatabaseProperties();
- }
- ReportGenerator rg = new ReportGenerator("DependencyCheck", instance.getDependencies(), instance.getAnalyzers(), prop);
- rg.generateReports("./target/", "ALL");
+ instance.writeReports("dependency-check sample", new File("./target/"), "ALL");
instance.cleanup();
}
}
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIT.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIT.java
index e472c1e63..c0392df31 100644
--- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIT.java
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIT.java
@@ -25,15 +25,12 @@ import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
-import static org.junit.Assert.fail;
import org.junit.Test;
import org.owasp.dependencycheck.BaseDBTestCase;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;
-import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
-import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.exception.ReportException;
import org.owasp.dependencycheck.utils.InvalidSettingException;
@@ -47,67 +44,6 @@ import static org.junit.Assert.fail;
*/
public class ReportGeneratorIT extends BaseDBTestCase {
- /**
- * Test of generateReport method, of class ReportGenerator.
- *
- * @throws Exception is thrown when an exception occurs.
- */
- @Test
- public void testGenerateReport() throws Exception {
-// String templateName = "HtmlReport";
-// File f = new File("target/test-reports");
-// if (!f.exists()) {
-// f.mkdir();
-// }
-// String writeTo = "target/test-reports/Report.html";
-// Map properties = new HashMap();
-// Dependency d = new Dependency();
-// d.setFileName("FileName.jar");
-// d.setActualFilePath("lib/FileName.jar");
-// d.addCPEentry("cpe://a:/some:cpe:1.0");
-//
-// List dependencies = new ArrayList();
-// d.getProductEvidence().addEvidence("jar","filename","test", Confidence.HIGH);
-// d.getProductEvidence().addEvidence("manifest","vendor","test", Confidence.HIGH);
-//
-// for (Evidence e : d.getProductEvidence().iterator(Confidence.HIGH)) {
-// String t = e.getValue();
-// }
-// dependencies.add(d);
-//
-// Dependency d2 = new Dependency();
-// d2.setFileName("Another.jar");
-// d2.setActualFilePath("lib/Another.jar");
-// d2.addCPEentry("cpe://a:/another:cpe:1.0");
-// d2.addCPEentry("cpe://a:/another:cpe:1.1");
-// d2.addCPEentry("cpe://a:/another:cpe:1.2");
-// d2.getProductEvidence().addEvidence("jar","filename","another.jar", Confidence.HIGH);
-// d2.getProductEvidence().addEvidence("manifest","vendor","Company A", Confidence.MEDIUM);
-//
-// for (Evidence e : d2.getProductEvidence().iterator(Confidence.HIGH)) {
-// String t = e.getValue();
-// }
-//
-// dependencies.add(d2);
-//
-// Dependency d3 = new Dependency();
-// d3.setFileName("Third.jar");
-// d3.setActualFilePath("lib/Third.jar");
-// d3.getProductEvidence().addEvidence("jar","filename","third.jar", Confidence.HIGH);
-//
-// for (Evidence e : d3.getProductEvidence().iterator(Confidence.HIGH)) {
-// String t = e.getValue();
-// }
-//
-// dependencies.add(d3);
-//
-// properties.put("dependencies",dependencies);
-//
-// ReportGenerator instance = new ReportGenerator();
-// instance.generateReport(templateName, writeTo, properties);
- //assertTrue("need to add a real check here", false);
- }
-
/**
* Generates an XML report containing known vulnerabilities and realistic
* data and validates the generated XML document against the XSD.
@@ -115,7 +51,7 @@ public class ReportGeneratorIT extends BaseDBTestCase {
* @throws Exception
*/
@Test
- public void testGenerateXMLReport() {
+ public void testGenerateReport() {
try {
String templateName = "XmlReport";
@@ -123,7 +59,7 @@ public class ReportGeneratorIT extends BaseDBTestCase {
if (!f.exists()) {
f.mkdir();
}
- String writeTo = "target/test-reports/Report.xml";
+ File writeTo = new File("target/test-reports/Report.xml");
File suppressionFile = BaseTest.getResourceAsFile(this, "incorrectSuppressions.xml");
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile.getAbsolutePath());
@@ -135,29 +71,20 @@ public class ReportGeneratorIT extends BaseDBTestCase {
//File jetty = new File(this.getClass().getClassLoader().getResource("org.mortbay.jetty.jar").getPath());
File jetty = BaseTest.getResourceAsFile(this, "org.mortbay.jetty.jar");
- boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
Engine engine = new Engine();
- Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
engine.scan(struts);
engine.scan(axis);
engine.scan(jetty);
engine.analyzeDependencies();
-
- CveDB cveDB = CveDB.getInstance();
- DatabaseProperties dbProp = cveDB.getDatabaseProperties();
-
- ReportGenerator generator = new ReportGenerator("Test Report", "org.owasp", "dependency-check-core", "1.4.7",
- engine.getDependencies(), engine.getAnalyzers(), dbProp);
- generator.generateReport(templateName, writeTo);
- cveDB.close();
+ engine.writeReports("Test Report", "org.owasp", "dependency-check-core", "1.4.7", writeTo, "XML");
engine.cleanup();
InputStream xsdStream = ReportGenerator.class.getClassLoader().getResourceAsStream("schema/dependency-check.1.5.xsd");
StreamSource xsdSource = new StreamSource(xsdStream);
- StreamSource xmlSource = new StreamSource(new File(writeTo));
+ StreamSource xmlSource = new StreamSource(writeTo);
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(xsdSource);
Validator validator = schema.newValidator();
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/XmlEntityTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/XmlEntityTest.java
new file mode 100644
index 000000000..6d143ddd8
--- /dev/null
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/XmlEntityTest.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (c) 2017 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.xml;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Jeremy Long
+ */
+public class XmlEntityTest {
+
+ /**
+ * Test of fromNamedReference method, of class XmlEntity.
+ */
+ @Test
+ public void testFromNamedReference() {
+ CharSequence s = null;
+ String expResult = null;
+ String result = XmlEntity.fromNamedReference(s);
+ assertEquals(expResult, result);
+
+ s = "somethingWrong";
+ expResult = null;
+ result = XmlEntity.fromNamedReference(s);
+ assertEquals(expResult, result);
+
+ s = "amp";
+ expResult = "&";
+ result = XmlEntity.fromNamedReference(s);
+ assertEquals(expResult, result);
+
+ s = "acute";
+ expResult = "´";
+ result = XmlEntity.fromNamedReference(s);
+ assertEquals(expResult, result);
+ }
+
+}
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/XmlInputStreamTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/XmlInputStreamTest.java
new file mode 100644
index 000000000..f2382f7ab
--- /dev/null
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/XmlInputStreamTest.java
@@ -0,0 +1,135 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (c) 2017 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.xml;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author jerem
+ */
+public class XmlInputStreamTest {
+
+ /**
+ * Test of length method, of class XmlInputStream.
+ */
+ @Test
+ public void testLength() {
+ String data = "";
+ InputStream stream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
+ XmlInputStream instance = new XmlInputStream(stream);
+ int expResult = 0;
+ int result = instance.length();
+ assertEquals(expResult, result);
+
+ data = "Input data";
+ stream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
+ instance = new XmlInputStream(stream);
+ result = instance.length();
+ assertTrue(result > 0);
+ }
+
+ /**
+ * Test of read method, of class XmlInputStream.
+ */
+ @Test
+ public void testRead_0args() throws Exception {
+ String data = "";
+ InputStream stream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
+ XmlInputStream instance = new XmlInputStream(stream);
+ int expResult = -1;
+ int result = instance.read();
+ assertEquals(expResult, result);
+
+ data = "*";
+ stream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
+ instance = new XmlInputStream(stream);
+ expResult = 42;
+ result = instance.read();
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of read method, of class XmlInputStream.
+ */
+ @Test
+ public void testRead_3args() throws Exception {
+ byte[] data = new byte[10];
+ int offset = 0;
+ int length = 10;
+ byte[] expected = "abcdefghij".getBytes(StandardCharsets.UTF_8);
+ String text = "abcdefghijklmnopqrstuvwxyz";
+ InputStream stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ XmlInputStream instance = new XmlInputStream(stream);
+ int expResult = 10;
+ int result = instance.read(data, offset, length);
+ assertEquals(expResult, result);
+ assertArrayEquals(expected, data);
+
+
+ data = new byte[5];
+ offset = 0;
+ length = 5;
+ expected = "&".getBytes(StandardCharsets.UTF_8);
+ text = "&";
+ stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ instance = new XmlInputStream(stream);
+ expResult = 5;
+ result = instance.read(data, offset, length);
+ assertEquals(expResult, result);
+ assertArrayEquals(expected, data);
+
+ data = new byte[10];
+ offset = 0;
+ length = 10;
+ expected = "& test".getBytes(StandardCharsets.UTF_8);
+ text = "& test";
+ stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ instance = new XmlInputStream(stream);
+ expResult = 10;
+ result = instance.read(data, offset, length);
+ assertEquals(expResult, result);
+ assertArrayEquals(expected, data);
+ }
+
+ /**
+ * Test of toString method, of class XmlInputStream.
+ */
+ @Test
+ public void testToString() throws IOException {
+ String data = "test";
+ InputStream stream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
+ XmlInputStream instance = new XmlInputStream(stream);
+ int r = instance.read();
+ assertEquals('t', r);
+ String expResult = "[1]-\"t\" ( 74)";
+ String result = instance.toString();
+ assertEquals(expResult, result);
+ r = instance.read();
+ assertEquals('e', r);
+ expResult = "[2]-\"te\" ( 74 65)";
+ result = instance.toString();
+ assertEquals(expResult, result);
+
+ }
+}
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/pom/PomUtilsTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/pom/PomUtilsTest.java
index 3b5c285bf..879e1217f 100644
--- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/pom/PomUtilsTest.java
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/pom/PomUtilsTest.java
@@ -49,7 +49,7 @@ public class PomUtilsTest extends BaseTest {
assertEquals(expResult, result.getOrganizationUrl());
file = BaseTest.getResourceAsFile(this, "jmockit-1.26.pom");
- expResult = "Main";
+ expResult = "Main ΓΈ modified to test issue #710";
result = PomUtils.readPom(file);
assertEquals(expResult, result.getName());
}
diff --git a/dependency-check-core/src/test/resources/jmockit-1.26.pom b/dependency-check-core/src/test/resources/jmockit-1.26.pom
index 590d69b63..3faac78be 100644
--- a/dependency-check-core/src/test/resources/jmockit-1.26.pom
+++ b/dependency-check-core/src/test/resources/jmockit-1.26.pom
@@ -7,7 +7,7 @@
org.jmockitjmockit1.26jar
- Main
+ Main ø modified to test issue #710
JMockit is a Java toolkit for automated developer testing.
It contains mocking and faking APIs and a code coverage tool, supporting both JUnit and TestNG.
diff --git a/dependency-check-maven/pom.xml b/dependency-check-maven/pom.xml
index 8f03b9bb0..edb89aa63 100644
--- a/dependency-check-maven/pom.xml
+++ b/dependency-check-maven/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 1.4.6-SNAPSHOT
+ 2.0.0-SNAPSHOTdependency-check-mavenmaven-plugin
diff --git a/dependency-check-maven/src/it/710-pom-parse-error/invoker.properties b/dependency-check-maven/src/it/710-pom-parse-error/invoker.properties
new file mode 100644
index 000000000..693fb2637
--- /dev/null
+++ b/dependency-check-maven/src/it/710-pom-parse-error/invoker.properties
@@ -0,0 +1,19 @@
+#
+# This file is part of dependency-check-maven.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Copyright (c) 2014 Jeremy Long. All Rights Reserved.
+#
+
+invoker.goals = install ${project.groupId}:${project.artifactId}:${project.version}:check -X -Dformat=ALL
diff --git a/dependency-check-maven/src/it/710-pom-parse-error/pom.xml b/dependency-check-maven/src/it/710-pom-parse-error/pom.xml
new file mode 100644
index 000000000..0adbf19b9
--- /dev/null
+++ b/dependency-check-maven/src/it/710-pom-parse-error/pom.xml
@@ -0,0 +1,32 @@
+
+
+
+ 4.0.0
+ org.owasp.test
+ pom-parse-error
+ 1.0.0-SNAPSHOT
+ jar
+
+
+ qdox
+ qdox
+ 1.6.1
+
+
+
\ No newline at end of file
diff --git a/dependency-check-maven/src/it/710-pom-parse-error/postbuild.groovy b/dependency-check-maven/src/it/710-pom-parse-error/postbuild.groovy
new file mode 100644
index 000000000..9ec3a0a91
--- /dev/null
+++ b/dependency-check-maven/src/it/710-pom-parse-error/postbuild.groovy
@@ -0,0 +1,17 @@
+/*
+ * This file is part of dependency-check-maven.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (c) 2017 Jeremy Long. All Rights Reserved.
+ */
diff --git a/dependency-check-maven/src/it/710-pom-parse-error/prebuild.groovy b/dependency-check-maven/src/it/710-pom-parse-error/prebuild.groovy
new file mode 100644
index 000000000..9eff4bb5c
--- /dev/null
+++ b/dependency-check-maven/src/it/710-pom-parse-error/prebuild.groovy
@@ -0,0 +1,17 @@
+/*
+ * This file is part of dependency-check-maven.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (c) 2014 Jeremy Long. All Rights Reserved.
+ */
diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java
index 62c333efe..7a0c0b6d5 100644
--- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java
+++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java
@@ -123,7 +123,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
outputDir = new File(this.getProject().getBuild().getDirectory());
}
try {
- writeReports(engine, this.getProject(), outputDir);
+ final MavenProject p = this.getProject();
+ engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), outputDir, getFormat());
} catch (ReportException ex) {
if (exCol == null) {
exCol = new ExceptionCollection("Error writing aggregate report", ex);
diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
index 99b3a401f..e7cf5f937 100644
--- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
+++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java
@@ -1069,35 +1069,6 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
return format;
}
- /**
- * Generates the reports for a given dependency-check engine.
- *
- * @param engine a dependency-check engine
- * @param p the Maven project
- * @param outputDir the directory path to write the report(s)
- * @throws ReportException thrown if there is an error writing the report
- */
- protected void writeReports(Engine engine, MavenProject p, File outputDir) throws ReportException {
- DatabaseProperties prop = null;
- try (CveDB cve = CveDB.getInstance()) {
- prop = cve.getDatabaseProperties();
- } catch (DatabaseException ex) {
- //TODO shouldn't this throw an exception?
- if (getLog().isDebugEnabled()) {
- getLog().debug("Unable to retrieve DB Properties", ex);
- }
- }
- final ReportGenerator r = new ReportGenerator(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(),
- engine.getDependencies(), engine.getAnalyzers(), prop);
- try {
- r.generateReports(outputDir.getAbsolutePath(), format);
- } catch (ReportException ex) {
- final String msg = String.format("Error generating the report for %s", p.getName());
- throw new ReportException(msg, ex);
- }
-
- }
-
//
/**
* Checks to see if a vulnerability has been identified with a CVSS score
diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java
index cb95628db..1b6a30d55 100644
--- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java
+++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java
@@ -25,6 +25,7 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.exception.ExceptionCollection;
@@ -99,19 +100,19 @@ public class CheckMojo extends BaseDependencyCheckMojo {
ExceptionCollection exCol = scanArtifacts(getProject(), engine);
if (engine.getDependencies().isEmpty()) {
getLog().info("No dependencies were identified that could be analyzed by dependency-check");
- } else {
- try {
- engine.analyzeDependencies();
- } catch (ExceptionCollection ex) {
- if (this.isFailOnError() && ex.isFatal()) {
- throw new MojoExecutionException("One or more exceptions occurred during analysis", ex);
- }
- exCol = ex;
+ }
+ try {
+ engine.analyzeDependencies();
+ } catch (ExceptionCollection ex) {
+ if (this.isFailOnError() && ex.isFatal()) {
+ throw new MojoExecutionException("One or more exceptions occurred during analysis", ex);
}
+ exCol = ex;
}
if (exCol == null || !exCol.isFatal()) {
try {
- writeReports(engine, getProject(), getCorrectOutputDirectory());
+ final MavenProject p = this.getProject();
+ engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), getCorrectOutputDirectory(), getFormat());
} catch (ReportException ex) {
if (this.isFailOnError()) {
if (exCol != null) {
diff --git a/dependency-check-plugin/pom.xml b/dependency-check-plugin/pom.xml
index 0cccc8d97..b53f42ae4 100644
--- a/dependency-check-plugin/pom.xml
+++ b/dependency-check-plugin/pom.xml
@@ -21,7 +21,7 @@ Copyright (c) 2017 Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 1.4.6-SNAPSHOT
+ 2.0.0-SNAPSHOTorg.owaspdependency-check-plugin
diff --git a/dependency-check-utils/pom.xml b/dependency-check-utils/pom.xml
index 035222a77..bc6577a0b 100644
--- a/dependency-check-utils/pom.xml
+++ b/dependency-check-utils/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 1.4.6-SNAPSHOT
+ 2.0.0-SNAPSHOTdependency-check-utils
diff --git a/pom.xml b/pom.xml
index 370e4c9fd..c76264c30 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long
org.owaspdependency-check-parent
- 1.4.6-SNAPSHOT
+ 2.0.0-SNAPSHOTpom
@@ -288,7 +288,7 @@ Copyright (c) 2012 - Jeremy Long
prepare-agent
-
+ ${project.build.directory}/coverage-reports/jacoco-ut.execsurefireArgLine
@@ -299,12 +299,31 @@ Copyright (c) 2012 - Jeremy Long
prepare-agent
-
+ ${project.build.directory}/coverage-reports/jacoco-it.execfailsafeArgLine
+
+ org.codehaus.gmaven
+ gmaven-plugin
+ 1.5
+
+
+ add-dynamic-properties
+ pre-integration-test
+
+ execute
+
+
+
+ project.properties['invoker.mavenOpts']=project.properties.failsafeArgLine
+
+
+
+
+ org.apache.maven.pluginsmaven-surefire-plugin
@@ -459,7 +478,7 @@ Copyright (c) 2012 - Jeremy Long
org.codehaus.mojo.signature
- java16
+ java171.1
@@ -578,6 +597,10 @@ Copyright (c) 2012 - Jeremy Long
jacoco-maven-plugin0.7.9
+
+ target/coverage-reports/jacoco-ut.exec
+ target/coverage-reports/jacoco-it.exec
+
diff --git a/src/main/config/checkstyle-suppressions.xml b/src/main/config/checkstyle-suppressions.xml
index 56ec1750f..46acbbaf7 100644
--- a/src/main/config/checkstyle-suppressions.xml
+++ b/src/main/config/checkstyle-suppressions.xml
@@ -12,4 +12,6 @@
+
+
\ No newline at end of file
diff --git a/src/site/markdown/data/database.md.vm b/src/site/markdown/data/database.md.vm
index b5a6b514d..018a90284 100644
--- a/src/site/markdown/data/database.md.vm
+++ b/src/site/markdown/data/database.md.vm
@@ -20,8 +20,8 @@ To setup a centralized database the following generalized steps can be used:
Create the database and tables using either initialize.sql
or one of the other initialization scripts found here.
The account that the clients will connect using must have select granted on the tables.
-
Note, if the clients performing the scans should run with the noupdate setting. A single
- instance of the dependency-check client should be setup with update enabled and the account
+
Note, the clients performing the scans should run with the noupdate setting. A single
+ instance of the dependency-check client should be setup with updates enabled and the account
used during the update process will need to be granted update rights on the tables.
Dependency-check clients running scans will need to be configured to use the central database: