diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/xml/DatabaseUpdater.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/xml/DatabaseUpdater.java
index a1d9a9823..38256e4bb 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/xml/DatabaseUpdater.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/xml/DatabaseUpdater.java
@@ -88,6 +88,11 @@ public class DatabaseUpdater implements CachedWebDataSource {
*/
private Index cpeIndex = null;
+ public DatabaseUpdater() {
+ batchUpdateMode = !Settings.getString(Settings.KEYS.BATCH_UPDATE_URL, "").isEmpty();
+ doBatchUpdate = false;
+ }
+
/**
*
Downloads the latest NVD CVE XML file from the web and imports it into
* the current CVE Database.
@@ -95,6 +100,7 @@ public class DatabaseUpdater implements CachedWebDataSource {
* @throws UpdateException is thrown if there is an error updating the
* database
*/
+ @Override
public void update() throws UpdateException {
try {
final Map update = updateNeeded();
@@ -111,6 +117,15 @@ public class DatabaseUpdater implements CachedWebDataSource {
if (maxUpdates > 0) {
openDataStores();
}
+
+ if (isBatchUpdateMode() && isDoBatchUpdate()) {
+ try {
+ performBatchUpdate();
+ } catch (IOException ex) {
+ throw new UpdateException("Unable to perform batch update", ex);
+ }
+ }
+
int count = 0;
for (NvdCveUrl cve : update.values()) {
@@ -126,11 +141,11 @@ public class DatabaseUpdater implements CachedWebDataSource {
"Downloading {0}", cve.getUrl());
outputPath = File.createTempFile("cve" + cve.getId() + "_", ".xml");
- Downloader.fetchFile(url, outputPath, false);
+ Downloader.fetchFile(url, outputPath);
url = new URL(cve.getOldSchemaVersionUrl());
outputPath12 = File.createTempFile("cve_1_2_" + cve.getId() + "_", ".xml");
- Downloader.fetchFile(url, outputPath12, false);
+ Downloader.fetchFile(url, outputPath12);
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.INFO,
"Processing {0}", cve.getUrl());
@@ -203,8 +218,8 @@ public class DatabaseUpdater implements CachedWebDataSource {
* @throws ParserConfigurationException is thrown if there is a parser
* configuration exception
* @throws SAXException is thrown if there is a SAXException
- * @throws IOException is thrown if there is a ioexception
- * @throws SQLException is thrown if there is a sql exception
+ * @throws IOException is thrown if there is a IO Exception
+ * @throws SQLException is thrown if there is a SQL exception
* @throws DatabaseException is thrown if there is a database exception
* @throws ClassNotFoundException thrown if the h2 database driver cannot be
* loaded
@@ -381,17 +396,25 @@ public class DatabaseUpdater implements CachedWebDataSource {
if (currentlyPublished == null) {
throw new DownloadFailedException("Unable to retrieve valid timestamp from nvd cve downloads page");
}
- String dir;
- try {
- dir = CveDB.getDataDirectory().getCanonicalPath();
- } catch (IOException ex) {
- Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, "CveDB data directory doesn't exist?", ex);
- throw new UpdateException("Unable to locate last updated properties file.", ex);
- }
- final File f = new File(dir);
- if (f.exists()) {
- final File cveProp = new File(dir, UPDATE_PROPERTIES_FILE);
+ final File cpeDataDirectory;
+ try {
+ cpeDataDirectory = CveDB.getDataDirectory();
+ } catch (IOException ex) {
+ String msg;
+ try {
+ msg = String.format("Unable to create the CVE Data Directory '%s'",
+ Settings.getFile(Settings.KEYS.CVE_DATA_DIRECTORY).getCanonicalPath());
+ } catch (IOException ex1) {
+ msg = String.format("Unable to create the CVE Data Directory, this is likely a configuration issue: '%s%s%s'",
+ Settings.getString(Settings.KEYS.DATA_DIRECTORY, ""),
+ File.separator,
+ Settings.getString(Settings.KEYS.CVE_DATA_DIRECTORY, ""));
+ }
+ throw new UpdateException(msg, ex);
+ }
+ if (cpeDataDirectory.exists()) {
+ final File cveProp = new File(cpeDataDirectory, UPDATE_PROPERTIES_FILE);
if (cveProp.exists()) {
final Properties prop = new Properties();
InputStream is = null;
@@ -416,15 +439,10 @@ public class DatabaseUpdater implements CachedWebDataSource {
}
}
if (deleteAndRecreate) {
- Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.INFO, "The database version is old. Rebuilding the database.");
is.close();
- //this is an old version of the lucene index - just delete it
- FileUtils.delete(f);
-
- //this importer also updates the CPE index and it is also using an old version
- final Index cpeId = new Index();
- final File cpeDir = cpeId.getDataDirectory();
- FileUtils.delete(cpeDir);
+ is = null;
+ deleteExistingData();
+ setDoBatchUpdate(isBatchUpdateMode());
return currentlyPublished;
}
@@ -435,11 +453,19 @@ public class DatabaseUpdater implements CachedWebDataSource {
final int end = Calendar.getInstance().get(Calendar.YEAR);
if (lastUpdated == currentlyPublished.get(MODIFIED).timestamp) {
currentlyPublished.clear(); //we don't need to update anything.
+ setDoBatchUpdate(batchUpdateMode);
} else if (withinRange(lastUpdated, now.getTime(), days)) {
currentlyPublished.get(MODIFIED).setNeedsUpdate(true);
- for (int i = start; i <= end; i++) {
- currentlyPublished.get(String.valueOf(i)).setNeedsUpdate(false);
+ if (isBatchUpdateMode()) {
+ setDoBatchUpdate(false);
+ } else {
+ for (int i = start; i <= end; i++) {
+ currentlyPublished.get(String.valueOf(i)).setNeedsUpdate(false);
+ }
}
+ } else if (isBatchUpdateMode()) {
+ currentlyPublished.get(MODIFIED).setNeedsUpdate(true);
+ setDoBatchUpdate(true);
} else { //we figure out which of the several XML files need to be downloaded.
currentlyPublished.get(MODIFIED).setNeedsUpdate(false);
for (int i = start; i <= end; i++) {
@@ -492,6 +518,49 @@ public class DatabaseUpdater implements CachedWebDataSource {
final double differenceInDays = (compareTo - date) / 1000.0 / 60.0 / 60.0 / 24.0;
return differenceInDays < range;
}
+ /**
+ * Indicates whether or not the updates are using a batch update mode or
+ * not.
+ */
+ private boolean batchUpdateMode;
+
+ /**
+ * Get the value of batchUpdateMode.
+ *
+ * @return the value of batchUpdateMode
+ */
+ protected boolean isBatchUpdateMode() {
+ return batchUpdateMode;
+ }
+
+ /**
+ * Set the value of batchUpdateMode.
+ *
+ * @param batchUpdateMode new value of batchUpdateMode
+ */
+ protected void setBatchUpdateMode(boolean batchUpdateMode) {
+ this.batchUpdateMode = batchUpdateMode;
+ }
+ //flag indicating whether or not the batch update should be performed.
+ protected boolean doBatchUpdate;
+
+ /**
+ * Get the value of doBatchUpdate
+ *
+ * @return the value of doBatchUpdate
+ */
+ protected boolean isDoBatchUpdate() {
+ return doBatchUpdate;
+ }
+
+ /**
+ * Set the value of doBatchUpdate
+ *
+ * @param doBatchUpdate new value of doBatchUpdate
+ */
+ protected void setDoBatchUpdate(boolean doBatchUpdate) {
+ this.doBatchUpdate = doBatchUpdate;
+ }
/**
* Retrieves the timestamps from the NVD CVE meta data file.
@@ -520,18 +589,21 @@ public class DatabaseUpdater implements CachedWebDataSource {
item.timestamp = Downloader.getLastModified(new URL(retrieveUrl));
map.put(MODIFIED, item);
- final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR);
- final int end = Calendar.getInstance().get(Calendar.YEAR);
- final String baseUrl20 = Settings.getString(Settings.KEYS.CVE_SCHEMA_2_0);
- final String baseUrl12 = Settings.getString(Settings.KEYS.CVE_SCHEMA_1_2);
- for (int i = start; i <= end; i++) {
- retrieveUrl = String.format(baseUrl20, i);
- item = new NvdCveUrl();
- item.setId(Integer.toString(i));
- item.setUrl(retrieveUrl);
- item.setOldSchemaVersionUrl(String.format(baseUrl12, i));
- item.setTimestamp(Downloader.getLastModified(new URL(retrieveUrl)));
- map.put(item.id, item);
+ //only add these urls if we are not in batch mode
+ if (!isBatchUpdateMode()) {
+ final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR);
+ final int end = Calendar.getInstance().get(Calendar.YEAR);
+ final String baseUrl20 = Settings.getString(Settings.KEYS.CVE_SCHEMA_2_0);
+ final String baseUrl12 = Settings.getString(Settings.KEYS.CVE_SCHEMA_1_2);
+ for (int i = start; i <= end; i++) {
+ retrieveUrl = String.format(baseUrl20, i);
+ item = new NvdCveUrl();
+ item.setId(Integer.toString(i));
+ item.setUrl(retrieveUrl);
+ item.setOldSchemaVersionUrl(String.format(baseUrl12, i));
+ item.setTimestamp(Downloader.getLastModified(new URL(retrieveUrl)));
+ map.put(item.id, item);
+ }
}
return map;
}
@@ -550,6 +622,33 @@ public class DatabaseUpdater implements CachedWebDataSource {
}
}
+ /**
+ * Deletes the existing data directories.
+ *
+ * @throws IOException thrown if the directory cannot be deleted
+ */
+ private void deleteExistingData() throws IOException {
+ Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.INFO, "The database version is old. Rebuilding the database.");
+
+ final File cveDir = CveDB.getDataDirectory();
+ FileUtils.delete(cveDir);
+
+ final File cpeDir = Index.getDataDirectory();
+ FileUtils.delete(cpeDir);
+ }
+
+ private void performBatchUpdate() throws IOException {
+ if (batchUpdateMode && doBatchUpdate) {
+ deleteExistingData();
+ String batchSrc = Settings.getString(Settings.KEYS.BATCH_UPDATE_URL);
+ File dataDirectory = CveDB.getDataDirectory().getParentFile();
+ URL batchUrl = new URL(batchSrc);
+ File tmp = File.createTempFile("batch_", ".zip");
+ Downloader.fetchFile(batchUrl, tmp);
+ FileUtils.extractFiles(tmp, dataDirectory);
+ }
+ }
+
/**
* A pojo that contains the Url and timestamp of the current NvdCve XML
* files.