From a9cf6b595d4a03d4250684538485ba33aa73b1d7 Mon Sep 17 00:00:00 2001
From: Jeremy Long
Date: Mon, 17 Sep 2012 22:22:11 -0400
Subject: [PATCH] prepared for CVE data by refactoring CPE code
---
.../dependencycheck/data/AbstractIndex.java | 196 +++++++++
.../dependencycheck/data/WebDataIndex.java | 45 +++
.../dependencycheck/data/cpe/CPEQuery.java | 84 ++--
.../dependencycheck/data/cpe/Index.java | 47 +--
.../dependencycheck/data/cpe/Indexer.java | 5 +
.../data/cpe/xml/Importer.java | 4 +-
.../dependencycheck/data/cve/Entry.java | 380 ++++++++++++++++++
.../dependencycheck/data/cve/Fields.java | 53 +++
.../dependencycheck/data/cve/Index.java | 255 ++++++++++++
.../dependencycheck/data/cve/Indexer.java | 100 +++++
.../data/cve/package-info.java | 12 +
.../data/cve/xml/CVEHandler.java | 350 ++++++++++++++++
.../data/cve/xml/EntrySaveDelegate.java | 42 ++
.../data/cve/xml/Importer.java | 76 ++++
.../data/cve/xml/package-info.java | 12 +
.../dependencycheck/scanner/Dependency.java | 18 +-
.../dependencycheck/scanner/JarAnalyzer.java | 60 +--
.../dependencycheck/data/cpe/IndexTest.java | 11 +-
.../data/cpe/IndexTestCase.java | 33 --
.../reporting/ReportGeneratorTest.java | 16 +-
.../scanner/JarAnalyzerTest.java | 2 +-
21 files changed, 1614 insertions(+), 187 deletions(-)
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/AbstractIndex.java
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/WebDataIndex.java
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/cve/Entry.java
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/cve/Fields.java
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/cve/Index.java
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/cve/Indexer.java
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/cve/package-info.java
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/cve/xml/CVEHandler.java
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/cve/xml/EntrySaveDelegate.java
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/cve/xml/Importer.java
create mode 100644 src/main/java/org/codesecure/dependencycheck/data/cve/xml/package-info.java
delete mode 100644 src/test/java/org/codesecure/dependencycheck/data/cpe/IndexTestCase.java
diff --git a/src/main/java/org/codesecure/dependencycheck/data/AbstractIndex.java b/src/main/java/org/codesecure/dependencycheck/data/AbstractIndex.java
new file mode 100644
index 000000000..4d9a9c97c
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/AbstractIndex.java
@@ -0,0 +1,196 @@
+package org.codesecure.dependencycheck.data;
+/*
+ * This file is part of DependencyCheck.
+ *
+ * DependencyCheck is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DependencyCheck is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.LockObtainFailedException;
+import org.apache.lucene.util.Version;
+
+/**
+ * The base Index for other index objects. Implements the open and close methods.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public abstract class AbstractIndex {
+
+ /**
+ * The Lucene directory containing the index.
+ */
+ protected Directory directory = null;
+ /**
+ * The IndexWriter for the Lucene index.
+ */
+ protected IndexWriter indexWriter = null;
+ /**
+ * The Lucene IndexReader.
+ */
+ private IndexReader indexReader = null;
+ /**
+ * The Lucene IndexSearcher.
+ */
+ private IndexSearcher indexSearcher = null;
+
+ /**
+ * The Lucene Analyzer.
+ */
+ private Analyzer analyzer = null;
+
+ /**
+ * Indicates whether or not the Lucene Index is open.
+ */
+ private boolean indexOpen = false;
+
+ /**
+ * Opens the CPE Index.
+ * @throws IOException is thrown if an IOException occurs opening the index.
+ */
+ public void open() throws IOException {
+ directory = this.getDirectory();
+ analyzer = this.getAnalyzer(); //new StandardAnalyzer(Version.LUCENE_35);
+ indexOpen = true;
+ }
+
+ /**
+ * Closes the CPE Index.
+ */
+ public void close() {
+ if (indexWriter != null) {
+ try {
+ indexWriter.commit();
+ } catch (CorruptIndexException ex) {
+ Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (IOException ex) {
+ Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ try {
+ indexWriter.close(true);
+ } catch (CorruptIndexException ex) {
+ Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (IOException ex) {
+ Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
+ } finally {
+ indexWriter = null;
+ }
+ }
+ if (indexSearcher != null) {
+ try {
+ indexSearcher.close();
+ } catch (IOException ex) {
+ Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
+ } finally {
+ indexSearcher = null;
+ }
+ }
+
+ if (analyzer != null) {
+ analyzer.close();
+ analyzer = null;
+ }
+ try {
+ directory.close();
+ } catch (IOException ex) {
+ Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
+ } finally {
+ directory = null;
+ }
+ indexOpen = false;
+ }
+
+ /**
+ * Returns the status of the data source - is the index open.
+ * @return true or false.
+ */
+ public boolean isOpen() {
+ return indexOpen;
+ }
+ /**
+ * Opens the Lucene Index Writer.
+ *
+ * @throws CorruptIndexException is thrown if the Lucene index is corrupt.
+ * @throws IOException is thrown if an IOException occurs opening the index.
+ */
+ public void openIndexWriter() throws CorruptIndexException, IOException {
+ if (!isOpen()) {
+ open();
+ }
+ IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_35, analyzer);
+ indexWriter = new IndexWriter(directory, conf);
+ }
+
+ /**
+ * Retrieves the IndexWriter for the Lucene Index.
+ *
+ * @return an IndexWriter.
+ * @throws CorruptIndexException is thrown if the Lucene Index is corrupt.
+ * @throws LockObtainFailedException is thrown if there is an exception obtaining a lock on the Lucene index.
+ * @throws IOException is thrown if an IOException occurs opening the index.
+ */
+ public IndexWriter getIndexWriter() throws CorruptIndexException, LockObtainFailedException, IOException {
+ if (indexWriter == null) {
+ openIndexWriter();
+ }
+ return indexWriter;
+ }
+
+ public void openIndexReader() throws CorruptIndexException, IOException {
+ if (!isOpen()) {
+ open();
+ }
+ indexReader = IndexReader.open(directory, true);
+ }
+
+ public IndexSearcher getIndexSearcher() throws CorruptIndexException, IOException {
+ if (indexReader == null) {
+ openIndexReader();
+ }
+ if (indexSearcher == null) {
+ indexSearcher = new IndexSearcher(indexReader);
+ }
+ return indexSearcher;
+ }
+
+ public Analyzer getAnalyzer() {
+ if (analyzer == null) {
+ analyzer = createAnalyzer();
+ }
+ return analyzer;
+ }
+
+ /**
+ * Gets the directory that contains the Lucene Index.
+ * @return a Lucene Directory.
+ * @throws IOException is thrown when an IOException occurs.
+ */
+ public abstract Directory getDirectory() throws IOException;
+ /**
+ * Creates the Lucene Analyzer used when indexing and searching the index.
+ * @return a Lucene Analyzer.
+ */
+ public abstract Analyzer createAnalyzer();
+
+}
diff --git a/src/main/java/org/codesecure/dependencycheck/data/WebDataIndex.java b/src/main/java/org/codesecure/dependencycheck/data/WebDataIndex.java
new file mode 100644
index 000000000..91da6d142
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/WebDataIndex.java
@@ -0,0 +1,45 @@
+package org.codesecure.dependencycheck.data;
+/*
+ * This file is part of DependencyCheck.
+ *
+ * DependencyCheck is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DependencyCheck is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import javax.xml.parsers.ParserConfigurationException;
+import org.xml.sax.SAXException;
+
+/**
+ * Defines an Index who's data is retrieved from the Internet. This data can
+ * be downloaded and the index updated.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public interface WebDataIndex {
+
+ /**
+ * Determines if an update to the current index is needed, if it is the new
+ * data is downloaded from the Internet and imported into the current Lucene Index.
+ *
+ * @throws MalformedURLException is thrown if the URL for the CPE is malformed.
+ * @throws ParserConfigurationException is thrown if the parser is misconfigured.
+ * @throws SAXException is thrown if there is an error parsing the CPE XML.
+ * @throws IOException is thrown if a temporary file could not be created.
+ */
+ public void updateIndexFromWeb() throws MalformedURLException, ParserConfigurationException, SAXException, IOException;
+}
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cpe/CPEQuery.java b/src/main/java/org/codesecure/dependencycheck/data/cpe/CPEQuery.java
index 4acc36e56..dbf4b98d1 100644
--- a/src/main/java/org/codesecure/dependencycheck/data/cpe/CPEQuery.java
+++ b/src/main/java/org/codesecure/dependencycheck/data/cpe/CPEQuery.java
@@ -75,29 +75,17 @@ public class CPEQuery {
*/
static final int STRING_BUILDER_BUFFER = 20;
/**
- * The Lucene IndexReader.
+ * The CPE Index.
*/
- private IndexReader indexReader = null;
+ protected Index cpe = null;
/**
* The Lucene IndexSearcher.
*/
private IndexSearcher indexSearcher = null;
- /**
- * The Lucene directory.
- */
- private Directory directory = null;
- /**
- * The Lucene Analyzer.
- */
- private Analyzer analyzer = null;
/**
* The Lucene QueryParser.
*/
private QueryParser queryParser = null;
- /**
- * Indicates whether or not the Lucene Index is open.
- */
- private boolean indexOpen = false;
/**
* Opens the data source.
@@ -105,41 +93,21 @@ public class CPEQuery {
* @throws IOException when the Lucene directory to be querried does not exist or is corrupt.
*/
public void open() throws IOException {
- directory = Index.getDirectory();
- indexReader = IndexReader.open(directory, true);
- indexSearcher = new IndexSearcher(indexReader);
- analyzer = Index.createAnalyzer(); //use the same analyzer as used when indexing
+ cpe = new Index();
+ cpe.open();
+ indexSearcher = cpe.getIndexSearcher();
+ Analyzer analyzer = cpe.getAnalyzer();
//TITLE is the default field because it contains venddor, product, and version all in one.
queryParser = new QueryParser(Version.LUCENE_35, Fields.TITLE, analyzer);
- indexOpen = true;
}
/**
* Closes the data source.
*/
public void close() {
- analyzer.close();
- analyzer = null;
queryParser = null;
- try {
- indexSearcher.close();
- } catch (IOException ex) {
- Logger.getLogger(CPEQuery.class.getName()).log(Level.SEVERE, null, ex);
- }
indexSearcher = null;
- try {
- indexReader.close();
- } catch (IOException ex) {
- Logger.getLogger(CPEQuery.class.getName()).log(Level.SEVERE, null, ex);
- }
- indexReader = null;
- try {
- directory.close();
- } catch (IOException ex) {
- Logger.getLogger(CPEQuery.class.getName()).log(Level.SEVERE, null, ex);
- }
- directory = null;
- indexOpen = false;
+ cpe.close();
}
/**
@@ -147,7 +115,7 @@ public class CPEQuery {
* @return true or false.
*/
public boolean isOpen() {
- return indexOpen;
+ return (cpe == null) ? false : cpe.isOpen();
}
/**
@@ -157,7 +125,7 @@ public class CPEQuery {
@Override
protected void finalize() throws Throwable {
super.finalize();
- if (indexOpen) {
+ if (isOpen()) {
close();
}
}
@@ -174,7 +142,7 @@ public class CPEQuery {
*/
public void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
Confidence vendorConf = Confidence.HIGH;
- Confidence titleConf = Confidence.HIGH;
+ Confidence productConf = Confidence.HIGH;
Confidence versionConf = Confidence.HIGH;
String vendors = addEvidenceWithoutDuplicateTerms("", dependency.getVendorEvidence(), vendorConf);
@@ -182,10 +150,10 @@ public class CPEQuery {
// if ("".equals(vendors)) {
// vendors = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
// }
- String titles = addEvidenceWithoutDuplicateTerms("", dependency.getTitleEvidence(), titleConf);
- ///dependency.getTitleEvidence().toString(titleConf);
-// if ("".equals(titles)) {
-// titles = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
+ String products = addEvidenceWithoutDuplicateTerms("", dependency.getProductEvidence(), productConf);
+ ///dependency.getProductEvidence().toString(productConf);
+// if ("".equals(products)) {
+// products = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
// }
String versions = addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), versionConf);
//dependency.getVersionEvidence().toString(versionConf);
@@ -196,7 +164,7 @@ public class CPEQuery {
boolean found = false;
int cnt = 0;
do {
- List entries = searchCPE(vendors, titles, versions, dependency.getTitleEvidence().getWeighting(),
+ List entries = searchCPE(vendors, products, versions, dependency.getProductEvidence().getWeighting(),
dependency.getVendorEvidence().getWeighting());
if (entries.size() > 0) {
@@ -220,10 +188,10 @@ public class CPEQuery {
}
}
if (round == 1) {
- titleConf = reduceConfidence(titleConf);
- if (dependency.getTitleEvidence().contains(titleConf)) {
- //titles += " " + dependency.getTitleEvidence().toString(titleConf);
- titles = addEvidenceWithoutDuplicateTerms(titles, dependency.getTitleEvidence(), titleConf);
+ productConf = reduceConfidence(productConf);
+ if (dependency.getProductEvidence().contains(productConf)) {
+ //products += " " + dependency.getProductEvidence().toString(productConf);
+ products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), productConf);
} else {
cnt += 1;
round += 1;
@@ -289,7 +257,7 @@ public class CPEQuery {
* with the supplied vendor, product, and version.
*
* @param vendor the text used to search the vendor field.
- * @param product the text used to search the title field.
+ * @param product the text used to search the product field.
* @param version the text used to search the version field.
* @return a list of possible CPE values.
* @throws CorruptIndexException when the Lucene index is corrupt.
@@ -309,10 +277,10 @@ public class CPEQuery {
* this data is used to add weighting factors to the search.
*
* @param vendor the text used to search the vendor field.
- * @param product the text used to search the title field.
+ * @param product the text used to search the product field.
* @param version the text used to search the version field.
* @param vendorWeightings a list of strings to use to add weighting factors to the vendor field.
- * @param productWeightings Adds a list of strings that will be used to add weighting factors to the title search.
+ * @param productWeightings Adds a list of strings that will be used to add weighting factors to the product search.
* @return a list of possible CPE values.
* @throws CorruptIndexException when the Lucene index is corrupt.
* @throws IOException when the Lucene index is not found.
@@ -347,11 +315,11 @@ public class CPEQuery {
* data is used to add weighting factors to the search string generated.
*
* @param vendor text to search the vendor field.
- * @param product text to search the title field.
+ * @param product text to search the product field.
* @param version text to search the version field.
* @param vendorWeighting a list of strings to apply to the vendor
* to boost the terms weight.
- * @param produdctWeightings a list of strings to apply to the product/title
+ * @param produdctWeightings a list of strings to apply to the product
* to boost the terms weight.
* @return the Lucene query.
*/
@@ -473,7 +441,7 @@ public class CPEQuery {
/**
* Takes a list of entries and a dependency. If the entry has terms that were
* used (i.e. this CPE entry wasn't identified because the version matched
- * but the product and title did not) then the CPE Entry is returned in a list
+ * but the product names did not) then the CPE Entry is returned in a list
* of possible CPE Entries.
*
* @param entries a list of CPE entries.
@@ -483,7 +451,7 @@ public class CPEQuery {
private List verifyEntries(final List entries, final Dependency dependency) {
List verified = new ArrayList();
for (Entry e : entries) {
- if (dependency.getTitleEvidence().containsUsedString(e.getProduct())
+ if (dependency.getProductEvidence().containsUsedString(e.getProduct())
&& dependency.getVendorEvidence().containsUsedString(e.getVendor())) {
//TODO - determine if this is right? Should we be carrying too much about the
// version at this point? Likely need to implement the versionAnalyzer....
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 ff592f3d4..795e1c588 100644
--- a/src/main/java/org/codesecure/dependencycheck/data/cpe/Index.java
+++ b/src/main/java/org/codesecure/dependencycheck/data/cpe/Index.java
@@ -44,6 +44,8 @@ import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
+import org.codesecure.dependencycheck.data.AbstractIndex;
+import org.codesecure.dependencycheck.data.WebDataIndex;
import org.codesecure.dependencycheck.utils.Downloader;
import org.codesecure.dependencycheck.utils.Settings;
import org.codesecure.dependencycheck.data.cpe.xml.Importer;
@@ -55,48 +57,17 @@ import org.xml.sax.SAXException;
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
-public class Index {
+public class Index extends AbstractIndex implements WebDataIndex {
/**
- * Te name of the properties file containing the timestamp of the last update.
+ * The name of the properties file containing the timestamp of the last update.
*/
private static final String UPDATE_PROPERTIES_FILE = "lastupdated.prop";
/**
* The properties file key for the last updated field.
*/
private static final String LAST_UPDATED = "lastupdated";
- /**
- * The Lucene directory containing the index.
- */
- protected Directory directory = null;
- /**
- * The IndexWriter for the Lucene index.
- */
- protected IndexWriter indexWriter = null;
- /**
- * Opens the CPE Index.
- * @throws IOException is thrown if an IOException occurs opening the index.
- */
- public void open() throws IOException {
- directory = Index.getDirectory();
-
- Analyzer analyzer = Index.createAnalyzer(); //new StandardAnalyzer(Version.LUCENE_35);
- IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_35, analyzer);
- indexWriter = new IndexWriter(directory, conf);
- }
-
- /**
- * Closes the CPE Index.
- *
- * @throws CorruptIndexException is thrown if the index is corrupt.
- * @throws IOException is thrown if an IOException occurs closing the index.
- */
- public void close() throws CorruptIndexException, IOException {
- indexWriter.commit();
- indexWriter.close(true);
- directory.close();
- }
/**
* Returns the directory that holds the CPE Index.
@@ -104,12 +75,12 @@ public class Index {
* @return the Directory containing the CPE Index.
* @throws IOException is thrown if an IOException occurs.
*/
- public static Directory getDirectory() throws IOException {
+ public Directory getDirectory() throws IOException {
String fileName = Settings.getString(Settings.KEYS.CPE_INDEX);
File path = new File(fileName);
- Directory directory = FSDirectory.open(path);
+ Directory dir = FSDirectory.open(path);
- return directory;
+ return dir;
}
/**
@@ -117,11 +88,11 @@ public class Index {
*
* @return the CPE Analyzer.
*/
- public static Analyzer createAnalyzer() {
+ @SuppressWarnings("unchecked")
+ public Analyzer createAnalyzer() {
Map fieldAnalyzers = new HashMap();
fieldAnalyzers.put(Fields.VERSION, new KeywordAnalyzer());
- //new WhitespaceAnalyzer(Version.LUCENE_35)); //
PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper(
new StandardAnalyzer(Version.LUCENE_35), fieldAnalyzers);
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cpe/Indexer.java b/src/main/java/org/codesecure/dependencycheck/data/cpe/Indexer.java
index e26d82c9c..5b0de7064 100644
--- a/src/main/java/org/codesecure/dependencycheck/data/cpe/Indexer.java
+++ b/src/main/java/org/codesecure/dependencycheck/data/cpe/Indexer.java
@@ -25,6 +25,10 @@ import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.FieldInfo.IndexOptions;
import org.apache.lucene.index.Term;
import org.codesecure.dependencycheck.data.LuceneUtils;
+import org.codesecure.dependencycheck.data.cpe.Entry;
+import org.codesecure.dependencycheck.data.cpe.Fields;
+import org.codesecure.dependencycheck.data.cpe.Index;
+import org.codesecure.dependencycheck.data.cpe.xml.EntrySaveDelegate;
import org.codesecure.dependencycheck.data.cpe.xml.EntrySaveDelegate;
/**
@@ -97,4 +101,5 @@ public class Indexer extends Index implements EntrySaveDelegate {
return doc;
}
+
}
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cpe/xml/Importer.java b/src/main/java/org/codesecure/dependencycheck/data/cpe/xml/Importer.java
index a90eb7d1d..54dfb0464 100644
--- a/src/main/java/org/codesecure/dependencycheck/data/cpe/xml/Importer.java
+++ b/src/main/java/org/codesecure/dependencycheck/data/cpe/xml/Importer.java
@@ -18,12 +18,12 @@ package org.codesecure.dependencycheck.data.cpe.xml;
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
+import org.codesecure.dependencycheck.data.cpe.Indexer;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
-import org.codesecure.dependencycheck.data.cpe.Indexer;
import org.xml.sax.SAXException;
/**
@@ -53,7 +53,7 @@ public class Importer {
SAXParser saxParser = factory.newSAXParser();
CPEHandler handler = new CPEHandler();
Indexer indexer = new Indexer();
- indexer.open();
+ indexer.openIndexWriter();
handler.registerSaveDelegate(indexer);
saxParser.parse(file, handler);
indexer.close();
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cve/Entry.java b/src/main/java/org/codesecure/dependencycheck/data/cve/Entry.java
new file mode 100644
index 000000000..2ec95c33b
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/cve/Entry.java
@@ -0,0 +1,380 @@
+package org.codesecure.dependencycheck.data.cve;
+/*
+ * This file is part of DependencyCheck.
+ *
+ * DependencyCheck is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DependencyCheck is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.lucene.document.Document;
+
+/**
+ * A single CVE entry from the cve.xml files downloaded from
+ * http://nvd.nist.gov/cpe.cfm.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class Entry {
+
+ /**
+ * This parse method does not fully convert a Lucene Document into a CPE Entry;
+ * it only sets the Entry.Name.
+ *
+ * @param doc a Lucene Document.
+ * @return a CPE Entry.
+ */
+ public static Entry parse(Document doc) {
+ Entry entry = new Entry();
+ try {
+ entry.setName(doc.get(Fields.NAME));
+ entry.setTitle(doc.get(Fields.TITLE));
+ } catch (UnsupportedEncodingException ex) {
+ Logger.getLogger(Entry.class.getName()).log(Level.SEVERE, null, ex);
+ entry.name = doc.get(Fields.NAME);
+ }
+// entry.vendor = doc.get(Fields.VENDOR);
+// entry.version = doc.get(Fields.VERSION);
+// //entry.revision = doc.get(Fields.REVISION);
+// entry.product = doc.get(Fields.TITLE);
+// entry.nvdId = doc.get(Fields.NVDID);
+ return entry;
+ }
+ /**
+ * The title of the CPE
+ */
+ protected String title;
+
+ /**
+ * Get the value of title
+ *
+ * @return the value of title
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * Set the value of title
+ *
+ * @param title new value of title
+ */
+ public void setTitle(String title) {
+ this.title = title;
+ }
+ /**
+ * The name of the CPE entry.
+ */
+ protected String name;
+
+ /**
+ * Get the value of name
+ *
+ * @return the value of name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Set the value of name and calls parseName to obtain the vendor:product:version:revision
+ *
+ * @param name new value of name
+ * @throws UnsupportedEncodingException should never be thrown...
+ */
+ public void setName(String name) throws UnsupportedEncodingException {
+ this.name = name;
+ parseName();
+ }
+ /**
+ * The status of the CPE Entry.
+ */
+ protected String status;
+
+ /**
+ * Get the value of status
+ *
+ * @return the value of status
+ */
+ public String getStatus() {
+ return status;
+ }
+
+ /**
+ * Set the value of status
+ *
+ * @param status new value of status
+ */
+ public void setStatus(String status) {
+ this.status = status;
+ }
+ /**
+ * The modification date of the CPE Entry.
+ */
+ protected Date modificationDate;
+
+ /**
+ * Get the value of modificationDate
+ *
+ * @return the value of modificationDate
+ */
+ public Date getModificationDate() {
+ return modificationDate;
+ }
+
+ /**
+ * Set the value of modificationDate
+ *
+ * @param modificationDate new value of modificationDate
+ */
+ public void setModificationDate(Date modificationDate) {
+ this.modificationDate = modificationDate;
+ }
+
+ /**
+ * Set the value of modificationDate
+ *
+ * Expected format: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
+ *
+ * @param modificationDate new value of modificationDate
+ * @throws ParseException is thrown when a parse exception occurs.
+ */
+ public void setModificationDate(String modificationDate) throws ParseException {
+
+ String formatStr = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
+ Date tempDate = null;
+ SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
+ sdf.setLenient(true);
+ tempDate = sdf.parse(modificationDate);
+
+ this.modificationDate = tempDate;
+ }
+ /**
+ * The nvdId.
+ */
+ protected String nvdId;
+
+ /**
+ * Get the value of nvdId
+ *
+ * @return the value of nvdId
+ */
+ public String getNvdId() {
+ return nvdId;
+ }
+
+ /**
+ * Set the value of nvdId
+ *
+ * @param nvdId new value of nvdId
+ */
+ public void setNvdId(String nvdId) {
+ this.nvdId = nvdId;
+ }
+ /**
+ * The vendor name.
+ */
+ protected String vendor;
+
+ /**
+ * Get the value of vendor
+ *
+ * @return the value of vendor
+ */
+ public String getVendor() {
+ return vendor;
+ }
+
+ /**
+ * Set the value of vendor
+ *
+ * @param vendor new value of vendor
+ */
+ public void setVendor(String vendor) {
+ this.vendor = vendor;
+ }
+ /**
+ * The product name.
+ */
+ protected String product;
+
+ /**
+ * Get the value of product
+ *
+ * @return the value of product
+ */
+ public String getProduct() {
+ return product;
+ }
+
+ /**
+ * Set the value of product
+ *
+ * @param product new value of product
+ */
+ public void setProduct(String product) {
+ this.product = product;
+ }
+ /**
+ * The product version.
+ */
+ protected String version;
+
+ /**
+ * Get the value of version
+ *
+ * @return the value of version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * Set the value of version
+ *
+ * @param version new value of version
+ */
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ /**
+ * The product revision.
+ */
+ protected String revision;
+
+ /**
+ * Get the value of revision
+ *
+ * @return the value of revision
+ */
+ public String getRevision() {
+ return revision;
+ }
+
+ /**
+ * Set the value of revision
+ *
+ * @param revision new value of revision
+ */
+ public void setRevision(String revision) {
+ this.revision = revision;
+ }
+ /**
+ * If the CPE Entry is well known (i.e. based off a hash)
+ */
+ protected boolean wellKnown = false;
+
+ /**
+ * Get the value of wellKnown
+ *
+ * @return the value of wellKnown
+ */
+ public boolean isWellKnown() {
+ return wellKnown;
+ }
+
+ /**
+ * Set the value of wellKnown
+ *
+ * @param wellKnown new value of wellKnown
+ */
+ public void setWellKnown(boolean wellKnown) {
+ this.wellKnown = wellKnown;
+ }
+ /**
+ * The search score.
+ */
+ protected float searchScore;
+
+ /**
+ * Get the value of searchScore
+ *
+ * @return the value of searchScore
+ */
+ public float getSearchScore() {
+ return searchScore;
+ }
+
+ /**
+ * Set the value of searchScore
+ *
+ * @param searchScore new value of searchScore
+ */
+ public void setSearchScore(float searchScore) {
+ this.searchScore = searchScore;
+ }
+
+ /**
+ * Parses a name attribute value, from the cpe.xml, into its
+ * corresponding parts: vendor, product, version, revision.
+ * Example:
+ * cpe:/a:apache:struts:1.1:rc2
+ *
+ * Results in:
+ *
+ * - Vendor: apache
+ * - Product: struts
+ * - Version: 1.1
+ * - Revision: rc2
+ *
+ *
+ * @throws UnsupportedEncodingException should never be thrown...
+ */
+ private void parseName() throws UnsupportedEncodingException {
+ if (name != null && name.length() > 7) {
+ String[] data = name.substring(7).split(":");
+ if (data.length >= 1) {
+ vendor = URLDecoder.decode(data[0], "UTF-8");
+ if (data.length >= 2) {
+ product = URLDecoder.decode(data[1], "UTF-8");
+ if (data.length >= 3) {
+ version = URLDecoder.decode(data[2], "UTF-8");
+ if (data.length >= 4) {
+ revision = URLDecoder.decode(data[3], "UTF-8");
+ }
+ //ignore edition and language fields.. don't really see them used in the a:
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Entry other = (Entry) obj;
+ if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 83 * hash + (this.name != null ? this.name.hashCode() : 0);
+ return hash;
+ }
+}
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cve/Fields.java b/src/main/java/org/codesecure/dependencycheck/data/cve/Fields.java
new file mode 100644
index 000000000..eb0082395
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/cve/Fields.java
@@ -0,0 +1,53 @@
+package org.codesecure.dependencycheck.data.cve;
+/*
+ * This file is part of DependencyCheck.
+ *
+ * DependencyCheck is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DependencyCheck is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+
+/**
+ * Fields is a collection of field names used within the Lucene index for CPE
+ * entries.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public abstract class Fields {
+ /**
+ * The key for the name field.
+ */
+ public static final String NAME = "name";
+ /**
+ * The key for the vendor field.
+ */
+ public static final String VENDOR = "vendor";
+ /**
+ * The key for the version field.
+ */
+ public static final String VERSION = "version";
+ //public static final String REVISION = "revision";
+ /**
+ * The key for the product field.
+ */
+ public static final String PRODUCT = "product";
+ /**
+ * The key for the title field. This is a field combining vendor, product, and version.
+ */
+ public static final String TITLE = "title";
+ /**
+ * The key for the nvdId field.
+ */
+ public static final String NVDID = "nvdid";
+}
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cve/Index.java b/src/main/java/org/codesecure/dependencycheck/data/cve/Index.java
new file mode 100644
index 000000000..9bed884bf
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/cve/Index.java
@@ -0,0 +1,255 @@
+package org.codesecure.dependencycheck.data.cve;
+/*
+ * This file is part of DependencyCheck.
+ *
+ * DependencyCheck is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DependencyCheck is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.parsers.ParserConfigurationException;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.KeywordAnalyzer;
+import org.apache.lucene.analysis.PerFieldAnalyzerWrapper;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.util.Version;
+import org.codesecure.dependencycheck.data.AbstractIndex;
+import org.codesecure.dependencycheck.data.WebDataIndex;
+import org.codesecure.dependencycheck.utils.Downloader;
+import org.codesecure.dependencycheck.utils.Settings;
+import org.codesecure.dependencycheck.data.cpe.xml.Importer;
+import org.codesecure.dependencycheck.utils.DownloadFailedException;
+import org.xml.sax.SAXException;
+
+/**
+ * The Index class is used to utilize and maintain the CVE Index.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class Index extends AbstractIndex implements WebDataIndex {
+
+ /**
+ * The name of the properties file containing the timestamp of the last update.
+ */
+ private static final String UPDATE_PROPERTIES_FILE = "lastupdated.prop";
+ /**
+ * The properties file key for the last updated field.
+ */
+ private static final String LAST_UPDATED = "lastupdated";
+
+
+ /**
+ * Returns the directory that holds the CPE Index.
+ *
+ * @return the Directory containing the CPE Index.
+ * @throws IOException is thrown if an IOException occurs.
+ */
+ public Directory getDirectory() throws IOException {
+ String fileName = Settings.getString(Settings.KEYS.CVE_INDEX);
+ File path = new File(fileName);
+ Directory dir = FSDirectory.open(path);
+
+ return dir;
+ }
+
+ /**
+ * Creates an Analyzer for the CPE Index.
+ *
+ * @return the CPE Analyzer.
+ */
+ @SuppressWarnings("unchecked")
+ public Analyzer createAnalyzer() {
+ Map fieldAnalyzers = new HashMap();
+
+ fieldAnalyzers.put(Fields.VERSION, new KeywordAnalyzer());
+
+ PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper(
+ new StandardAnalyzer(Version.LUCENE_35), fieldAnalyzers);
+
+ return wrapper;
+ }
+
+ /**
+ * Downloads the latest CPE XML file from the web and imports it into
+ * the current CPE Index.
+ *
+ * @throws MalformedURLException is thrown if the URL for the CPE is malformed.
+ * @throws ParserConfigurationException is thrown if the parser is misconfigured.
+ * @throws SAXException is thrown if there is an error parsing the CPE XML.
+ * @throws IOException is thrown if a temporary file could not be created.
+ */
+ public void updateIndexFromWeb() throws MalformedURLException, ParserConfigurationException, SAXException, IOException {
+ long timeStamp = updateNeeded();
+ if (timeStamp > 0) {
+ URL url = new URL(Settings.getString(Settings.KEYS.CPE_URL));
+ File outputPath = null;
+ try {
+ outputPath = File.createTempFile("cve", ".xml");
+ Downloader.fetchFile(url, outputPath, true);
+ Importer.importXML(outputPath.toString());
+ writeLastUpdatedPropertyFile(timeStamp);
+ } catch (DownloadFailedException ex) {
+ Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
+ } finally {
+ try {
+ if (outputPath != null && outputPath.exists()) {
+ outputPath.delete();
+ }
+ } finally {
+ if (outputPath != null && outputPath.exists()) {
+ outputPath.deleteOnExit();
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Writes a properties file containing the last updated date to the CPE directory.
+ * @param timeStamp the timestamp to write.
+ */
+ private void writeLastUpdatedPropertyFile(long timeStamp) {
+ String dir = Settings.getString(Settings.KEYS.CPE_INDEX);
+ File cpeProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE);
+ Properties prop = new Properties();
+ prop.put(Index.LAST_UPDATED, String.valueOf(timeStamp));
+ OutputStream os = null;
+ try {
+ os = new FileOutputStream(cpeProp);
+ OutputStreamWriter out = new OutputStreamWriter(os);
+ prop.store(out, dir);
+ } catch (FileNotFoundException ex) {
+ Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (IOException ex) {
+ Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
+ } finally {
+ try {
+ os.flush();
+ } catch (IOException ex) {
+ Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ try {
+ os.close();
+ } catch (IOException ex) {
+ Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ }
+
+ /**
+ * Determines if the index needs to be updated. This is done by fetching the
+ * cpe.meta data and checking the lastModifiedDate. If the CPE data needs to
+ * be refreshed this method will return the timestamp of the new CPE. If an
+ * update is not required this function will return 0.
+ *
+ * @return the timestamp of the currently published CPE.xml if the index needs to be updated, otherwise returns 0..
+ * @throws MalformedURLException is thrown if the URL for the CPE Meta data is incorrect.
+ * @throws DownloadFailedException is thrown if there is an error downloading the cpe.meta data file.
+ */
+ public long updateNeeded() throws MalformedURLException, DownloadFailedException {
+ long retVal = 0;
+ long lastUpdated = 0;
+ long currentlyPublishedDate = retrieveCurrentCPETimestampFromWeb();
+ if (currentlyPublishedDate == 0) {
+ 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);
+ if (!f.exists()) {
+ retVal = currentlyPublishedDate;
+ } else {
+ File cpeProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE);
+ if (!cpeProp.exists()) {
+ retVal = currentlyPublishedDate;
+ } else {
+ Properties prop = new Properties();
+ InputStream is = null;
+ try {
+ is = new FileInputStream(cpeProp);
+ prop.load(is);
+ lastUpdated = Long.parseLong(prop.getProperty(Index.LAST_UPDATED));
+ } catch (FileNotFoundException ex) {
+ Logger.getLogger(Index.class.getName()).log(Level.FINEST, null, ex);
+ } catch (IOException ex) {
+ Logger.getLogger(Index.class.getName()).log(Level.FINEST, null, ex);
+ } catch (NumberFormatException ex) {
+ Logger.getLogger(Index.class.getName()).log(Level.FINEST, null, ex);
+ }
+ if (currentlyPublishedDate > lastUpdated) {
+ retVal = currentlyPublishedDate;
+ }
+ }
+ }
+ return retVal;
+ }
+
+ /**
+ * Retrieves the timestamp from the CPE meta data file.
+ * @return the timestamp from the currently published cpe.meta.
+ * @throws MalformedURLException is thrown if the URL for the CPE Meta data is incorrect.
+ * @throws DownloadFailedException is thrown if there is an error downloading the cpe.meta data file.
+ */
+ private long retrieveCurrentCPETimestampFromWeb() throws MalformedURLException, DownloadFailedException {
+ long timestamp = 0;
+ File tmp = null;
+ InputStream is = null;
+ try {
+ tmp = File.createTempFile("cpe", "meta");
+ URL url = new URL(Settings.getString(Settings.KEYS.CPE_META_URL));
+ Downloader.fetchFile(url, tmp);
+ Properties prop = new Properties();
+ is = new FileInputStream(tmp);
+ prop.load(is);
+ timestamp = Long.parseLong(prop.getProperty("lastModifiedDate"));
+ } catch (IOException ex) {
+ throw new DownloadFailedException("Unable to create temporary file for CPE Meta File download.", ex);
+ } finally {
+ try {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException ex) {
+ Logger.getLogger(Index.class.getName()).log(Level.FINEST, null, ex);
+ }
+ }
+ if (tmp != null && tmp.exists()) {
+ tmp.delete();
+ }
+ } finally {
+ if (tmp != null && tmp.exists()) {
+ tmp.deleteOnExit();
+ }
+ }
+ }
+ return timestamp;
+ }
+}
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cve/Indexer.java b/src/main/java/org/codesecure/dependencycheck/data/cve/Indexer.java
new file mode 100644
index 000000000..a0185df9e
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/cve/Indexer.java
@@ -0,0 +1,100 @@
+package org.codesecure.dependencycheck.data.cve;
+/*
+ * This file is part of DependencyCheck.
+ *
+ * DependencyCheck is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DependencyCheck is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+
+import java.io.IOException;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.index.Term;
+import org.codesecure.dependencycheck.data.LuceneUtils;
+import org.codesecure.dependencycheck.data.cve.xml.EntrySaveDelegate;
+
+/**
+ * The Indexer is used to convert a CPE Entry, retrieved from the CPE XML file,
+ * into a Document that is stored in the Lucene index.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class Indexer extends Index implements EntrySaveDelegate {
+
+ /**
+ * Saves a CPE Entry into the Lucene index.
+ *
+ * @param entry a CPE entry.
+ * @throws CorruptIndexException is thrown if the index is corrupt.
+ * @throws IOException is thrown if an IOException occurs.
+ */
+ public void saveEntry(Entry entry) throws CorruptIndexException, IOException {
+ Document doc = convertEntryToDoc(entry);
+ Term term = new Term(Fields.NVDID, LuceneUtils.escapeLuceneQuery(entry.getNvdId()));
+ indexWriter.updateDocument(term, doc);
+ }
+
+ /**
+ * Converst a CPE entry into a Lucene Document.
+ *
+ * @param entry a CPE Entry.
+ * @return a Lucene Document containing a CPE Entry.
+ */
+ protected Document convertEntryToDoc(Entry entry) {
+ Document doc = new Document();
+
+ Field name = new Field(Fields.NAME, entry.getName(), Field.Store.YES, Field.Index.ANALYZED);
+ name.setIndexOptions(IndexOptions.DOCS_ONLY);
+ doc.add(name);
+
+ Field nvdId = new Field(Fields.NVDID, entry.getNvdId(), Field.Store.NO, Field.Index.ANALYZED);
+ nvdId.setIndexOptions(IndexOptions.DOCS_ONLY);
+ doc.add(nvdId);
+
+ Field vendor = new Field(Fields.VENDOR, entry.getVendor(), Field.Store.NO, Field.Index.ANALYZED);
+ vendor.setIndexOptions(IndexOptions.DOCS_ONLY);
+ vendor.setBoost(5.0F);
+ doc.add(vendor);
+
+ Field product = new Field(Fields.PRODUCT, entry.getProduct(), Field.Store.NO, Field.Index.ANALYZED);
+ product.setIndexOptions(IndexOptions.DOCS_ONLY);
+ product.setBoost(5.0F);
+ doc.add(product);
+
+ Field title = new Field(Fields.TITLE, entry.getTitle(), Field.Store.NO, Field.Index.ANALYZED);
+ title.setIndexOptions(IndexOptions.DOCS_ONLY);
+ //title.setBoost(1.0F);
+ doc.add(title);
+
+ //TODO revision should likely be its own field
+ if (entry.getVersion() != null) {
+ Field version = null;
+ if (entry.getRevision() != null) {
+ version = new Field(Fields.VERSION, entry.getVersion() + " "
+ + entry.getRevision(), Field.Store.NO, Field.Index.ANALYZED);
+ } else {
+ version = new Field(Fields.VERSION, entry.getVersion(),
+ Field.Store.NO, Field.Index.ANALYZED);
+ }
+ version.setIndexOptions(IndexOptions.DOCS_ONLY);
+ version.setBoost(0.8F);
+ doc.add(version);
+ }
+
+ return doc;
+ }
+}
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cve/package-info.java b/src/main/java/org/codesecure/dependencycheck/data/cve/package-info.java
new file mode 100644
index 000000000..7748a0137
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/cve/package-info.java
@@ -0,0 +1,12 @@
+/**
+ *
+ *
+ * org.codesecure.dependencycheck.data.cve.xml
+ *
+ *
+ * Contains classes used to parse the CVE XML files.
+ *
+ *
+*/
+
+package org.codesecure.dependencycheck.data.cve;
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cve/xml/CVEHandler.java b/src/main/java/org/codesecure/dependencycheck/data/cve/xml/CVEHandler.java
new file mode 100644
index 000000000..d1fa366c0
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/cve/xml/CVEHandler.java
@@ -0,0 +1,350 @@
+package org.codesecure.dependencycheck.data.cve.xml;
+/*
+ * This file is part of DependencyCheck.
+ *
+ * DependencyCheck is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DependencyCheck is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+
+import org.codesecure.dependencycheck.data.cve.Entry;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.text.ParseException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.lucene.index.CorruptIndexException;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A SAX Handler that will parse the CVE XML Listing.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class CVEHandler extends DefaultHandler {
+
+ private static final String CURRENT_SCHEMA_VERSION = "2.2";
+ EntrySaveDelegate saveDelegate = null;
+ Entry entry = null;
+ boolean languageIsUS = false;
+ StringBuilder nodeText = null;
+ boolean skip = false;
+ Element current = new Element();
+
+ /**
+ * Register a EntrySaveDelegate object. When the last node of an entry is
+ * reached if a save delegate has been regsitered the save method will be invoked.
+ *
+ * @param delegate the delegate used to save an entry
+ */
+ public void registerSaveDelegate(EntrySaveDelegate delegate) {
+ this.saveDelegate = delegate;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ nodeText = null;
+ current.setNode(qName);
+ if (current.isCpeItemNode()) {
+ entry = new Entry();
+ String temp = attributes.getValue("deprecated");
+ String name = attributes.getValue("name");
+ skip = (temp != null && temp.equals("true"));
+ try {
+ if (!skip && name.startsWith("cpe:/a:")) {
+ entry.setName(name);
+ } else {
+ skip = true;
+ }
+ } catch (UnsupportedEncodingException ex) {
+ throw new SAXException(ex);
+ }
+ } else if (current.isTitleNode()) {
+ nodeText = new StringBuilder(100);
+ if ("en-US".equalsIgnoreCase(attributes.getValue("xml:lang"))) {
+ languageIsUS = true;
+ } else {
+ languageIsUS = false;
+ }
+ } else if (current.isMetaNode()) {
+ try {
+ entry.setModificationDate(attributes.getValue("modification-date"));
+ } catch (ParseException ex) {
+ Logger.getLogger(CVEHandler.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ entry.setStatus(attributes.getValue("status"));
+ entry.setNvdId(attributes.getValue("nvd-id"));
+ } else if (current.isSchemaVersionNode()) {
+ nodeText = new StringBuilder(3);
+ } else if (current.isTimestampNode()) {
+ nodeText = new StringBuilder(24);
+ }
+// } else if (current.isCpeListNode()) {
+// //do nothing
+// } else if (current.isNotesNode()) {
+// //do nothing
+// } else if (current.isNoteNode()) {
+// //do nothing
+// } else if (current.isCheckNode()) {
+// //do nothing
+// } else if (current.isGeneratorNode()) {
+// //do nothing
+// } else if (current.isProductNameNode()) {
+// //do nothing
+// } else if (current.isProductVersionNode()) {
+// //do nothing
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ //nodeText += new String(ch, start, length);
+ if (nodeText != null) {
+ nodeText.append(ch, start, length);
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ current.setNode(qName);
+ if (current.isCpeItemNode()) {
+ if (saveDelegate != null && !skip) {
+ try {
+ saveDelegate.saveEntry(entry);
+ } catch (CorruptIndexException ex) {
+ Logger.getLogger(CVEHandler.class.getName()).log(Level.SEVERE, null, ex);
+ throw new SAXException(ex);
+ } catch (IOException ex) {
+ Logger.getLogger(CVEHandler.class.getName()).log(Level.SEVERE, null, ex);
+ throw new SAXException(ex);
+ }
+ entry = null;
+ }
+ } else if (current.isTitleNode()) {
+ if (languageIsUS) {
+ entry.setTitle(nodeText.toString());
+ }
+ } else if (current.isSchemaVersionNode() && !CURRENT_SCHEMA_VERSION.equals(nodeText.toString())) {
+ throw new SAXException("ERROR: Invalid Schema Version, expected: "
+ + CURRENT_SCHEMA_VERSION + ", file is: " + nodeText);
+ }
+// } else if (current.isCpeListNode()) {
+// //do nothing
+// } else if (current.isMetaNode()) {
+// //do nothing
+// } else if (current.isNotesNode()) {
+// //do nothing
+// } else if (current.isNoteNode()) {
+// //do nothing
+// } else if (current.isCheckNode()) {
+// //do nothing
+// } else if (current.isGeneratorNode()) {
+// //do nothing
+// } else if (current.isProductNameNode()) {
+// //do nothing
+// } else if (current.isProductVersionNode()) {
+// //do nothing
+// else if (current.isTimestampNode()) {
+// //do nothing
+// } else {
+// throw new SAXException("ERROR STATE: Unexpected qName '" + qName + "'");
+// }
+ }
+
+ //
+ /**
+ * A simple class to maintain information about the current element while parsing
+ * the CPE XML.
+ */
+ protected class Element {
+
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String CPE_LIST = "cpe-list";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String CPE_ITEM = "cpe-item";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String TITLE = "title";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String NOTES = "notes";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String NOTE = "note";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String CHECK = "check";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String META = "meta:item-metadata";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String GENERATOR = "generator";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String PRODUCT_NAME = "product_name";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String PRODUCT_VERSION = "product_version";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String SCHEMA_VERSION = "schema_version";
+ /**
+ * A node type in the CPE Schema 2.2
+ */
+ public static final String TIMESTAMP = "timestamp";
+ private String node = null;
+
+ /**
+ * Gets the value of node
+ *
+ * @return the value of node
+ */
+ public String getNode() {
+ return this.node;
+ }
+
+ /**
+ * Sets the value of node
+ *
+ * @param node new value of node
+ */
+ public void setNode(String node) {
+ this.node = node;
+ }
+
+ /**
+ * Checks if the handler is at the CPE_LIST node
+ *
+ * @return true or false
+ */
+ public boolean isCpeListNode() {
+ return CPE_LIST.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the CPE_ITEM node
+ *
+ * @return true or false
+ */
+ public boolean isCpeItemNode() {
+ return CPE_ITEM.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the TITLE node
+ *
+ * @return true or false
+ */
+ public boolean isTitleNode() {
+ return TITLE.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the NOTES node
+ *
+ * @return true or false
+ */
+ public boolean isNotesNode() {
+ return NOTES.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the NOTE node
+ *
+ * @return true or false
+ */
+ public boolean isNoteNode() {
+ return NOTE.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the CHECK node
+ *
+ * @return true or false
+ */
+ public boolean isCheckNode() {
+ return CHECK.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the META node
+ *
+ * @return true or false
+ */
+ public boolean isMetaNode() {
+ return META.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the GENERATOR node
+ *
+ * @return true or false
+ */
+ public boolean isGeneratorNode() {
+ return GENERATOR.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the PRODUCT_NAME node
+ *
+ * @return true or false
+ */
+ public boolean isProductNameNode() {
+ return PRODUCT_NAME.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the PRODUCT_VERSION node
+ *
+ * @return true or false
+ */
+ public boolean isProductVersionNode() {
+ return PRODUCT_VERSION.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the SCHEMA_VERSION node
+ *
+ * @return true or false
+ */
+ public boolean isSchemaVersionNode() {
+ return SCHEMA_VERSION.equals(node);
+ }
+
+ /**
+ * Checks if the handler is at the TIMESTAMP node
+ *
+ * @return true or false
+ */
+ public boolean isTimestampNode() {
+ return TIMESTAMP.equals(node);
+ }
+ }
+ //
+}
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cve/xml/EntrySaveDelegate.java b/src/main/java/org/codesecure/dependencycheck/data/cve/xml/EntrySaveDelegate.java
new file mode 100644
index 000000000..c5a263e88
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/cve/xml/EntrySaveDelegate.java
@@ -0,0 +1,42 @@
+package org.codesecure.dependencycheck.data.cve.xml;
+/*
+ * This file is part of DependencyCheck.
+ *
+ * DependencyCheck is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DependencyCheck is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+
+import org.codesecure.dependencycheck.data.cve.Entry;
+import java.io.IOException;
+import org.apache.lucene.index.CorruptIndexException;
+
+/**
+ *
+ * An interface used to define the save function used when parsing the CVE XML
+ * file.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public interface EntrySaveDelegate {
+
+ /**
+ * Saves a CVE Entry into the Lucene index.
+ *
+ * @param entry a CVE entry.
+ * @throws CorruptIndexException is thrown if the index is corrupt.
+ * @throws IOException is thrown if an IOException occurs.
+ */
+ void saveEntry(Entry entry) throws CorruptIndexException, IOException;
+}
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cve/xml/Importer.java b/src/main/java/org/codesecure/dependencycheck/data/cve/xml/Importer.java
new file mode 100644
index 000000000..c76fdd06e
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/cve/xml/Importer.java
@@ -0,0 +1,76 @@
+package org.codesecure.dependencycheck.data.cve.xml;
+/*
+ * This file is part of DependencyCheck.
+ *
+ * DependencyCheck is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DependencyCheck is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+ */
+
+import org.codesecure.dependencycheck.data.cve.Indexer;
+import java.io.File;
+import java.io.IOException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.SAXException;
+
+/**
+ * Imports a CVE XML file into the Lucene CVE Index.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class Importer {
+
+ /**
+ * Private constructor for utility class.
+ */
+ private Importer() {
+
+ }
+
+ /**
+ * Imports the CPE XML File into the Lucene Index.
+ *
+ * @param file containing the path to the CPE XML file.
+ * @throws ParserConfigurationException is thrown if the parser is misconfigured.
+ * @throws SAXException is thrown when there is a SAXException.
+ * @throws IOException is thrown when there is an IOException.
+ */
+ public static void importXML(File file) throws ParserConfigurationException, SAXException, IOException {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ SAXParser saxParser = factory.newSAXParser();
+ CVEHandler handler = new CVEHandler();
+ Indexer indexer = new Indexer();
+ indexer.open();
+ handler.registerSaveDelegate(indexer);
+ saxParser.parse(file, handler);
+ indexer.close();
+ }
+ /**
+ * Imports the CPE XML File into the Lucene Index.
+ *
+ * @param path the path to the CPE XML file.
+ * @throws ParserConfigurationException is thrown if the parser is misconfigured.
+ * @throws SAXException is thrown when there is a SAXException.
+ * @throws IOException is thrown when there is an IOException.
+ */
+ public static void importXML(String path) throws ParserConfigurationException, SAXException, IOException {
+ File f = new File(path);
+ if (!f.exists()) {
+ f.mkdirs();
+ }
+ Importer.importXML(f);
+ }
+}
diff --git a/src/main/java/org/codesecure/dependencycheck/data/cve/xml/package-info.java b/src/main/java/org/codesecure/dependencycheck/data/cve/xml/package-info.java
new file mode 100644
index 000000000..9256378f9
--- /dev/null
+++ b/src/main/java/org/codesecure/dependencycheck/data/cve/xml/package-info.java
@@ -0,0 +1,12 @@
+/**
+ *
+ *
+ * org.codesecure.dependencycheck.data.cve.xml
+ *
+ *
+ * Contains classes used to parse the CVE XML file.
+ *
+ *
+*/
+
+package org.codesecure.dependencycheck.data.cve.xml;
diff --git a/src/main/java/org/codesecure/dependencycheck/scanner/Dependency.java b/src/main/java/org/codesecure/dependencycheck/scanner/Dependency.java
index 0045a6ec5..3c7a19e1d 100644
--- a/src/main/java/org/codesecure/dependencycheck/scanner/Dependency.java
+++ b/src/main/java/org/codesecure/dependencycheck/scanner/Dependency.java
@@ -57,9 +57,9 @@ public class Dependency {
*/
protected EvidenceCollection vendorEvidence = null;
/**
- * A collection of title evidence.
+ * A collection of product evidence.
*/
- protected EvidenceCollection titleEvidence = null;
+ protected EvidenceCollection productEvidence = null;
/**
* A collection of version evidence.
*/
@@ -70,7 +70,7 @@ public class Dependency {
*/
public Dependency() {
vendorEvidence = new EvidenceCollection();
- titleEvidence = new EvidenceCollection();
+ productEvidence = new EvidenceCollection();
versionEvidence = new EvidenceCollection();
cpes = new ArrayList();
}
@@ -181,7 +181,7 @@ public class Dependency {
* @return an EvidenceCollection.
*/
public EvidenceCollection getEvidence() {
- return EvidenceCollection.mergeUsed(this.titleEvidence, this.vendorEvidence, this.versionEvidence);
+ return EvidenceCollection.mergeUsed(this.productEvidence, this.vendorEvidence, this.versionEvidence);
}
@@ -191,7 +191,7 @@ public class Dependency {
* @return an EvidenceCollection.
*/
public EvidenceCollection getEvidenceUsed() {
- EvidenceCollection ec = EvidenceCollection.mergeUsed(this.titleEvidence, this.vendorEvidence, this.versionEvidence);
+ EvidenceCollection ec = EvidenceCollection.mergeUsed(this.productEvidence, this.vendorEvidence, this.versionEvidence);
return ec;
}
@@ -205,12 +205,12 @@ public class Dependency {
}
/**
- * Gets the Title Evidence.
+ * Gets the Product Evidence.
*
* @return an EvidenceCollection.
*/
- public EvidenceCollection getTitleEvidence() {
- return this.titleEvidence;
+ public EvidenceCollection getProductEvidence() {
+ return this.productEvidence;
}
/**
@@ -244,7 +244,7 @@ public class Dependency {
if (vendorEvidence.containsUsedString(str)) {
return true;
}
- if (titleEvidence.containsUsedString(str)) {
+ if (productEvidence.containsUsedString(str)) {
return true;
}
if (versionEvidence.containsUsedString(fnd)) {
diff --git a/src/main/java/org/codesecure/dependencycheck/scanner/JarAnalyzer.java b/src/main/java/org/codesecure/dependencycheck/scanner/JarAnalyzer.java
index 6c99c28f9..f9138eb99 100644
--- a/src/main/java/org/codesecure/dependencycheck/scanner/JarAnalyzer.java
+++ b/src/main/java/org/codesecure/dependencycheck/scanner/JarAnalyzer.java
@@ -179,7 +179,7 @@ public class JarAnalyzer extends AbstractAnalyzer {
}
Pattern rx = Pattern.compile("\\s\\s+");
fileNameEvidence = rx.matcher(sb.toString()).replaceAll(" ");
- dependency.getTitleEvidence().addEvidence("jar", "file name",
+ dependency.getProductEvidence().addEvidence("jar", "file name",
fileNameEvidence, Evidence.Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("jar", "file name",
fileNameEvidence, Evidence.Confidence.HIGH);
@@ -276,14 +276,14 @@ public class JarAnalyzer extends AbstractAnalyzer {
return;
}
EvidenceCollection vendor = dependency.getVendorEvidence();
- EvidenceCollection title = dependency.getTitleEvidence();
+ EvidenceCollection product = dependency.getProductEvidence();
for (String s : level0.keySet()) {
if (!"org".equals(s) && !"com".equals(s)) {
vendor.addWeighting(s);
- title.addWeighting(s);
+ product.addWeighting(s);
vendor.addEvidence("jar", "package", s, Evidence.Confidence.LOW);
- title.addEvidence("jar", "package", s, Evidence.Confidence.LOW);
+ product.addEvidence("jar", "package", s, Evidence.Confidence.LOW);
}
}
for (String s : level1.keySet()) {
@@ -296,9 +296,9 @@ public class JarAnalyzer extends AbstractAnalyzer {
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
} else {
vendor.addWeighting(parts[0]);
- title.addWeighting(parts[1]);
+ product.addWeighting(parts[1]);
vendor.addEvidence("jar", "package", parts[0], Evidence.Confidence.LOW);
- title.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
+ product.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
}
}
}
@@ -309,18 +309,18 @@ public class JarAnalyzer extends AbstractAnalyzer {
String[] parts = s.split("/");
if ("org".equals(parts[0]) || "com".equals(parts[0])) {
vendor.addWeighting(parts[1]);
- title.addWeighting(parts[2]);
+ product.addWeighting(parts[2]);
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
- title.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
+ product.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
} else {
vendor.addWeighting(parts[0]);
vendor.addWeighting(parts[1]);
- title.addWeighting(parts[1]);
- title.addWeighting(parts[2]);
+ product.addWeighting(parts[1]);
+ product.addWeighting(parts[2]);
vendor.addEvidence("jar", "package", parts[0], Evidence.Confidence.LOW);
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
- title.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
- title.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
+ product.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
+ product.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
}
}
}
@@ -332,26 +332,26 @@ public class JarAnalyzer extends AbstractAnalyzer {
if ("org".equals(parts[0]) || "com".equals(parts[0])) {
vendor.addWeighting(parts[1]);
vendor.addWeighting(parts[2]);
- title.addWeighting(parts[2]);
- title.addWeighting(parts[3]);
+ product.addWeighting(parts[2]);
+ product.addWeighting(parts[3]);
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
vendor.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
- title.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
- title.addEvidence("jar", "package", parts[3], Evidence.Confidence.LOW);
+ product.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
+ product.addEvidence("jar", "package", parts[3], Evidence.Confidence.LOW);
} else {
vendor.addWeighting(parts[0]);
vendor.addWeighting(parts[1]);
vendor.addWeighting(parts[2]);
- title.addWeighting(parts[1]);
- title.addWeighting(parts[2]);
- title.addWeighting(parts[3]);
+ product.addWeighting(parts[1]);
+ product.addWeighting(parts[2]);
+ product.addWeighting(parts[3]);
vendor.addEvidence("jar", "package", parts[0], Evidence.Confidence.LOW);
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
vendor.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
- title.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
- title.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
- title.addEvidence("jar", "package", parts[3], Evidence.Confidence.LOW);
+ product.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
+ product.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
+ product.addEvidence("jar", "package", parts[3], Evidence.Confidence.LOW);
}
}
}
@@ -380,7 +380,7 @@ public class JarAnalyzer extends AbstractAnalyzer {
Attributes atts = manifest.getMainAttributes();
EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
- EvidenceCollection titleEvidence = dependency.getTitleEvidence();
+ EvidenceCollection productEvidence = dependency.getProductEvidence();
EvidenceCollection versionEvidence = dependency.getVersionEvidence();
String source = "Manifest";
@@ -389,7 +389,7 @@ public class JarAnalyzer extends AbstractAnalyzer {
String key = entry.getKey().toString();
String value = atts.getValue(key);
if (key.equals(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
- titleEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
+ productEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
@@ -397,15 +397,15 @@ public class JarAnalyzer extends AbstractAnalyzer {
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VENDOR_ID.toString())) {
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
} else if (key.equals(BUNDLE_DESCRIPTION)) {
- titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
+ productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
} else if (key.equals(BUNDLE_NAME)) {
- titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
+ productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
} else if (key.equals(BUNDLE_VENDOR)) {
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
} else if (key.equals(BUNDLE_VERSION)) {
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
} else if (key.equals(Attributes.Name.MAIN_CLASS.toString())) {
- titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
+ productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
} else {
key = key.toLowerCase();
@@ -414,14 +414,14 @@ public class JarAnalyzer extends AbstractAnalyzer {
if (key.contains("version")) {
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
} else if (key.contains("title")) {
- titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
+ productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
} else if (key.contains("vendor")) {
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
} else if (key.contains("name")) {
- titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
+ productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
} else {
- titleEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
+ productEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
if (value.matches(".*\\d.*")) {
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
diff --git a/src/test/java/org/codesecure/dependencycheck/data/cpe/IndexTest.java b/src/test/java/org/codesecure/dependencycheck/data/cpe/IndexTest.java
index c88d05c66..00dba6a5e 100644
--- a/src/test/java/org/codesecure/dependencycheck/data/cpe/IndexTest.java
+++ b/src/test/java/org/codesecure/dependencycheck/data/cpe/IndexTest.java
@@ -56,13 +56,7 @@ public class IndexTest extends BaseIndexTestCase {
} catch (IOException ex) {
fail(ex.getMessage());
}
- try {
- instance.close();
- } catch (CorruptIndexException ex) {
- fail(ex.getMessage());
- } catch (IOException ex) {
- fail(ex.getMessage());
- }
+ instance.close();
}
/**
@@ -71,7 +65,8 @@ public class IndexTest extends BaseIndexTestCase {
@Test
public void testGetDirectory() throws Exception {
System.out.println("getDirectory");
- Directory result = Index.getDirectory();
+ Index index = new Index();
+ Directory result = index.getDirectory();
String exp = "\\target\\store\\cpe";
// TODO review the generated test code and remove the default call to fail.
assertTrue(result.toString().contains(exp));
diff --git a/src/test/java/org/codesecure/dependencycheck/data/cpe/IndexTestCase.java b/src/test/java/org/codesecure/dependencycheck/data/cpe/IndexTestCase.java
deleted file mode 100644
index c35d7097a..000000000
--- a/src/test/java/org/codesecure/dependencycheck/data/cpe/IndexTestCase.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.codesecure.dependencycheck.data.cpe;
-
-import org.codesecure.dependencycheck.data.BaseIndexTestCase;
-
-/**
- *
- * @author jeremy
- */
-public class IndexTestCase extends BaseIndexTestCase {
-
- public IndexTestCase(String testName) {
- super(testName);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- public void testIgnoreThisClass() throws Exception {
- assertTrue(true);
- }
-
-}
diff --git a/src/test/java/org/codesecure/dependencycheck/reporting/ReportGeneratorTest.java b/src/test/java/org/codesecure/dependencycheck/reporting/ReportGeneratorTest.java
index 55fbae29b..35a070995 100644
--- a/src/test/java/org/codesecure/dependencycheck/reporting/ReportGeneratorTest.java
+++ b/src/test/java/org/codesecure/dependencycheck/reporting/ReportGeneratorTest.java
@@ -68,10 +68,10 @@ public class ReportGeneratorTest extends BaseIndexTestCase {
d.addCPEentry("cpe://a:/some:cpe:1.0");
List dependencies = new ArrayList();
- d.getTitleEvidence().addEvidence("jar","filename","test", Confidence.HIGH);
- d.getTitleEvidence().addEvidence("manifest","vendor","test", Confidence.HIGH);
+ d.getProductEvidence().addEvidence("jar","filename","test", Confidence.HIGH);
+ d.getProductEvidence().addEvidence("manifest","vendor","test", Confidence.HIGH);
- for (Evidence e : d.getTitleEvidence().iterator(Confidence.HIGH)) {
+ for (Evidence e : d.getProductEvidence().iterator(Confidence.HIGH)) {
String t = e.getValue();
}
dependencies.add(d);
@@ -82,10 +82,10 @@ public class ReportGeneratorTest extends BaseIndexTestCase {
d2.addCPEentry("cpe://a:/another:cpe:1.0");
d2.addCPEentry("cpe://a:/another:cpe:1.1");
d2.addCPEentry("cpe://a:/another:cpe:1.2");
- d2.getTitleEvidence().addEvidence("jar","filename","another.jar", Confidence.HIGH);
- d2.getTitleEvidence().addEvidence("manifest","vendor","Company A", Confidence.MEDIUM);
+ d2.getProductEvidence().addEvidence("jar","filename","another.jar", Confidence.HIGH);
+ d2.getProductEvidence().addEvidence("manifest","vendor","Company A", Confidence.MEDIUM);
- for (Evidence e : d2.getTitleEvidence().iterator(Confidence.HIGH)) {
+ for (Evidence e : d2.getProductEvidence().iterator(Confidence.HIGH)) {
String t = e.getValue();
}
@@ -94,9 +94,9 @@ public class ReportGeneratorTest extends BaseIndexTestCase {
Dependency d3 = new Dependency();
d3.setFileName("Third.jar");
d3.setFilePath("lib/Third.jar");
- d3.getTitleEvidence().addEvidence("jar","filename","third.jar", Confidence.HIGH);
+ d3.getProductEvidence().addEvidence("jar","filename","third.jar", Confidence.HIGH);
- for (Evidence e : d3.getTitleEvidence().iterator(Confidence.HIGH)) {
+ for (Evidence e : d3.getProductEvidence().iterator(Confidence.HIGH)) {
String t = e.getValue();
}
diff --git a/src/test/java/org/codesecure/dependencycheck/scanner/JarAnalyzerTest.java b/src/test/java/org/codesecure/dependencycheck/scanner/JarAnalyzerTest.java
index a0f8864dc..0f3a0abdb 100644
--- a/src/test/java/org/codesecure/dependencycheck/scanner/JarAnalyzerTest.java
+++ b/src/test/java/org/codesecure/dependencycheck/scanner/JarAnalyzerTest.java
@@ -59,7 +59,7 @@ public class JarAnalyzerTest {
result = instance.insepct(file);
boolean found = false;
- for (Evidence e : result.getTitleEvidence()) {
+ for (Evidence e : result.getProductEvidence()) {
if (e.getName().equals("package-title") && e.getValue().equals("org.mortbay.http")) {
found = true;
break;