Moved some of the utility classes from core to a new utils module

Former-commit-id: 2e6ff9631ff4c843f10db1e022e41e728394e420
This commit is contained in:
Jeremy Long
2014-05-21 06:29:46 -04:00
parent d43fee5585
commit ce48823d38
25 changed files with 563 additions and 134 deletions

View File

@@ -0,0 +1,280 @@
<!--
This file is part of dependency-check-utils.
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.
-->
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.2-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-utils</artifactId>
<name>Dependency-Check Utils</name>
<description>Dependency-check-utils a collection of common utlity classs used within dependency-check.</description>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<distributionManagement>
<site>
<id>github-pages-site</id>
<name>Deployment through GitHub's site deployment plugin</name>
<url>${basedir}/../target/site/${project.version}/dependency-check-ant</url>
</site>
</distributionManagement>
<!-- end copy -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.6</version>
<configuration>
<instrumentation>
<ignoreTrivial>true</ignoreTrivial>
</instrumentation>
<check>
<branchRate>85</branchRate>
<lineRate>85</lineRate>
<haltOnFailure>false</haltOnFailure>
<totalBranchRate>85</totalBranchRate>
<totalLineRate>85</totalLineRate>
<packageLineRate>85</packageLineRate>
<packageBranchRate>85</packageBranchRate>
<regexes>
<regex>
<pattern>.*\$.*</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
</regexes>
</check>
</configuration>
<executions>
<execution>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<systemProperties>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.16</version>
<configuration>
<systemProperties>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<showDeprecation>false</showDeprecation>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.3</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.doxia</groupId>
<artifactId>doxia-module-markdown</artifactId>
<version>1.5</version>
</dependency>
</dependencies>
<configuration>
<skipDeploy>true</skipDeploy>
<reportPlugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.7</version>
<reportSets>
<reportSet>
<reports>
<report>index</report>
<report>summary</report>
<report>license</report>
<report>help</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<reportSets>
<reportSet>
<id>default</id>
<reports>
<report>javadoc</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.1</version>
<reportSets>
<reportSet>
<reports>
<report>dependency-updates-report</report>
<report>plugin-updates-report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.16</version>
<reportSets>
<reportSet>
<reports>
<report>report-only</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>taglist-maven-plugin</artifactId>
<version>2.4</version>
<configuration>
<tagListOptions>
<tagClasses>
<tagClass>
<displayName>Todo Work</displayName>
<tags>
<tag>
<matchString>todo</matchString>
<matchType>ignoreCase</matchType>
</tag>
<tag>
<matchString>FIXME</matchString>
<matchType>exact</matchType>
</tag>
</tags>
</tagClass>
</tagClasses>
</tagListOptions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.11</version>
<configuration>
<enableRulesSummary>false</enableRulesSummary>
<configLocation>${basedir}/../src/main/config/checkstyle-checks.xml</configLocation>
<headerLocation>${basedir}/../src/main/config/checkstyle-header.txt</headerLocation>
<suppressionsLocation>${basedir}/../src/main/config/checkstyle-suppressions.xml</suppressionsLocation>
<suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<targetJdk>1.6</targetJdk>
<linkXref>true</linkXref>
<sourceEncoding>utf-8</sourceEncoding>
<rulesets>
<ruleset>../src/main/config/dcrules.xml</ruleset>
<ruleset>/rulesets/java/basic.xml</ruleset>
<ruleset>/rulesets/java/imports.xml</ruleset>
<ruleset>/rulesets/java/unusedcode.xml</ruleset>
</rulesets>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.5.3</version>
</plugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,68 @@
/*
* 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) 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@owasp.org>
*/
public class DownloadFailedException extends IOException {
/**
* The serial version UID.
*/
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,196 @@
/*
* 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) 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.URISyntaxException;
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@owasp.org>
*/
public final class Downloader {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(Downloader.class.getName());
/**
* 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, File outputPath) throws DownloadFailedException {
fetchFile(url, outputPath, true);
}
/**
* 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 useProxy whether to use the configured proxy when downloading files
* @throws DownloadFailedException is thrown if there is an error downloading the file
*/
public static void fetchFile(URL url, File outputPath, boolean useProxy) throws DownloadFailedException {
if ("file".equalsIgnoreCase(url.getProtocol())) {
File file;
try {
file = new File(url.toURI());
} catch (URISyntaxException ex) {
final String msg = String.format("Download failed, unable to locate '%s'", url.toString());
throw new DownloadFailedException(msg);
}
if (file.exists()) {
try {
org.apache.commons.io.FileUtils.copyFile(file, outputPath);
} catch (IOException ex) {
final String msg = String.format("Download failed, unable to copy '%s'", url.toString());
throw new DownloadFailedException(msg);
}
} else {
final String msg = String.format("Download failed, file does not exist '%s'", url.toString());
throw new DownloadFailedException(msg);
}
} else {
HttpURLConnection conn = null;
try {
conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
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);
}
final String encoding = conn.getContentEncoding();
BufferedOutputStream writer = null;
InputStream reader = null;
try {
if (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));
final byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = reader.read(buffer)) > 0) {
writer.write(buffer, 0, bytesRead);
}
} catch (Throwable ex) {
throw new DownloadFailedException("Error saving downloaded file.", ex);
} finally {
if (writer != null) {
try {
writer.close();
} catch (Throwable ex) {
LOGGER.log(Level.FINEST,
"Error closing the writer in Downloader.", ex);
}
}
if (reader != null) {
try {
reader.close();
} catch (Throwable ex) {
LOGGER.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. If the file:// protocol is
* specified, then the lastTimestamp of the file is returned.
*
* @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 {
long timestamp = 0;
//TODO add the FTP protocol?
if ("file".equalsIgnoreCase(url.getProtocol())) {
File lastModifiedFile;
try {
lastModifiedFile = new File(url.toURI());
} catch (URISyntaxException ex) {
final String msg = String.format("Unable to locate '%s'; is the cve.url-2.0.modified property set correctly?", url.toString());
throw new DownloadFailedException(msg);
}
timestamp = lastModifiedFile.lastModified();
} else {
HttpURLConnection conn = null;
try {
conn = URLConnectionFactory.createHttpURLConnection(url);
conn.setRequestMethod("HEAD");
conn.connect();
timestamp = conn.getLastModified();
} catch (URLConnectionFailureException ex) {
throw new DownloadFailedException("Error creating URL Connection for HTTP HEAD request.", ex);
} catch (IOException ex) {
throw new DownloadFailedException("Error making HTTP HEAD request.", ex);
} finally {
if (conn != null) {
try {
conn.disconnect();
} finally {
conn = null;
}
}
}
}
return timestamp;
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.IOException;
/**
* An exception used when a file is unable to be un-zipped.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class ExtractionException extends IOException {
/**
* The serial version UID.
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new ExtractionException.
*/
public ExtractionException() {
super();
}
/**
* Creates a new ExtractionException.
*
* @param msg a message for the exception.
*/
public ExtractionException(String msg) {
super(msg);
}
/**
* Creates a new ExtractionException.
*
* @param ex the cause of the download failure.
*/
public ExtractionException(Throwable ex) {
super(ex);
}
/**
* Creates a new ExtractionException.
*
* @param msg a message for the exception.
* @param ex the cause of the download failure.
*/
public ExtractionException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,157 @@
/*
* 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) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A collection of utilities for processing information about files.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class FileUtils {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(FileUtils.class.getName());
/**
* Bit bucket for non-Windows systems
*/
private static final String BIT_BUCKET_UNIX = "/dev/null";
/**
* Bit bucket for Windows systems (yes, only one 'L')
*/
private static final String BIT_BUCKET_WIN = "NUL";
/**
* 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;
final 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
* @return true if the file was deleted successfully, otherwise false
*/
public static boolean delete(File file) {
boolean success = true;
if (!org.apache.commons.io.FileUtils.deleteQuietly(file)) {
success = false;
final String msg = String.format("Failed to delete file: %s; attempting to delete on exit.", file.getPath());
LOGGER.log(Level.FINE, msg);
file.deleteOnExit();
}
return success;
}
/**
* Generates a new temporary file name that is guaranteed to be unique.
*
* @param prefix the prefix for the file name to generate
* @param extension the extension of the generated file name
* @return a temporary File
* @throws java.io.IOException thrown if the temporary folder could not be created
*/
public static File getTempFile(String prefix, String extension) throws IOException {
final File dir = Settings.getTempDirectory();
final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension);
final File tempFile = new File(dir, tempFileName);
if (tempFile.exists()) {
return getTempFile(prefix, extension);
}
return tempFile;
}
/**
* Returns the data directory. If a path was specified in dependencycheck.properties or was specified using the
* Settings object, and the path exists, that path will be returned as a File object. If it does not exist, then a
* File object will be created based on the file location of the JAR containing the specified class.
*
* @param configuredFilePath the configured relative or absolute path
* @param clazz the class to resolve the path
* @return a File object
* @throws IOException is thrown if the path could not be decoded
* @deprecated This method should no longer be used. See the implementation in dependency-check-cli/App.java to see
* how the data directory should be set.
*/
@java.lang.Deprecated
public static File getDataDirectory(String configuredFilePath, Class clazz) throws IOException {
final File file = new File(configuredFilePath);
if (file.isDirectory() && file.canWrite()) {
return new File(file.getCanonicalPath());
} else {
final File exePath = getPathToJar(clazz);
return new File(exePath, configuredFilePath);
}
}
/**
* Retrieves the physical path to the parent directory containing the provided class. For example, if a JAR file
* contained a class org.something.clazz this method would return the parent directory of the JAR file.
*
* @param clazz the class to determine the parent directory of
* @return the parent directory of the file containing the specified class.
* @throws UnsupportedEncodingException thrown if UTF-8 is not supported.
* @deprecated this should no longer be used.
*/
@java.lang.Deprecated
public static File getPathToJar(Class clazz) throws UnsupportedEncodingException {
final String filePath = clazz.getProtectionDomain().getCodeSource().getLocation().getPath();
final String decodedPath = URLDecoder.decode(filePath, "UTF-8");
final File jarPath = new File(decodedPath);
return jarPath.getParentFile();
}
/**
* Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for Windows
*
* @return a String containing the bit bucket
*/
public static String getBitBucket() {
if (System.getProperty("os.name").startsWith("Windows")) {
return BIT_BUCKET_WIN;
} else {
return BIT_BUCKET_UNIX;
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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) 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@owasp.org>
*/
public class InvalidSettingException extends IOException {
/**
* The serial version UID.
*/
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,42 @@
/*
* 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) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.util.logging.Filter;
import java.util.logging.LogRecord;
/**
* A simple log filter to limit the entries written to the verbose log file. The verbose log file uses the root logger
* as I couldn't get anything else to work; as such, this filter limits the log entries to specific classes.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class LogFilter implements Filter {
/**
* Determines if the record should be logged.
*
* @param record a log record to examine
* @return true if the record should be logged, otherwise false
*/
@Override
public boolean isLoggable(LogRecord record) {
final String name = record.getSourceClassName();
return name.startsWith("org.owasp.dependencycheck") && !name.contains("generated") && !name.contains("VelocityLoggerRedirect");
}
}

View File

@@ -0,0 +1,93 @@
/*
* 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) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
/**
* A utility class to aide in the setup of the logging mechanism.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class LogUtils {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(LogUtils.class.getName());
/**
* Private constructor for a utility class.
*/
private LogUtils() {
}
/**
* Configures the logger for use by the application.
*
* @param in the input stream to read the log settings from
* @param verboseLogFile the file path for the verbose log
*/
public static void prepareLogger(InputStream in, String verboseLogFile) {
try {
LogManager.getLogManager().reset();
LogManager.getLogManager().readConfiguration(in);
if (verboseLogFile != null && !verboseLogFile.isEmpty()) {
verboseLoggingEnabled = true;
final Logger logger = Logger.getLogger("");
final FileHandler handler = new FileHandler(verboseLogFile, true);
handler.setFormatter(new SimpleFormatter());
handler.setLevel(Level.FINE);
handler.setFilter(new LogFilter());
logger.addHandler(handler);
logger.setLevel(Level.FINE);
}
} catch (IOException ex) {
LOGGER.log(Level.FINE, "IO Error preparing the logger", ex);
} catch (SecurityException ex) {
LOGGER.log(Level.FINE, "Error preparing the logger", ex);
} finally {
if (in != null) {
try {
in.close();
} catch (Throwable ex) {
LOGGER.log(Level.FINEST, "Error closing resource stream", ex);
}
}
}
}
/**
* Whether or not verbose logging is enabled.
*/
private static boolean verboseLoggingEnabled = false;
/**
* Get the value of verboseLoggingEnabled.
*
* @return the value of verboseLoggingEnabled
*/
public static boolean isVerboseLoggingEnabled() {
return verboseLoggingEnabled;
}
}

View File

@@ -0,0 +1,618 @@
/*
* 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) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.utils.FileUtils;
/**
* A simple settings container that wraps the dependencycheck.properties file.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class Settings {
//<editor-fold defaultstate="collapsed" desc="KEYS used to access settings">
/**
* The collection of keys used within the properties file.
*/
public static final class KEYS {
/**
* private constructor because this is a "utility" class containing constants
*/
private KEYS() {
//do nothing
}
/**
* The properties key indicating whether or not the cached data sources should be updated.
*/
public static final String AUTO_UPDATE = "autoupdate";
/**
* The database driver class name. If this is not in the properties file the embedded database is used.
*/
public static final String DB_DRIVER_NAME = "data.driver_name";
/**
* The database driver class name. If this is not in the properties file the embedded database is used.
*/
public static final String DB_DRIVER_PATH = "data.driver_path";
/**
* The database connection string. If this is not in the properties file the embedded database is used.
*/
public static final String DB_CONNECTION_STRING = "data.connection_string";
/**
* The username to use when connecting to the database.
*/
public static final String DB_USER = "data.user";
/**
* The password to authenticate to the database.
*/
public static final String DB_PASSWORD = "data.password";
/**
* The base path to use for the data directory (for embedded db).
*/
public static final String DATA_DIRECTORY = "data.directory";
/**
* 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_START_YEAR = "cve.startyear";
/**
* The properties key for the CVE schema version 1.2.
*/
public static final String CVE_SCHEMA_1_2 = "cve.url-1.2.base";
/**
* The properties key for the CVE schema version 2.0.
*/
public static final String CVE_SCHEMA_2_0 = "cve.url-2.0.base";
/**
* 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 proxy username.
*/
public static final String PROXY_USERNAME = "proxy.username";
/**
* The properties key for the proxy password.
*/
public static final String PROXY_PASSWORD = "proxy.password";
/**
* The properties key for the connection timeout.
*/
public static final String CONNECTION_TIMEOUT = "connection.timeout";
/**
* The location of the temporary directory.
*/
public static final String TEMP_DIRECTORY = "temp.directory";
/**
* The maximum number of threads to allocate when downloading files.
*/
public static final String MAX_DOWNLOAD_THREAD_POOL_SIZE = "max.download.threads";
/**
* The key for a list of suppression files.
*/
public static final String SUPPRESSION_FILE = "suppression.file";
/**
* The properties key for whether the Jar Analyzer is enabled.
*/
public static final String ANALYZER_JAR_ENABLED = "analyzer.jar.enabled";
/**
* The properties key for whether the Archive analyzer is enabled.
*/
public static final String ANALYZER_ARCHIVE_ENABLED = "analyzer.archive.enabled";
/**
* The properties key for whether the .NET Assembly analyzer is enabled.
*/
public static final String ANALYZER_ASSEMBLY_ENABLED = "analyzer.assembly.enabled";
/**
* The properties key for whether the .NET Nuspec analyzer is enabled.
*/
public static final String ANALYZER_NUSPEC_ENABLED = "analyzer.nuspec.enabled";
/**
* The properties key for whether the JavaScript analyzer is enabled.
*/
public static final String ANALYZER_JAVASCRIPT_ENABLED = "analyzer.javascript.enabled";
/**
* The properties key for whether the Nexus analyzer is enabled.
*/
public static final String ANALYZER_NEXUS_ENABLED = "analyzer.nexus.enabled";
/**
* The properties key for the Nexus search URL.
*/
public static final String ANALYZER_NEXUS_URL = "analyzer.nexus.url";
/**
* The properties key for using the proxy to reach Nexus.
*/
public static final String ANALYZER_NEXUS_PROXY = "analyzer.nexus.proxy";
/**
* The path to mono, if available.
*/
public static final String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path";
/**
* The additional configured zip file extensions, if available.
*/
public static final String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip";
/**
* The properties key for whether Test Scope dependencies should be skipped.
*/
public static final String SKIP_TEST_SCOPE = "skip.test.scope";
/**
* The properties key for whether Runtime Scope dependencies should be skipped.
*/
public static final String SKIP_RUNTIME_SCOPE = "skip.runtime.scope";
/**
* The properties key for whether Provided Scope dependencies should be skipped.
*/
public static final String SKIP_PROVIDED_SCOPE = "skip.provided.scope";
}
//</editor-fold>
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(Settings.class.getName());
/**
* The properties file location.
*/
private static final String PROPERTIES_FILE = "dependencycheck.properties";
/**
* Thread local settings.
*/
private static ThreadLocal<Settings> localSettings = new ThreadLocal();
/**
* The properties.
*/
private Properties props = null;
/**
* Private constructor for the Settings class. This class loads the properties files.
*/
private Settings() {
InputStream in = null;
props = new Properties();
try {
in = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
props.load(in);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Unable to load default settings.");
LOGGER.log(Level.FINE, null, ex);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, null, ex);
}
}
}
logProperties("Properties loaded", props);
}
/**
* Initializes the thread local settings object. Note, to use the settings object you must call this method.
* However, you must also call Settings.cleanup() to properly release resources.
*/
public static void initialize() {
localSettings.set(new Settings());
}
/**
* Cleans up resources to prevent memory leaks.
*
* @param deleteTemporary flag indicating whether any temporary directories generated should be removed
*/
public static void cleanup(boolean deleteTemporary) {
if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) {
FileUtils.delete(tempDirectory);
}
try {
localSettings.remove();
} catch (Throwable ex) {
LOGGER.log(Level.FINE, "Error cleaning up Settings", ex);
}
}
/**
* Gets the underlying instance of the Settings object.
*
* @return the Settings object
*/
public static Settings getInstance() {
return localSettings.get();
}
/**
* Sets the instance of the Settings object to use in this thread.
*
* @param instance the instance of the settings object to use in this thread
*/
public static void setInstance(Settings instance) {
localSettings.set(instance);
}
/**
* Logs the properties. This will not log any properties that contain 'password' in the key.
*
* @param header the header to print with the log message
* @param properties the properties to log
*/
private static void logProperties(String header, Properties properties) {
if (LOGGER.isLoggable(Level.FINE)) {
final StringWriter sw = new StringWriter();
PrintWriter pw = null;
try {
pw = new PrintWriter(sw);
pw.format("%s:%n%n", header);
final Enumeration e = properties.propertyNames();
while (e.hasMoreElements()) {
final String key = (String) e.nextElement();
if (key.contains("password")) {
pw.format("%s='*****'%n", key);
} else {
final String value = properties.getProperty(key);
if (value != null) {
pw.format("%s='%s'%n", key, value);
}
}
}
pw.flush();
LOGGER.fine(sw.toString());
} finally {
if (pw != null) {
pw.close();
}
}
}
}
/**
* 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) {
localSettings.get().props.setProperty(key, value);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(String.format("Setting: %s='%s'", key, value));
}
}
/**
* Sets a property value.
*
* @param key the key for the property
* @param value the value for the property
*/
public static void setBoolean(String key, boolean value) {
if (value) {
localSettings.get().props.setProperty(key, Boolean.TRUE.toString());
} else {
localSettings.get().props.setProperty(key, Boolean.FALSE.toString());
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(String.format("Setting: %s='%b'", 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(File filePath) throws FileNotFoundException, IOException {
final 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 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 {
final 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 {
localSettings.get().props.load(stream);
logProperties("Properties updated via merge", localSettings.get().props);
}
/**
* Returns a value from the properties file as a File object. 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 converted to a File object
*/
public static File getFile(String key) {
final String file = getString(key);
if (file == null) {
return null;
}
return new File(file);
}
/**
* Returns a value from the properties file as a File object. 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.
*
* This method will check the configured base directory and will use this as the base of the file path.
* Additionally, if the base directory begins with a leading "[JAR]\" sequence with the path to the folder
* containing the JAR file containing this class.
*
* @param key the key to lookup within the properties file
* @return the property from the properties file converted to a File object
*/
public static File getDataFile(String key) {
final String file = getString(key);
LOGGER.log(Level.FINE, String.format("Settings.getDataFile() - file: '%s'", file));
if (file == null) {
return null;
}
if (file.startsWith("[JAR]")) {
LOGGER.log(Level.FINE, "Settings.getDataFile() - transforming filename");
final File jarPath = getJarPath();
LOGGER.log(Level.FINE, String.format("Settings.getDataFile() - jar file: '%s'", jarPath.toString()));
final File retVal = new File(jarPath, file.substring(6));
LOGGER.log(Level.FINE, String.format("Settings.getDataFile() - returning: '%s'", retVal.toString()));
return retVal;
}
return new File(file);
}
/**
* Attempts to retrieve the folder containing the Jar file containing the Settings class.
*
* @return a File object
*/
private static File getJarPath() {
final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = ".";
try {
decodedPath = URLDecoder.decode(jarPath, "UTF-8");
} catch (UnsupportedEncodingException ex) {
LOGGER.log(Level.FINEST, null, ex);
}
final File path = new File(decodedPath);
if (path.getName().toLowerCase().endsWith(".jar")) {
return path.getParentFile();
} else {
return new File(".");
}
}
/**
* 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) {
final String str = System.getProperty(key, localSettings.get().props.getProperty(key, defaultValue));
return str;
}
/**
* A reference to the temporary directory; used incase it needs to be deleted during cleanup.
*/
private static File tempDirectory = null;
/**
* Returns the temporary directory.
*
* @return the temporary directory
* @throws java.io.IOException thrown if the temporary directory does not exist and cannot be created
*/
public static File getTempDirectory() throws IOException {
final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")));
if (!tmpDir.exists()) {
if (!tmpDir.mkdirs()) {
final String msg = String.format("Unable to make a temporary folder '%s'", tmpDir.getPath());
throw new IOException(msg);
} else {
tempDirectory = tmpDir;
}
}
return tmpDir;
}
/**
* 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, localSettings.get().props.getProperty(key));
}
/**
* Removes a property from the local properties collection. This is mainly used in test cases.
*
* @param key the property key to remove
*/
public static void removeProperty(String key) {
localSettings.get().props.remove(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 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
* @param defaultValue the default value to return
* @return the property from the properties file or the defaultValue if the property does not exist or cannot be
* converted to an integer
*/
public static int getInt(String key, int defaultValue) {
int value;
try {
value = Integer.parseInt(Settings.getString(key));
} catch (NumberFormatException ex) {
final String msg = String.format("Could not convert property '%s' to an int.", key);
LOGGER.log(Level.FINEST, msg, ex);
value = defaultValue;
}
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 <code>-Dprop=value</code> 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;
}
/**
* Returns a boolean value from the properties file. If the value was specified as a system property or passed in
* via the <code>-Dprop=value</code> 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 to return if the setting does not exist
* @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, boolean defaultValue) throws InvalidSettingException {
boolean value;
try {
final String strValue = Settings.getString(key);
if (strValue == null) {
return defaultValue;
}
value = Boolean.parseBoolean(strValue);
} catch (NumberFormatException ex) {
throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
}
return value;
}
}

View File

@@ -0,0 +1,118 @@
/*
* 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) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.IOException;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URL;
/**
* A URLConnection Factory to create new connections. This encapsulates several configuration checks to ensure that the
* connection uses the correct proxy settings.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class URLConnectionFactory {
/**
* Private constructor for this factory.
*/
private URLConnectionFactory() {
}
/**
* Utility method to create an HttpURLConnection. If the application 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 URLConnectionFailureException thrown if there is an exception
*/
public static HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException {
HttpURLConnection conn = null;
Proxy proxy = null;
final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_URL);
try {
if (proxyUrl != null) {
final int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT);
final SocketAddress address = new InetSocketAddress(proxyUrl, proxyPort);
final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME);
final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD);
if (username != null && password != null) {
final Authenticator auth = new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
if (getRequestorType().equals(Authenticator.RequestorType.PROXY)) {
return new PasswordAuthentication(username, password.toCharArray());
}
return super.getPasswordAuthentication();
}
};
Authenticator.setDefault(auth);
}
proxy = new Proxy(Proxy.Type.HTTP, address);
conn = (HttpURLConnection) url.openConnection(proxy);
} else {
conn = (HttpURLConnection) url.openConnection();
}
final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 60000);
conn.setConnectTimeout(timeout);
} catch (IOException ex) {
if (conn != null) {
try {
conn.disconnect();
} finally {
conn = null;
}
}
throw new URLConnectionFailureException("Error getting connection.", ex);
}
return conn;
}
/**
* Utility method to create an HttpURLConnection. The use of a proxy here is optional as there may be cases where a
* proxy is configured but we don't want to use it (for example, if there's an internal repository configured)
*
* @param url the url to connect to
* @param proxy whether to use the proxy (if configured)
* @return a newly constructed HttpURLConnection
* @throws URLConnectionFailureException thrown if there is an exception
*/
public static HttpURLConnection createHttpURLConnection(URL url, boolean proxy) throws URLConnectionFailureException {
if (proxy) {
return createHttpURLConnection(url);
}
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) url.openConnection();
final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 60000);
conn.setConnectTimeout(timeout);
} catch (IOException ioe) {
throw new URLConnectionFailureException("Error getting connection.", ioe);
}
return conn;
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.IOException;
/**
* An exception used when the creation of an URLConnection fails.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class URLConnectionFailureException extends IOException {
/**
* The serial version UID.
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new URLConnectionFailureException.
*/
public URLConnectionFailureException() {
super();
}
/**
* Creates a new URLConnectionFailureException.
*
* @param msg a message for the exception.
*/
public URLConnectionFailureException(String msg) {
super(msg);
}
/**
* Creates a new URLConnectionFailureException.
*
* @param ex the cause of the download failure.
*/
public URLConnectionFailureException(Throwable ex) {
super(ex);
}
/**
* Creates a new URLConnectionFailureException.
*
* @param msg a message for the exception.
* @param ex the cause of the download failure.
*/
public URLConnectionFailureException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,11 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.utils</title>
* </head>
* <body>
* Includes various utility classes such as a Settings wrapper, utilities to make URL Connections, etc.
* </body>
* </html>
*/
package org.owasp.dependencycheck.utils;

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2014 OWASP.
*
* 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.
*/
package org.owasp.dependencycheck.utils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class BaseTest {
@BeforeClass
public static void setUpClass() throws Exception {
Settings.initialize();
}
@AfterClass
public static void tearDownClass() throws Exception {
Settings.cleanup(true);
}
}

View File

@@ -0,0 +1,54 @@
/*
* 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) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.File;
import java.net.URL;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class DownloaderIntegrationTest extends BaseTest {
/**
* Test of fetchFile method, of class Downloader.
*
* @throws Exception thrown when an exception occurs.
*/
@Test
public void testFetchFile() throws Exception {
// Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, "1000");
// Settings.setString(Settings.KEYS.PROXY_PORT, "8080");
// Settings.setString(Settings.KEYS.PROXY_URL, "127.0.0.1");
URL url = new URL(Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL));
File outputPath = new File("target/downloaded_cve.xml");
Downloader.fetchFile(url, outputPath);
}
@Test
public void testGetLastModified() throws Exception {
URL url = new URL("http://nvd.nist.gov/download/nvdcve-2012.xml");
long timestamp = Downloader.getLastModified(url);
assertTrue("timestamp equal to zero?", timestamp > 0);
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.File;
import java.net.URL;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.owasp.dependencycheck.utils.Downloader;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class DownloaderTest {
@Test
public void testGetLastModified_file() throws Exception {
File f = new File("target/test-classes/dependencycheck.properties");
URL url = new URL("file:///" + f.getCanonicalPath());
long timestamp = Downloader.getLastModified(url);
assertTrue("timestamp equal to zero?", timestamp > 0);
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.File;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class FileUtilsTest extends BaseTest {
/**
* Test of getFileExtension method, of class FileUtils.
*/
@Test
public void testGetFileExtension() {
String[] fileName = {"something-0.9.5.jar", "lib2-1.1.js"};
String[] expResult = {"jar", "js"};
for (int i = 0; i < fileName.length; i++) {
String result = FileUtils.getFileExtension(fileName[i]);
assertEquals("Failed extraction on \"" + fileName[i] + "\".", expResult[i], result);
}
}
/**
* Test of delete method, of class FileUtils.
*/
@Test
public void testDelete() throws Exception {
File file = File.createTempFile("tmp", "deleteme", Settings.getTempDirectory());
if (!file.exists()) {
fail("Unable to create a temporary file.");
}
boolean status = FileUtils.delete(file);
assertTrue("delete returned a failed status", status);
assertFalse("Temporary file exists after attempting deletion", file.exists());
}
}

View File

@@ -0,0 +1,160 @@
/*
* 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) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import org.junit.Assert;
import org.junit.Test;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class SettingsTest extends BaseTest {
/**
* Test of getString method, of class Settings.
*/
@Test
public void testGetString() {
String key = Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS;
String expResult = "7";
String result = Settings.getString(key);
Assert.assertTrue(result.endsWith(expResult));
}
/**
* Test of getDataFile method, of class Settings.
*/
@Test
public void testGetDataFile() throws IOException {
String key = Settings.KEYS.DATA_DIRECTORY;
String expResult = "data";
File result = Settings.getDataFile(key);
Assert.assertTrue(result.getAbsolutePath().endsWith(expResult));
}
/**
* Test of mergeProperties method, of class Settings.
*/
@Test
public void testMergeProperties_String() throws IOException, URISyntaxException {
String key = Settings.KEYS.PROXY_PORT;
String expResult = Settings.getString(key);
File f = new File(this.getClass().getClassLoader().getResource("test.properties").toURI());
//InputStream in = this.getClass().getClassLoader().getResourceAsStream("test.properties");
Settings.mergeProperties(f.getAbsolutePath());
String result = Settings.getString(key);
Assert.assertTrue("setting didn't change?", (expResult == null && result != null) || !expResult.equals(result));
}
/**
* Test of setString method, of class Settings.
*/
@Test
public void testSetString() {
String key = "newProperty";
String value = "someValue";
Settings.setString(key, value);
String expResults = Settings.getString(key);
Assert.assertEquals(expResults, value);
}
/**
* Test of getString method, of class Settings.
*/
@Test
public void testGetString_String_String() {
String key = "key That Doesn't Exist";
String defaultValue = "blue bunny";
String expResult = "blue bunny";
String result = Settings.getString(key);
Assert.assertTrue(result == null);
result = Settings.getString(key, defaultValue);
Assert.assertEquals(expResult, result);
}
/**
* Test of getString method, of class Settings.
*/
@Test
public void testGetString_String() {
String key = Settings.KEYS.CONNECTION_TIMEOUT;
String result = Settings.getString(key);
Assert.assertTrue(result == null);
}
/**
* Test of getInt method, of class Settings.
*/
@Test
public void testGetInt() throws InvalidSettingException {
String key = "SomeNumber";
int expResult = 85;
Settings.setString(key, "85");
int result = Settings.getInt(key);
Assert.assertEquals(expResult, result);
}
/**
* Test of getLong method, of class Settings.
*/
@Test
public void testGetLong() throws InvalidSettingException {
String key = "SomeNumber";
long expResult = 300L;
Settings.setString(key, "300");
long result = Settings.getLong(key);
Assert.assertEquals(expResult, result);
}
/**
* Test of getBoolean method, of class Settings.
*/
@Test
public void testGetBoolean() throws InvalidSettingException {
String key = "SomeBoolean";
Settings.setString(key, "false");
boolean expResult = false;
boolean result = Settings.getBoolean(key);
Assert.assertEquals(expResult, result);
key = "something that does not exist";
expResult = true;
result = Settings.getBoolean(key, true);
Assert.assertEquals(expResult, result);
}
/**
* Test of removeProperty method, of class Settings.
*/
@Test
public void testRemoveProperty() {
String key = "SomeKey";
String value = "value";
String dfault = "default";
Settings.setString(key, value);
String ret = Settings.getString(key);
Assert.assertEquals(value, ret);
Settings.removeProperty(key);
ret = Settings.getString(key, dfault);
Assert.assertEquals(dfault, ret);
}
}

View File

@@ -0,0 +1,57 @@
application.name=${pom.name}
application.version=${pom.version}
autoupdate=true
max.download.threads=3
#temp.directory defaults to System.getProperty("java.io.tmpdir")
#temp.directory=[path to temp directory]
# the path to the data directory; the [JAR] signifies to use the relative path
# to the dependency-check-core JAR file. This path is only used to construct
# the connection string for the H2 driver (or other drivers that require a file path
# to be supplied. If you are using another database (MySQL, Oracle, etc.) this property
# will not be used. The data.directory will be resolved and if the connection string
# below contains a %s then the data.directory will replace the %s.
data.directory=[JAR]/data
data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
#data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON;
#data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
# user name and password for the database connection. The inherent case is to use H2.
# As such, this unsecure username/password exist.
data.user=dcuser
data.password=DC-Pass1337!
# The following are only used if the DB Driver is not JDBC4 compliant and/or the driver
# is not in the current classpath. Setting these properties will add the give path(s) to
# the class loader and then register the driver with the DriverManager. If the class is
# not in the path you must specify both the driver name (aka the fully qualified driver name)
# and the driver path. The driver path can be a semi-colon separated list of files/directories
# to ensure any and all needed files can be added to the classpath to load the driver.
# For non-JDBC4 drivers in the classpath only the driver_name needs to be set.
# For MOST situations these properties likely do not need to be set.
data.driver_name=org.h2.Driver
data.driver_path=
# the path to the cpe xml file
cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.xml.gz
# the path to the cpe meta data file.
cpe.meta.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.meta
# the number of days that the modified nvd cve data holds data for. We don't need
# to update the other files if we are within this timespan. Per NIST this file
# holds 8 days of updates, we are using 7 just to be safe.
cve.url.modified.validfordays=7
# the path to the modified nvd cve xml file.
cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
cve.startyear=2014
cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
# the URL for searching Nexus for SHA-1 hashes and whether it's enabled
analyzer.nexus.enabled=true
analyzer.nexus.url=https://repository.sonatype.org/service/local/
# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
# are configured
analyzer.nexus.proxy=true

View File

@@ -0,0 +1 @@
proxy.port=80