From 5c836717396a951b75fadf49ba4c6be97ba0afd7 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Mon, 12 Nov 2012 13:36:44 -0500 Subject: [PATCH] general updates Former-commit-id: 9ad33356df25672ff4e9c91e8c1d456450069402 --- pom.xml | 12 ++++ .../org/codesecure/dependencycheck/App.java | 24 +++++++- .../dependencycheck/data/cpe/Index.java | 59 +++++++++++++++---- .../dependencycheck/data/nvdcve/Index.java | 53 +++++++++++++---- .../dependencycheck/utils/CliParser.java | 32 +++++++--- .../data/cpe/BaseIndexTestCase.java | 18 +++++- .../data/nvdcve/BaseIndexTestCase.java | 19 +++++- .../data/nvdcve/IndexTest.java | 4 +- .../dependencycheck/utils/SettingsTest.java | 2 +- 9 files changed, 186 insertions(+), 37 deletions(-) diff --git a/pom.xml b/pom.xml index f544f208e..ef11cc871 100644 --- a/pom.xml +++ b/pom.xml @@ -232,6 +232,18 @@ along with DependencyCheck. If not, see . org.apache.maven.plugins maven-failsafe-plugin 2.12.4 + + + + cve + ../data/cve + + + cpe + ../data/cpe + + + diff --git a/src/main/java/org/codesecure/dependencycheck/App.java b/src/main/java/org/codesecure/dependencycheck/App.java index a0b7ee8dc..0273d125b 100644 --- a/src/main/java/org/codesecure/dependencycheck/App.java +++ b/src/main/java/org/codesecure/dependencycheck/App.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.net.URLDecoder; import java.util.List; import java.util.logging.Level; import java.util.logging.LogManager; @@ -69,11 +70,32 @@ public class App { app.run(args); } + private static File getLoggingDirectory() throws IOException { + String fileName = "logs"; + String filePath = App.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + String decodedPath = URLDecoder.decode(filePath, "UTF-8"); + File exePath = new File(decodedPath); + if (!exePath.isDirectory()) { + exePath = exePath.getParentFile(); + } + File path = new File(exePath.getCanonicalFile() + File.separator + fileName); + path = new File(path.getCanonicalPath()); + return path; + } + private static void prepareLogger() { //while java doc for JUL says to use preferences api - it throws an exception... //Preferences.systemRoot().put("java.util.logging.config.file", "log.properties"); //System.getProperties().put("java.util.logging.config.file", "configuration/log.properties"); - File dir = new File("logs"); + File dir; + try { + dir = getLoggingDirectory(); + } catch (IOException ex) { + Logger.getLogger(App.class.getName()).log(Level.SEVERE, "Unable to get default logging location, " + + "using the working directory instead.", ex); + dir = new File("logs"); + } + if (!dir.exists()) { dir.mkdir(); } diff --git a/src/main/java/org/codesecure/dependencycheck/data/cpe/Index.java b/src/main/java/org/codesecure/dependencycheck/data/cpe/Index.java index 9e4fa3391..4d7354c87 100644 --- a/src/main/java/org/codesecure/dependencycheck/data/cpe/Index.java +++ b/src/main/java/org/codesecure/dependencycheck/data/cpe/Index.java @@ -75,17 +75,32 @@ public class Index extends AbstractIndex implements CachedWebDataSource { * @throws IOException is thrown if an IOException occurs. */ public Directory getDirectory() throws IOException { - String fileName = Settings.getString(Settings.KEYS.CPE_INDEX); - String filePath = Index.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - String decodedPath = URLDecoder.decode(filePath, "UTF-8"); - - File path = new File(decodedPath + File.separator + fileName); - path = new File(path.getCanonicalPath()); + File path = getDataDirectory(); Directory dir = FSDirectory.open(path); return dir; } + /** + * Retrieves the directory that the JAR file exists in so that + * we can ensure we always use a common data directory. + * + * @return the data directory for this index. + * @throws IOException is thrown if an IOException occurs of course... + */ + protected File getDataDirectory() throws IOException { + String fileName = Settings.getString(Settings.KEYS.CPE_INDEX); + String filePath = Index.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + String decodedPath = URLDecoder.decode(filePath, "UTF-8"); + File exePath = new File(decodedPath); + if (!exePath.isDirectory()) { + exePath = exePath.getParentFile(); + } + File path = new File(exePath.getCanonicalFile() + File.separator + fileName); + path = new File(path.getCanonicalPath()); + return path; + } + /** * Creates an Analyzer for the CPE Index. * @@ -158,8 +173,14 @@ public class Index extends AbstractIndex implements CachedWebDataSource { * * @param timeStamp the timestamp to write. */ - private void writeLastUpdatedPropertyFile(long timeStamp) { - String dir = Settings.getString(Settings.KEYS.CPE_INDEX); + private void writeLastUpdatedPropertyFile(long timeStamp) throws UpdateException { + String dir; + try { + dir = getDataDirectory().getCanonicalPath(); + } catch (IOException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + throw new UpdateException("Unable to locate the last updated properties file.", ex); + } File cpeProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE); Properties prop = new Properties(); prop.put(Index.LAST_UPDATED, String.valueOf(timeStamp)); @@ -198,8 +219,10 @@ public class Index extends AbstractIndex implements CachedWebDataSource { * is incorrect. * @throws DownloadFailedException is thrown if there is an error * downloading the cpe.meta data file. + * @throws UpdateException is thrown if there is an error locating the last updated + * properties file. */ - public long updateNeeded() throws MalformedURLException, DownloadFailedException { + public long updateNeeded() throws MalformedURLException, DownloadFailedException, UpdateException { long retVal = 0; long lastUpdated = 0; long currentlyPublishedDate = retrieveCurrentCPETimestampFromWeb(); @@ -207,12 +230,24 @@ public class Index extends AbstractIndex implements CachedWebDataSource { throw new DownloadFailedException("Unable to retrieve valid timestamp from cpe.meta file"); } - String dir = Settings.getString(Settings.KEYS.CPE_INDEX); - File f = new File(dir); + //String dir = Settings.getString(Settings.KEYS.CPE_INDEX); + File f; + try { + f = getDataDirectory(); //new File(dir); + } catch (IOException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + throw new UpdateException("Unable to locate last updated properties file.", ex); + } if (!f.exists()) { retVal = currentlyPublishedDate; } else { - File cpeProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE); + File cpeProp; + try { + cpeProp = new File(f.getCanonicalPath() + File.separatorChar + UPDATE_PROPERTIES_FILE); + } catch (IOException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + throw new UpdateException("Unable to find last updated properties file.", ex); + } if (!cpeProp.exists()) { retVal = currentlyPublishedDate; } else { diff --git a/src/main/java/org/codesecure/dependencycheck/data/nvdcve/Index.java b/src/main/java/org/codesecure/dependencycheck/data/nvdcve/Index.java index dad110f23..6a381dd21 100644 --- a/src/main/java/org/codesecure/dependencycheck/data/nvdcve/Index.java +++ b/src/main/java/org/codesecure/dependencycheck/data/nvdcve/Index.java @@ -67,21 +67,36 @@ public class Index extends AbstractIndex implements CachedWebDataSource { private static final String LAST_UPDATED_BASE = "lastupdated."; /** - * Returns the directory that holds the NVD CVE Index. + * Returns the directory that holds the NVD CVE Index. Note, this + * returns the path where the class or jar file exists. * * @return the Directory containing the NVD CVE Index. * @throws IOException is thrown if an IOException occurs. */ public Directory getDirectory() throws IOException { + File path = getDataDirectory(); + Directory dir = FSDirectory.open(path); + return dir; + } + + /** + * Retrieves the directory that the JAR file exists in so that + * we can ensure we always use a common data directory. + * + * @return the data directory for this index. + * @throws IOException is thrown if an IOException occurs of course... + */ + protected File getDataDirectory() throws IOException { String fileName = Settings.getString(Settings.KEYS.CVE_INDEX); String filePath = Index.class.getProtectionDomain().getCodeSource().getLocation().getPath(); String decodedPath = URLDecoder.decode(filePath, "UTF-8"); - - File path = new File(decodedPath + File.separator + fileName); + File exePath = new File(decodedPath); + if (!exePath.isDirectory()) { + exePath = exePath.getParentFile(); + } + File path = new File(exePath.getCanonicalFile() + File.separator + fileName); path = new File(path.getCanonicalPath()); - Directory dir = FSDirectory.open(path); - - return dir; + return path; } /** @@ -171,8 +186,14 @@ public class Index extends AbstractIndex implements CachedWebDataSource { * * @param timeStamp the timestamp to write. */ - private void writeLastUpdatedPropertyFile(Map updated) { - String dir = Settings.getString(Settings.KEYS.CVE_INDEX); + private void writeLastUpdatedPropertyFile(Map updated) throws UpdateException { + String dir; + try { + dir = getDataDirectory().getCanonicalPath(); + } catch (IOException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + throw new UpdateException("Unable to locate last updated properties file.", ex); + } File cveProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE); Properties prop = new Properties(); @@ -187,8 +208,10 @@ public class Index extends AbstractIndex implements CachedWebDataSource { prop.store(out, dir); } catch (FileNotFoundException ex) { Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + throw new UpdateException("Unable to find last updated properties file.", ex); } catch (IOException ex) { Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + throw new UpdateException("Unable to update last updated properties file.", ex); } finally { try { os.flush(); @@ -212,10 +235,11 @@ public class Index extends AbstractIndex implements CachedWebDataSource { * @return the NvdCveUrl of the files that need to be updated. * @throws MalformedURLException is thrown if the URL for the NVD CVE Meta * data is incorrect. - * @throws DownloadFailedException is thrown if there is an error + * @throws DownloadFailedException is thrown if there is an error. * downloading the nvd cve download data file. + * @throws UpdateException Is thrown if there is an issue with the last updated properties file. */ - public Map updateNeeded() throws MalformedURLException, DownloadFailedException { + public Map updateNeeded() throws MalformedURLException, DownloadFailedException, UpdateException { Map currentlyPublished; try { @@ -227,7 +251,14 @@ public class Index extends AbstractIndex implements CachedWebDataSource { if (currentlyPublished == null) { throw new DownloadFailedException("Unable to retrieve valid timestamp from nvd cve downloads page"); } - String dir = Settings.getString(Settings.KEYS.CVE_INDEX); + String dir; + try { + dir = getDataDirectory().getCanonicalPath(); + } catch (IOException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + throw new UpdateException("Unable to locate last updated properties file.", ex); + } + File f = new File(dir); if (f.exists()) { File cveProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE); diff --git a/src/main/java/org/codesecure/dependencycheck/utils/CliParser.java b/src/main/java/org/codesecure/dependencycheck/utils/CliParser.java index 9175f9091..6eedcb4be 100644 --- a/src/main/java/org/codesecure/dependencycheck/utils/CliParser.java +++ b/src/main/java/org/codesecure/dependencycheck/utils/CliParser.java @@ -93,17 +93,20 @@ public final class CliParser { 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."); + 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."); + 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."); + throw new ParseException("Scan cannot be run without specifying an application " + + "name via the 'app' argument."); } } } @@ -160,15 +163,25 @@ public final class CliParser { 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 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 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 load = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.CPE).withDescription("load the CPE xml file.").create(ArgumentName.CPE_SHORT); + Option load = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.CPE) + .withDescription("load the CPE xml file.") + .create(ArgumentName.CPE_SHORT); - Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.PROP).withDescription("a property file to load.").create(ArgumentName.PROP_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 out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ArgumentName.OUT) + .withDescription("the folder to write reports to.") + .create(ArgumentName.OUT_SHORT); //TODO add the ability to load a properties file to override the defaults... @@ -237,7 +250,8 @@ public final class CliParser { + "using the -p 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 cconnection timeout (in milliseconds) to use" + nl + "\t\t\t when downloading resources."; + + nl + " " + Settings.KEYS.CONNECTION_TIMEOUT + "\t the cconnection timeout (in milliseconds) to use" + + nl + "\t\t\t when downloading resources."; } formatter.printHelp(Settings.getString("application.name", "DependencyCheck"), diff --git a/src/test/java/org/codesecure/dependencycheck/data/cpe/BaseIndexTestCase.java b/src/test/java/org/codesecure/dependencycheck/data/cpe/BaseIndexTestCase.java index 2f13f5daa..96bee0fb5 100644 --- a/src/test/java/org/codesecure/dependencycheck/data/cpe/BaseIndexTestCase.java +++ b/src/test/java/org/codesecure/dependencycheck/data/cpe/BaseIndexTestCase.java @@ -9,6 +9,8 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URLDecoder; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import junit.framework.TestCase; @@ -30,8 +32,22 @@ public abstract class BaseIndexTestCase extends TestCase { ensureIndexExists(); } + protected static File getDataDirectory() throws IOException { + String fileName = Settings.getString(Settings.KEYS.CPE_INDEX); + String filePath = BaseIndexTestCase.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + String decodedPath = URLDecoder.decode(filePath, "UTF-8"); + File exePath = new File(decodedPath); + if (!exePath.isDirectory()) { + exePath = exePath.getParentFile(); + } + File path = new File(exePath.getCanonicalFile() + File.separator + fileName); + path = new File(path.getCanonicalPath()); + return path; + } + public static void ensureIndexExists() throws Exception { - String indexPath = Settings.getString(Settings.KEYS.CPE_INDEX); + //String indexPath = Settings.getString(Settings.KEYS.CPE_INDEX); + String indexPath = getDataDirectory().getCanonicalPath(); java.io.File f = new File(indexPath); if (!f.exists()) { f.mkdirs(); diff --git a/src/test/java/org/codesecure/dependencycheck/data/nvdcve/BaseIndexTestCase.java b/src/test/java/org/codesecure/dependencycheck/data/nvdcve/BaseIndexTestCase.java index 3efbc6aa6..1898b15d3 100644 --- a/src/test/java/org/codesecure/dependencycheck/data/nvdcve/BaseIndexTestCase.java +++ b/src/test/java/org/codesecure/dependencycheck/data/nvdcve/BaseIndexTestCase.java @@ -10,6 +10,8 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URLDecoder; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import junit.framework.TestCase; @@ -31,8 +33,23 @@ public abstract class BaseIndexTestCase extends TestCase { ensureIndexExists(); } + + protected static File getDataDirectory() throws IOException { + String fileName = Settings.getString(Settings.KEYS.CVE_INDEX); + String filePath = BaseIndexTestCase.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + String decodedPath = URLDecoder.decode(filePath, "UTF-8"); + File exePath = new File(decodedPath); + if (!exePath.isDirectory()) { + exePath = exePath.getParentFile(); + } + File path = new File(exePath.getCanonicalFile() + File.separator + fileName); + path = new File(path.getCanonicalPath()); + return path; + } + public static void ensureIndexExists() throws Exception { - String indexPath = Settings.getString(Settings.KEYS.CVE_INDEX); + //String indexPath = Settings.getString(Settings.KEYS.CVE_INDEX); + String indexPath = getDataDirectory().getCanonicalPath(); java.io.File f = new File(indexPath); if (!f.exists()) { f.mkdirs(); diff --git a/src/test/java/org/codesecure/dependencycheck/data/nvdcve/IndexTest.java b/src/test/java/org/codesecure/dependencycheck/data/nvdcve/IndexTest.java index 02c2a0b4b..135c63cdb 100644 --- a/src/test/java/org/codesecure/dependencycheck/data/nvdcve/IndexTest.java +++ b/src/test/java/org/codesecure/dependencycheck/data/nvdcve/IndexTest.java @@ -45,6 +45,8 @@ public class IndexTest extends BaseIndexTestCase { Index instance = new Index(); String exp = File.separatorChar + "target" + File.separatorChar + "data" + File.separatorChar + "cve"; Directory result = instance.getDirectory(); - assertTrue(result.toString().contains(exp)); + + assertTrue("Recieved '" + result.toString() + "' and excpected '" + exp + "'.", + result.toString().contains(exp)); } } diff --git a/src/test/java/org/codesecure/dependencycheck/utils/SettingsTest.java b/src/test/java/org/codesecure/dependencycheck/utils/SettingsTest.java index 4edcd7032..8f2e5a6fa 100644 --- a/src/test/java/org/codesecure/dependencycheck/utils/SettingsTest.java +++ b/src/test/java/org/codesecure/dependencycheck/utils/SettingsTest.java @@ -38,7 +38,7 @@ public class SettingsTest extends TestCase { public void testGetString() { System.out.println("getString"); String key = Settings.KEYS.CPE_INDEX; - String expResult = "target/data/cpe"; + String expResult = "../data/cpe"; String result = Settings.getString(key); assertTrue(result.endsWith(expResult)); }