changes to support Ant style paths to resolve issue #153

Former-commit-id: b1666d6652891c4b012457fd5de7f8230938fb45
This commit is contained in:
Jeremy Long
2014-11-05 06:20:15 -05:00
parent f8c913a3e8
commit da77727673
2 changed files with 97 additions and 17 deletions

View File

@@ -21,7 +21,11 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.apache.commons.cli.ParseException; import org.apache.commons.cli.ParseException;
@@ -29,6 +33,7 @@ import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException; import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.org.apache.tools.ant.DirectoryScanner;
import org.owasp.dependencycheck.reporting.ReportGenerator; import org.owasp.dependencycheck.reporting.ReportGenerator;
import org.owasp.dependencycheck.utils.LogUtils; import org.owasp.dependencycheck.utils.LogUtils;
import org.owasp.dependencycheck.utils.Settings; import org.owasp.dependencycheck.utils.Settings;
@@ -92,7 +97,11 @@ public class App {
cli.printVersionInfo(); cli.printVersionInfo();
} else if (cli.isRunScan()) { } else if (cli.isRunScan()) {
populateSettings(cli); populateSettings(cli);
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles()); try {
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles(), cli.getExcludeList());
} catch (InvalidScanPathException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, "An invalid scan path was detected; unable to scan '//*' paths");
}
} else { } else {
cli.printHelp(); cli.printHelp();
} }
@@ -105,18 +114,69 @@ public class App {
* @param outputFormat the output format of the report * @param outputFormat the output format of the report
* @param applicationName the application name for the report * @param applicationName the application name for the report
* @param files the files/directories to scan * @param files the files/directories to scan
* @param files the patterns for files/directories to exclude
*/ */
private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files) { private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
Engine scanner = null; String[] excludes) throws InvalidScanPathException {
Engine engine = null;
try { try {
scanner = new Engine(); engine = new Engine();
List<String> antStylePaths = new ArrayList<String>();
for (String file : files) { if (excludes == null || excludes.length == 0) {
scanner.scan(file); for (String file : files) {
if (file.contains("*") || file.contains("?")) {
antStylePaths.add(file);
} else {
engine.scan(file);
}
}
} else {
antStylePaths = Arrays.asList(files);
} }
scanner.analyzeDependencies(); Set<File> paths = new HashSet<File>();
final List<Dependency> dependencies = scanner.getDependencies(); for (String file : antStylePaths) {
DirectoryScanner scanner = new DirectoryScanner();
String include = file.replace('\\', '/');
File baseDir;
if (include.startsWith("//")) {
throw new InvalidScanPathException("Unable to scan paths specified by //");
} else if (include.startsWith("./")) {
baseDir = new File(".");
include = include.substring(2);
} else if (include.startsWith("/")) {
baseDir = new File("/");
include = include.substring(1);
} else if (include.contains("/")) {
final int pos = include.indexOf('/');
String tmp = include.substring(0, pos);
if (tmp.contains("*") || tmp.contains("?")) {
baseDir = new File(".");
} else {
baseDir = new File(tmp);
include = include.substring(pos + 1);
}
} else { //no path info - must just be a file in the working directory
baseDir = new File(".");
}
scanner.setBasedir(baseDir);
scanner.setIncludes(include);
if (excludes != null && excludes.length > 0) {
scanner.addExcludes(excludes);
}
scanner.scan();
if (scanner.getIncludedFilesCount() > 0) {
for (String s : scanner.getIncludedFiles()) {
File f = new File(baseDir, s);
paths.add(f);
}
}
}
engine.scan(paths);
engine.analyzeDependencies();
final List<Dependency> dependencies = engine.getDependencies();
DatabaseProperties prop = null; DatabaseProperties prop = null;
CveDB cve = null; CveDB cve = null;
try { try {
@@ -130,7 +190,7 @@ public class App {
cve.close(); cve.close();
} }
} }
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop); final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
try { try {
report.generateReports(reportDirectory, outputFormat); report.generateReports(reportDirectory, outputFormat);
} catch (IOException ex) { } catch (IOException ex) {
@@ -144,8 +204,8 @@ public class App {
LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped"); LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.log(Level.FINE, "", ex); LOGGER.log(Level.FINE, "", ex);
} finally { } finally {
if (scanner != null) { if (engine != null) {
scanner.cleanup(); engine.cleanup();
} }
} }
} }

View File

@@ -134,7 +134,7 @@ public final class CliParser {
* @throws FileNotFoundException is thrown if the path being validated does not exist. * @throws FileNotFoundException is thrown if the path being validated does not exist.
*/ */
private void validatePathExists(String path, String argumentName) throws FileNotFoundException { private void validatePathExists(String path, String argumentName) throws FileNotFoundException {
if (!path.contains("*.")) { if (!path.contains("*") && !path.contains("?")) {
final File f = new File(path); final File f = new File(path);
if (!f.exists()) { if (!f.exists()) {
isValid = false; isValid = false;
@@ -151,7 +151,6 @@ public final class CliParser {
*/ */
@SuppressWarnings("static-access") @SuppressWarnings("static-access")
private Options createCommandLineOptions() { private Options createCommandLineOptions() {
final Options options = new Options(); final Options options = new Options();
addStandardOptions(options); addStandardOptions(options);
addAdvancedOptions(options); addAdvancedOptions(options);
@@ -184,10 +183,15 @@ public final class CliParser {
.create(ARGUMENT.APP_NAME_SHORT); .create(ARGUMENT.APP_NAME_SHORT);
final Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.SCAN) final Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.SCAN)
.withDescription("The path to scan - this option can be specified multiple times. To limit the scan" .withDescription("The path to scan - this option can be specified multiple times. Ant style"
+ " to specific file types *.[ext] can be added to the end of the path.") + " paths are supported (e.g. path/**/*.jar).")
.create(ARGUMENT.SCAN_SHORT); .create(ARGUMENT.SCAN_SHORT);
final Option excludes = OptionBuilder.withArgName("pattern").hasArg().withLongOpt(ARGUMENT.EXCLUDE)
.withDescription("Specify and exclusion pattern. This option can be specified multiple times"
+ " and it accepts Ant style excludsions.")
.create();
final Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.PROP) final Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.PROP)
.withDescription("A property file to load.") .withDescription("A property file to load.")
.create(ARGUMENT.PROP_SHORT); .create(ARGUMENT.PROP_SHORT);
@@ -212,7 +216,11 @@ public final class CliParser {
final OptionGroup og = new OptionGroup(); final OptionGroup og = new OptionGroup();
og.addOption(path); og.addOption(path);
final OptionGroup exog = new OptionGroup();
exog.addOption(excludes);
options.addOptionGroup(og) options.addOptionGroup(og)
.addOptionGroup(exog)
.addOption(out) .addOption(out)
.addOption(outputFormat) .addOption(outputFormat)
.addOption(appName) .addOption(appName)
@@ -479,7 +487,6 @@ public final class CliParser {
options, options,
"", "",
true); true);
} }
/** /**
@@ -491,6 +498,15 @@ public final class CliParser {
return line.getOptionValues(ARGUMENT.SCAN); return line.getOptionValues(ARGUMENT.SCAN);
} }
/**
* Retrieves the list of excluded file patterns specified by the 'exclude' argument.
*
* @return the excluded file patterns
*/
public String[] getExcludeList() {
return line.getOptionValues(ARGUMENT.EXCLUDE);
}
/** /**
* Returns the directory to write the reports to specified on the command line. * Returns the directory to write the reports to specified on the command line.
* *
@@ -877,5 +893,9 @@ public final class CliParser {
* The CLI argument name for setting extra extensions. * The CLI argument name for setting extra extensions.
*/ */
public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions"; public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
/**
* Exclude path argument
*/
public static final String EXCLUDE = "exclude";
} }
} }