change in namespace as this is now an OWASP project

Former-commit-id: 162fbfc156a284f1597d230f65eaf29dc0f3e0fb
This commit is contained in:
Jeremy Long
2013-03-03 08:57:38 -05:00
parent 3bd9caf113
commit 8b8707c36e
141 changed files with 2729 additions and 2330 deletions

View File

@@ -0,0 +1,107 @@
package org.owasp.dependencycheck.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Includes methods to generate the MD5 and SHA1 checksum.
*
* This code was copied from Real's How To. It has been slightly modified.
*
* Written and compiled by Réal Gagnon ©1998-2012
*
* @author Real's How To: http://www.rgagnon.com/javadetails/java-0416.html
*
*/
public class Checksum {
/**
* <p>Creates the cryptographic checksum of a given file using the specified
* algorithm.</p> <p>This algorithm was copied and heavily modified from
* Real's How To: http://www.rgagnon.com/javadetails/java-0416.html</p>
*
* @param algorithm the algorithm to use to calculate the checksum
* @param file the file to calculate the checksum for
* @return the checksum
* @throws IOException when the file does not exist
* @throws NoSuchAlgorithmException when an algorithm is specified that does
* not exist
*/
public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
InputStream fis = null;
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance(algorithm);
int numRead;
try {
fis = new FileInputStream(file);
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
Logger.getLogger(Checksum.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
return complete.digest();
}
/**
* Calculates the MD5 checksum of a specified file.
*
* @param file the file to generate the MD5 checksum
* @return the hex representation of the MD5 hash
* @throws IOException when the file passed in does not exist
* @throws NoSuchAlgorithmException when the MD5 algorithm is not available
*/
public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException {
byte[] b = getChecksum("MD5", file);
return getHex(b);
}
/**
* Calculates the SHA1 checksum of a specified file.
*
* @param file the file to generate the MD5 checksum
* @return the hex representation of the SHA1 hash
* @throws IOException when the file passed in does not exist
* @throws NoSuchAlgorithmException when the SHA1 algorithm is not available
*/
public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException {
byte[] b = getChecksum("SHA1", file);
return getHex(b);
}
private static final String HEXES = "0123456789ABCDEF";
/**
* <p>Converts a byte array into a hex string.</p>
*
* <p>This method was copied from <a
* href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p>
*
* @param raw a byte array
* @return the hex representation of the byte array
*/
public static String getHex(byte[] raw) {
if (raw == null) {
return null;
}
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
}

View File

@@ -0,0 +1,415 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.File;
import java.io.FileNotFoundException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
/**
* A utility to parse command line arguments for the DependencyCheck.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public final class CliParser {
/**
* The command line.
*/
private CommandLine line = null;
/**
* The options for the command line parser.
*/
private Options options = createCommandLineOptions();
/**
* indicates whether the arguments are valid.
*/
boolean isValid = true;
/**
* Parses the arguments passed in and captures the results for later use.
*
* @param args the command line arguments
* @throws FileNotFoundException is thrown when a 'file' argument does not
* point to a file that exists.
* @throws ParseException is thrown when a Parse Exception occurs.
*/
public void parse(String[] args) throws FileNotFoundException, ParseException {
line = parseArgs(args);
if (line != null) {
validateArgs();
}
}
/**
* Parses the command line arguments.
*
* @param args the command line arguments
* @return the results of parsing the command line arguments
* @throws ParseException if the arguments are invalid
*/
private CommandLine parseArgs(String[] args) throws ParseException {
CommandLineParser parser = new PosixParser();
CommandLine ln = parser.parse(options, args);
return ln;
}
/**
* Validates that the command line arguments are valid.
*
* @throws FileNotFoundException if there is a file specified by either the
* SCAN or CPE command line arguments that does not exist.
*/
private void validateArgs() throws FileNotFoundException, ParseException {
if (isRunScan()) {
validatePathExists(getScanFiles());
if (!line.hasOption(ArgumentName.OUT)) {
//TODO - need a new exception type here, this isn't really a ParseException.
throw new ParseException("Scan cannot be run without specifying a directory "
+ "to write the reports to via the 'out' argument.");
} else {
String p = line.getOptionValue(ArgumentName.OUT, "");
File f = new File(p);
if ("".equals(p) || !(f.exists() && f.isDirectory())) {
//TODO - need a new exception type here, this isn't really a ParseException.
throw new ParseException("A valid directory name must be specified for "
+ "the 'out' argument.");
}
}
if (!line.hasOption(ArgumentName.APPNAME)) {
throw new ParseException("Scan cannot be run without specifying an application "
+ "name via the 'app' argument.");
}
if (line.hasOption(ArgumentName.OUTPUT_FORMAT)) {
String format = line.getOptionValue(ArgumentName.OUTPUT_FORMAT);
if (!(format.equalsIgnoreCase("XML") || format.equalsIgnoreCase("HTML"))) {
throw new ParseException("Supported output formats are XML and HTML");
}
}
}
}
/**
* Validates whether or not the path(s) points at a file that exists; if the
* path(s) does not point to an existing file a FileNotFoundException is
* thrown.
*
* @param paths the paths to validate if they exists
* @throws FileNotFoundException is thrown if one of the paths being
* validated does not exist.
*/
private void validatePathExists(String[] paths) throws FileNotFoundException {
for (String path : paths) {
validatePathExists(path);
}
}
/**
* Validates whether or not the path points at a file that exists; if the
* path does not point to an existing file a FileNotFoundException is
* thrown.
*
* @param path the paths to validate if they exists
* @throws FileNotFoundException is thrown if the path being validated does
* not exist.
*/
private void validatePathExists(String path) throws FileNotFoundException {
File f = new File(path);
if (!f.exists()) {
isValid = false;
throw new FileNotFoundException("Invalid file argument: " + path);
}
}
/**
* Generates an Options collection that is used to parse the command line
* and to display the help message.
*
* @return the command line options used for parsing the command line
*/
@SuppressWarnings("static-access")
private Options createCommandLineOptions() {
Option help = new Option(ArgumentName.HELP_SHORT, ArgumentName.HELP, false,
"print this message.");
Option advancedHelp = new Option(ArgumentName.ADVANCED_HELP_SHORT, ArgumentName.ADVANCED_HELP, false,
"shows additional help regarding properties file.");
Option version = new Option(ArgumentName.VERSION_SHORT, ArgumentName.VERSION,
false, "print the version information.");
Option noupdate = new Option(ArgumentName.DISABLE_AUTO_UPDATE_SHORT, ArgumentName.DISABLE_AUTO_UPDATE,
false, "disables the automatic updating of the CPE data.");
Option appname = OptionBuilder.withArgName("name").hasArg().withLongOpt(ArgumentName.APPNAME)
.withDescription("the name of the application being scanned.")
.create(ArgumentName.APPNAME_SHORT);
Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.SCAN)
.withDescription("the path to scan - this option can be specified multiple times.")
.create(ArgumentName.SCAN_SHORT);
Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.PROP)
.withDescription("a property file to load.")
.create(ArgumentName.PROP_SHORT);
Option out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ArgumentName.OUT)
.withDescription("the folder to write reports to.")
.create(ArgumentName.OUT_SHORT);
Option outputformat = OptionBuilder.withArgName("format").hasArg().withLongOpt(ArgumentName.OUTPUT_FORMAT)
.withDescription("the output format to write to.")
.create(ArgumentName.OUTPUT_FORMAT_SHORT);
//TODO add the ability to load a properties file to override the defaults...
OptionGroup og = new OptionGroup();
og.addOption(path);
Options opts = new Options();
opts.addOptionGroup(og);
opts.addOption(out);
opts.addOption(outputformat);
opts.addOption(appname);
opts.addOption(version);
opts.addOption(help);
opts.addOption(noupdate);
opts.addOption(props);
opts.addOption(advancedHelp);
return opts;
}
/**
* Determines if the 'version' command line argument was passed in.
*
* @return whether or not the 'version' command line argument was passed in
*/
public boolean isGetVersion() {
return (line != null) && line.hasOption(ArgumentName.VERSION);
}
/**
* Determines if the 'help' command line argument was passed in.
*
* @return whether or not the 'help' command line argument was passed in
*/
public boolean isGetHelp() {
return (line != null) && line.hasOption(ArgumentName.HELP);
}
/**
* Determines if the 'scan' command line argument was passed in.
*
* @return whether or not the 'scan' command line argument was passed in
*/
public boolean isRunScan() {
return (line != null) && isValid && line.hasOption(ArgumentName.SCAN);
}
/**
* Displays the command line help message to the standard output.
*/
public void printHelp() {
HelpFormatter formatter = new HelpFormatter();
String nl = System.getProperty("line.separator");
String advancedHelp = null;
if (line.hasOption(ArgumentName.ADVANCED_HELP)) {
advancedHelp = nl + nl
+ "Additionally, the following properties are supported and can be specified either"
+ "using the -p <file> argument or by passing them in as system properties." + nl
+ nl + " " + Settings.KEYS.PROXY_URL + "\t\t the proxy URL to use when downloading resources."
+ nl + " " + Settings.KEYS.PROXY_PORT + "\t\t the proxy port to use when downloading resources."
+ nl + " " + Settings.KEYS.CONNECTION_TIMEOUT + "\t the connection timeout (in milliseconds) to use"
+ nl + "\t\t\t when downloading resources.";
}
formatter.printHelp(Settings.getString("application.name", "DependencyCheck"),
nl + Settings.getString("application.name", "DependencyCheck")
+ " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
+ Settings.getString("application.name", "DependencyCheck")
+ " will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov." + nl + nl,
options,
"",
true);
if (advancedHelp != null) {
System.out.println(advancedHelp);
}
}
/**
* Retrieves the file command line parameter(s) specified for the 'scan'
* argument.
*
* @return the file paths specified on the command line for scan
*/
public String[] getScanFiles() {
return line.getOptionValues(ArgumentName.SCAN);
}
/**
* returns the directory to write the reports to specified on the command
* line.
*
* @return the path to the reports directory.
*/
public String getReportDirectory() {
return line.getOptionValue(ArgumentName.OUT);
}
/**
* Returns the output format specified on the command line. Defaults to
* HTML if no format was specified.
*
* @return the output format name.
*/
public String getReportFormat() {
return line.getOptionValue(ArgumentName.OUTPUT_FORMAT, "HTML");
}
/**
* Returns the application name specified on the command line.
*
* @return the application name.
*/
public String getApplicationName() {
return line.getOptionValue(ArgumentName.APPNAME);
}
/**
* <p>Prints the manifest information to standard output:</p>
* <ul><li>Implementation-Title: ${pom.name}</li>
* <li>Implementation-Version: ${pom.version}</li></ul>
*/
public void printVersionInfo() {
String version = String.format("%s version %s",
Settings.getString("application.name", "DependencyCheck"),
Settings.getString("application.version", "Unknown"));
System.out.println(version);
}
/**
* Checks if the auto update feature has been disabled. If it has been
* disabled via the command line this will return false.
*
* @return if auto-update is allowed.
*/
public boolean isAutoUpdate() {
return (line == null) || !line.hasOption(ArgumentName.DISABLE_AUTO_UPDATE);
}
/**
* A collection of static final strings that represent the possible command
* line arguments.
*/
public static class ArgumentName {
/**
* The long CLI argument name specifying the directory/file to scan
*/
public static final String SCAN = "scan";
/**
* The short CLI argument name specifying the directory/file to scan
*/
public static final String SCAN_SHORT = "s";
/**
* The long CLI argument name specifying that the CPE/CVE/etc. data
* should not be automatically updated.
*/
public static final String DISABLE_AUTO_UPDATE = "noupdate";
/**
* The short CLI argument name specifying that the CPE/CVE/etc. data
* should not be automatically updated.
*/
public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
/**
* The long CLI argument name specifying the directory to write the
* reports to.
*/
public static final String OUT = "out";
/**
* The short CLI argument name specifying the directory to write the
* reports to.
*/
public static final String OUT_SHORT = "o";
/**
* The long CLI argument name specifying the output format to write the
* reports to.
*/
public static final String OUTPUT_FORMAT = "format";
/**
* The short CLI argument name specifying the output format to write the
* reports to.
*/
public static final String OUTPUT_FORMAT_SHORT = "f";
/**
* The long CLI argument name specifying the name of the application to
* be scanned.
*/
public static final String APPNAME = "app";
/**
* The short CLI argument name specifying the name of the application to
* be scanned.
*/
public static final String APPNAME_SHORT = "a";
/**
* The long CLI argument name asking for help.
*/
public static final String HELP = "help";
/**
* The short CLI argument name asking for help.
*/
public static final String HELP_SHORT = "h";
/**
* The long CLI argument name asking for the version.
*/
public static final String VERSION_SHORT = "v";
/**
* The short CLI argument name asking for the version.
*/
public static final String VERSION = "version";
/**
* The CLI argument name asking for advanced help.
*/
public static final String ADVANCED_HELP_SHORT = "ah";
/**
* The short CLI argument name asking for advanced help.
*/
public static final String ADVANCED_HELP = "advancedhelp";
/**
* The short CLI argument name for setting the location of an additional
* properties file.
*/
public static final String PROP_SHORT = "p";
/**
* The CLI argument name for setting the location of an additional
* properties file.
*/
public static final String PROP = "propertyfile";
}
}

View File

@@ -0,0 +1,66 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.IOException;
/**
* An exception used when a download fails.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class DownloadFailedException extends IOException {
private static final long serialVersionUID = 1L;
/**
* Creates a new DownloadFailedException.
*/
public DownloadFailedException() {
super();
}
/**
* Creates a new DownloadFailedException.
*
* @param msg a message for the exception.
*/
public DownloadFailedException(String msg) {
super(msg);
}
/**
* Creates a new DownloadFailedException.
*
* @param ex the cause of the download failure.
*/
public DownloadFailedException(Throwable ex) {
super(ex);
}
/**
* Creates a new DownloadFailedException.
*
* @param msg a message for the exception.
* @param ex the cause of the download failure.
*/
public DownloadFailedException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,230 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;
/**
* A utility to download files from the Internet.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class Downloader {
/**
* Private constructor for utility class.
*/
private Downloader() {
}
/**
* Retrieves a file from a given URL and saves it to the outputPath.
*
* @param url the URL of the file to download.
* @param outputPath the path to the save the file to.
* @throws DownloadFailedException is thrown if there is an error
* downloading the file.
*/
public static void fetchFile(URL url, String outputPath) throws DownloadFailedException {
fetchFile(url, outputPath, false);
}
/**
* Retrieves a file from a given URL and saves it to the outputPath.
*
* @param url the URL of the file to download.
* @param outputPath the path to the save the file to.
* @param unzip true/false indicating that the file being retrieved is
* gzipped and if true, should be uncompressed before writing to the file.
* @throws DownloadFailedException is thrown if there is an error
* downloading the file.
*/
public static void fetchFile(URL url, String outputPath, boolean unzip) throws DownloadFailedException {
File f = new File(outputPath);
fetchFile(url, f, unzip);
}
/**
* Retrieves a file from a given URL and saves it to the outputPath.
*
* @param url the URL of the file to download.
* @param outputPath the path to the save the file to.
* @throws DownloadFailedException is thrown if there is an error
* downloading the file.
*/
public static void fetchFile(URL url, File outputPath) throws DownloadFailedException {
fetchFile(url, outputPath, false);
}
/**
* Retrieves a file from a given URL and saves it to the outputPath.
*
* @param url the URL of the file to download.
* @param outputPath the path to the save the file to.
* @param unzip true/false indicating that the file being retrieved is
* gzipped and if true, should be uncompressed before writing to the file.
* @throws DownloadFailedException is thrown if there is an error
* downloading the file.
*/
public static void fetchFile(URL url, File outputPath, boolean unzip) throws DownloadFailedException {
HttpURLConnection conn = null;
try {
conn = Downloader.getConnection(url);
conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
conn.connect();
} catch (IOException ex) {
try {
if (conn != null) {
conn.disconnect();
}
} finally {
conn = null;
}
throw new DownloadFailedException("Error downloading file.", ex);
}
String encoding = conn.getContentEncoding();
BufferedOutputStream writer = null;
InputStream reader = null;
try {
if (unzip || (encoding != null && "gzip".equalsIgnoreCase(encoding))) {
reader = new GZIPInputStream(conn.getInputStream());
} else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
reader = new InflaterInputStream(conn.getInputStream());
} else {
reader = conn.getInputStream();
}
writer = new BufferedOutputStream(new FileOutputStream(outputPath));
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = reader.read(buffer)) > 0) {
writer.write(buffer, 0, bytesRead);
}
} catch (Exception ex) {
throw new DownloadFailedException("Error saving downloaded file.", ex);
} finally {
if (writer != null) {
try {
writer.close();
writer = null;
} catch (Exception ex) {
Logger.getLogger(Downloader.class.getName()).log(Level.FINEST,
"Error closing the writer in Downloader.", ex);
}
}
if (reader != null) {
try {
reader.close();
reader = null;
} catch (Exception ex) {
Logger.getLogger(Downloader.class.getName()).log(Level.FINEST,
"Error closing the reader in Downloader.", ex);
}
}
try {
conn.disconnect();
} finally {
conn = null;
}
}
}
/**
* Makes an HTTP Head request to retrieve the last modified date of the given URL.
*
* @param url the URL to retrieve the timestamp from
* @return an epoch timestamp
* @throws DownloadFailedException is thrown if an exception occurs making the HTTP request
*/
public static long getLastModified(URL url) throws DownloadFailedException {
HttpURLConnection conn = null;
long timestamp = 0;
try {
conn = Downloader.getConnection(url);
conn.setRequestMethod("HEAD");
conn.connect();
timestamp = conn.getLastModified();
} catch (Exception ex) {
throw new DownloadFailedException("Error making HTTP HEAD request.", ex);
} finally {
if (conn != null) {
try {
conn.disconnect();
} finally {
conn = null;
}
}
}
return timestamp;
}
/**
* Utility method to get an HttpURLConnection. If the app is configured to
* use a proxy this method will retrieve the proxy settings and use them
* when setting up the connection.
*
* @param url the url to connect to
* @return an HttpURLConnection
* @throws DownloadFailedException thrown if there is an exception
*/
private static HttpURLConnection getConnection(URL url) throws DownloadFailedException {
HttpURLConnection conn = null;
Proxy proxy = null;
String proxyUrl = Settings.getString(Settings.KEYS.PROXY_URL);
try {
if (proxyUrl != null) {
int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT);
SocketAddress addr = new InetSocketAddress(proxyUrl, proxyPort);
proxy = new Proxy(Proxy.Type.HTTP, addr);
conn = (HttpURLConnection) url.openConnection(proxy);
} else {
conn = (HttpURLConnection) url.openConnection();
}
if (Settings.getString(Settings.KEYS.CONNECTION_TIMEOUT) != null) {
int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT);
conn.setConnectTimeout(timeout);
}
} catch (IOException ex) {
try {
if (conn != null) {
conn.disconnect();
}
} finally {
conn = null;
}
throw new DownloadFailedException("Error getting connection.", ex);
}
return conn;
}
}

View File

@@ -0,0 +1,70 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* A collection of utilities for processing information about files.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class FileUtils {
/**
* Private constructor for a utility class.
*/
private FileUtils() {
}
/**
* Returns the (lowercase) file extension for a specified file.
*
* @param fileName the file name to retrieve the file extension from.
* @return the file extension.
*/
public static String getFileExtension(String fileName) {
String ret = null;
int pos = fileName.lastIndexOf(".");
if (pos >= 0) {
ret = fileName.substring(pos + 1, fileName.length()).toLowerCase();
}
return ret;
}
/**
* Deletes a file. If the File is a directory it will recursively delete
* the contents.
*
* @param file the File to delete
* @throws IOException is thrown if the file could not be deleted
*/
public static void delete(File file) throws IOException {
if (file.isDirectory()) {
for (File c : file.listFiles()) {
delete(c);
}
}
if (!file.delete()) {
throw new FileNotFoundException("Failed to delete file: " + file);
}
}
}

View File

@@ -0,0 +1,70 @@
package org.owasp.dependencycheck.utils;
import java.util.Iterator;
import java.util.NoSuchElementException;
/*
* This is an abstract filter that can be used to filter iterable list.
*
* This Filter class was copied from:
* http://erikras.com/2008/01/18/the-filter-pattern-java-conditional-abstraction-with-iterables/
*
* Erik Rasmussen - © 2006 - 2012 All Rights Reserved. @author Erik Rasmussen
* https://plus.google.com/115403795880834599019/?rel=author
*/
public abstract class Filter<T> {
public abstract boolean passes(T object);
public Iterator<T> filter(Iterator<T> iterator) {
return new FilterIterator(iterator);
}
public Iterable<T> filter(final Iterable<T> iterable) {
return new Iterable<T>() {
public Iterator<T> iterator() {
return filter(iterable.iterator());
}
};
}
private class FilterIterator implements Iterator<T> {
private Iterator<T> iterator;
private T next;
private FilterIterator(Iterator<T> iterator) {
this.iterator = iterator;
toNext();
}
public boolean hasNext() {
return next != null;
}
public T next() {
if (next == null) {
throw new NoSuchElementException();
}
T returnValue = next;
toNext();
return returnValue;
}
public void remove() {
throw new UnsupportedOperationException();
}
private void toNext() {
next = null;
while (iterator.hasNext()) {
T item = iterator.next();
if (item != null && passes(item)) {
next = item;
break;
}
}
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.IOException;
/**
* An exception used when an error occurs reading a setting.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class InvalidSettingException extends IOException {
private static final long serialVersionUID = 1L;
/**
* Creates a new InvalidSettingException.
*/
public InvalidSettingException() {
super();
}
/**
* Creates a new InvalidSettingException.
*
* @param msg a message for the exception.
*/
public InvalidSettingException(String msg) {
super(msg);
}
/**
* Creates a new InvalidSettingException.
*
* @param ex the cause of the setting exception.
*/
public InvalidSettingException(Throwable ex) {
super(ex);
}
/**
* Creates a new InvalidSettingException.
*
* @param msg a message for the exception.
* @param ex the cause of the setting exception.
*/
public InvalidSettingException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,49 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.FilterInputStream;
import java.io.InputStream;
/**
* NonClosingStream is a stream filter which prevents
* another class that processes the stream from closing
* it. This is necessary when dealing with things like
* JAXB and zipInputStreams.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class NonClosingStream extends FilterInputStream {
/**
* Constructs a new NonClosingStream
* @param in an input stream.
*/
public NonClosingStream(InputStream in) {
super(in);
}
/**
* Prevents closing of the stream.
*/
@Override
public void close() {
// don't close the stream.
}
}

View File

@@ -0,0 +1,273 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A simple settings container that wraps the dependencycheck.properties file.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class Settings {
/**
* The collection of keys used within the properties file.
*/
public static class KEYS {
/**
* private constructor because this is a "utility" class containing constants
*/
private KEYS() {
//do nothing
}
/**
* The properties key for the path where the CPE Lucene Index will be
* stored.
*/
public static final String CPE_INDEX = "cpe";
/**
* The properties key for the URL to the CPE.
*/
public static final String CPE_URL = "cpe.url";
/**
* The properties key for the URL to the CPE.
*/
public static final String CPE_META_URL = "cpe.meta.url";
/**
* The properties key for the path where the CVE Lucene Index will be
* stored.
*/
public static final String CVE_INDEX = "cve";
/**
* The properties key for the URL to retrieve the "meta" data from about
* the CVE entries.
*/
public static final String CVE_META_URL = "cve.url.meta";
/**
* The properties key for the URL to retrieve the recently modified and
* added CVE entries (last 8 days) using the 2.0 schema.
*/
public static final String CVE_MODIFIED_20_URL = "cve.url-2.0.modified";
/**
* The properties key for the URL to retrieve the recently modified and
* added CVE entries (last 8 days) using the 1.2 schema.
*/
public static final String CVE_MODIFIED_12_URL = "cve.url-1.2.modified";
/**
* The properties key for the URL to retrieve the recently modified and
* added CVE entries (last 8 days).
*/
public static final String CVE_MODIFIED_VALID_FOR_DAYS = "cve.url.modified.validfordays";
/**
* The properties key for the telling us how many cvr.url.* URLs exists.
* This is used in combination with CVE_BASE_URL to be able to retrieve
* the URLs for all of the files that make up the NVD CVE listing.
*/
public static final String CVE_URL_COUNT = "cve.url.count";
/**
* The properties key for the "base" property key for the CVE URLs (e.g.
* cve.url-2.0.1, cve.url-1.2.2, cve.url.n).
*/
public static final String CVE_BASE_URL = "cve.url-";
/**
* The properties key for the CVE schema version 1.2
*/
public static final String CVE_SCHEMA_1_2 = "1.2.";
/**
* The properties key for the CVE schema version 2.0
*/
public static final String CVE_SCHEMA_2_0 = "2.0.";
/**
* The properties key for the proxy url.
*/
public static final String PROXY_URL = "proxy.url";
/**
* The properties key for the proxy port - this must be an integer
* value.
*/
public static final String PROXY_PORT = "proxy.port";
/**
* The properties key for the connection timeout.
*/
public static final String CONNECTION_TIMEOUT = "connection.timeout";
}
private static final String PROPERTIES_FILE = "configuration/dependencycheck.properties";
private static final Settings INSTANCE = new Settings();
private Properties props = null;
/**
* Private constructor for the Settings class. This class loads the
* properties files.
*/
private Settings() {
InputStream in = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
props = new Properties();
try {
props.load(in);
} catch (IOException ex) {
Logger.getLogger(Settings.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Sets a property value.
*
* @param key the key for the property.
* @param value the value for the property.
*/
public static void setString(String key, String value) {
INSTANCE.props.setProperty(key, value);
}
/**
* Merges a new properties file into the current properties. This method
* allows for the loading of a user provided properties file.<br/><br/>
* Note: even if using this method - system properties will be loaded before
* properties loaded from files.
*
* @param filePath the path to the properties file to merge.
* @throws FileNotFoundException is thrown when the filePath points to a
* non-existent file.
* @throws IOException is thrown when there is an exception loading/merging
* the properties.
*/
public static void mergeProperties(String filePath) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream(filePath);
mergeProperties(fis);
}
/**
* Merges a new properties file into the current properties. This method
* allows for the loading of a user provided properties file.<br/><br/>
* Note: even if using this method - system properties will be loaded before
* properties loaded from files.
*
* @param stream an Input Stream pointing at a properties file to merge.
* @throws IOException is thrown when there is an exception loading/merging
* the properties
*/
public static void mergeProperties(InputStream stream) throws IOException {
INSTANCE.props.load(stream);
}
/**
* Returns a value from the properties file. If the value was specified as a
* system property or passed in via the -Dprop=value argument - this method
* will return the value from the system properties before the values in the
* contained configuration file.
*
* @param key the key to lookup within the properties file.
* @param defaultValue the default value for the requested property.
* @return the property from the properties file.
*/
public static String getString(String key, String defaultValue) {
String str = System.getProperty(key, INSTANCE.props.getProperty(key));
if (str == null) {
str = defaultValue;
}
return str;
}
/**
* Returns a value from the properties file. If the value was specified as a
* system property or passed in via the -Dprop=value argument - this method
* will return the value from the system properties before the values in the
* contained configuration file.
*
* @param key the key to lookup within the properties file.
* @return the property from the properties file.
*/
public static String getString(String key) {
return System.getProperty(key, INSTANCE.props.getProperty(key));
}
/**
* Returns an int value from the properties file. If the value was specified
* as a system property or passed in via the -Dprop=value argument - this
* method will return the value from the system properties before the values
* in the contained configuration file.
*
* @param key the key to lookup within the properties file.
* @return the property from the properties file.
* @throws InvalidSettingException is thrown if there is an error retrieving
* the setting.
*/
public static int getInt(String key) throws InvalidSettingException {
int value;
try {
value = Integer.parseInt(Settings.getString(key));
} catch (NumberFormatException ex) {
throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
}
return value;
}
/**
* Returns a long value from the properties file. If the value was specified
* as a system property or passed in via the -Dprop=value argument - this
* method will return the value from the system properties before the values
* in the contained configuration file.
*
* @param key the key to lookup within the properties file.
* @return the property from the properties file.
* @throws InvalidSettingException is thrown if there is an error retrieving
* the setting.
*/
public static long getLong(String key) throws InvalidSettingException {
long value;
try {
value = Long.parseLong(Settings.getString(key));
} catch (NumberFormatException ex) {
throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
}
return value;
}
/**
* Returns a boolean value from the properties file. If the value was
* specified as a system property or passed in via the -Dprop=value argument
* - this method will return the value from the system properties before the
* values in the contained configuration file.
*
* @param key the key to lookup within the properties file.
* @return the property from the properties file.
* @throws InvalidSettingException is thrown if there is an error retrieving
* the setting.
*/
public static boolean getBoolean(String key) throws InvalidSettingException {
boolean value;
try {
value = Boolean.parseBoolean(Settings.getString(key));
} catch (NumberFormatException ex) {
throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
}
return value;
}
}

View File

@@ -0,0 +1,13 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.utils</title>
* </head>
* <body>
* Includes various utility classes such as a Settings wrapper, a CLI Parser,
* a Checksum utility, etc.
* </body>
* </html>
*/
package org.owasp.dependencycheck.utils;