diff --git a/.gitignore b/.gitignore index e9266d6e07..340b5a525f 100644 --- a/.gitignore +++ b/.gitignore @@ -76,4 +76,5 @@ hs_err_pid*.log /ImageGallery/release/ /thunderbirdparser/release/ /RecentActivity/release/ +/CentralRepository/release/ diff --git a/CentralRepository/Central Repository User Guide.pdf b/CentralRepository/Central Repository User Guide.pdf new file mode 100644 index 0000000000..7d18eec304 Binary files /dev/null and b/CentralRepository/Central Repository User Guide.pdf differ diff --git a/CentralRepository/build.xml b/CentralRepository/build.xml new file mode 100644 index 0000000000..4e8c2ff783 --- /dev/null +++ b/CentralRepository/build.xml @@ -0,0 +1,31 @@ + + + + + + Builds, tests, and runs the project org.sleuthkit.autopsy.centralrepository. + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CentralRepository/ivy.xml b/CentralRepository/ivy.xml new file mode 100644 index 0000000000..abf18b3da4 --- /dev/null +++ b/CentralRepository/ivy.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/CentralRepository/ivysettings.xml b/CentralRepository/ivysettings.xml new file mode 100644 index 0000000000..e3e086637b --- /dev/null +++ b/CentralRepository/ivysettings.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/CentralRepository/manifest.mf b/CentralRepository/manifest.mf new file mode 100644 index 0000000000..b798470437 --- /dev/null +++ b/CentralRepository/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +AutoUpdate-Show-In-Client: true +OpenIDE-Module: org.sleuthkit.autopsy.centralrepository +OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/centralrepository/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +OpenIDE-Module-Install: org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.class diff --git a/CentralRepository/nbproject/build-impl.xml b/CentralRepository/nbproject/build-impl.xml new file mode 100644 index 0000000000..60467ca5c3 --- /dev/null +++ b/CentralRepository/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CentralRepository/nbproject/project.properties b/CentralRepository/nbproject/project.properties new file mode 100644 index 0000000000..efcb9ba609 --- /dev/null +++ b/CentralRepository/nbproject/project.properties @@ -0,0 +1,9 @@ +file.reference.commons-dbcp2-2.1.1.jar=release/modules/ext/commons-dbcp2-2.1.1.jar +file.reference.commons-logging-1.2.jar=release/modules/ext/commons-logging-1.2.jar +file.reference.commons-pool2-2.4.2.jar=release/modules/ext/commons-pool2-2.4.2.jar +file.reference.postgresql-42.1.1.jar=release/modules/ext/postgresql-42.1.1.jar +file.reference.sqlite-jdbc-3.16.1.jar=release/modules/ext/sqlite-jdbc-3.16.1.jar +javac.source=1.8 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../LICENSE-2.0.txt +nbm.homepage=http://www.sleuthkit.org/autopsy/ diff --git a/CentralRepository/nbproject/project.xml b/CentralRepository/nbproject/project.xml new file mode 100644 index 0000000000..1c66ca32ff --- /dev/null +++ b/CentralRepository/nbproject/project.xml @@ -0,0 +1,116 @@ + + + org.netbeans.modules.apisupport.project + + + org.sleuthkit.autopsy.centralrepository + + + + org.netbeans.api.progress + + + + 1 + 1.47.1 + + + + org.netbeans.modules.options.api + + + + 1 + 1.45.1 + + + + org.openide.awt + + + + 7.67.1 + + + + org.openide.modules + + + + 7.48.1 + + + + org.openide.nodes + + + + 7.45.1 + + + + org.openide.util + + + + 9.7.1 + + + + org.openide.util.lookup + + + + 8.33.1 + + + + org.openide.util.ui + + + + 9.6.1 + + + + org.openide.windows + + + + 6.75.1 + + + + org.sleuthkit.autopsy.core + + + + 10 + 10.8 + + + + + + ext/sqlite-jdbc-3.16.1.jar + release\modules\ext\sqlite-jdbc-3.16.1.jar + + + ext/commons-dbcp2-2.1.1.jar + release\modules\ext\commons-dbcp2-2.1.1.jar + + + ext/postgresql-42.1.1.jar + release\modules\ext\postgresql-42.1.1.jar + + + ext/commons-pool2-2.4.2.jar + release\modules\ext\commons-pool2-2.4.2.jar + + + ext/commons-logging-1.2.jar + release\modules\ext\commons-logging-1.2.jar + + + + diff --git a/CentralRepository/nbproject/suite.properties b/CentralRepository/nbproject/suite.properties new file mode 100644 index 0000000000..29d7cc9bd6 --- /dev/null +++ b/CentralRepository/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/Bundle.properties b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/Bundle.properties new file mode 100644 index 0000000000..9e873a514b --- /dev/null +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/Bundle.properties @@ -0,0 +1,7 @@ +OpenIDE-Module-Name=Central Repository +OpenIDE-Module-Display-Category=Ingest Module +OpenIDE-Module-Short-Description=Correlation Engine Ingest Module +OpenIDE-Module-Long-Description=\ + Correlation Engine ingest module and central database. \n\n\ + The Correlation Engine ingest module stores attributes of artifacts matching selected correlation types into a central database.\n\ + Stored attributes are used in future cases to correlate and analyzes files and artifacts during ingest. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/README-POSTGRES-TESTING.md b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/README-POSTGRES-TESTING.md similarity index 100% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/README-POSTGRES-TESTING.md rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/README-POSTGRES-TESTING.md diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/README_MONGODB_TESTING.md b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/README_MONGODB_TESTING.md similarity index 100% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/README_MONGODB_TESTING.md rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/README_MONGODB_TESTING.md diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties similarity index 100% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.form b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/EamCaseEditDetailsDialog.form similarity index 83% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.form rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/EamCaseEditDetailsDialog.form index 48e0b20957..3b99a41a0b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.form +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/EamCaseEditDetailsDialog.form @@ -66,7 +66,7 @@ - + @@ -76,7 +76,7 @@ - + @@ -88,7 +88,7 @@ - + @@ -149,28 +149,28 @@ - + - + - + - + @@ -189,7 +189,7 @@ - + @@ -272,7 +272,7 @@ - + @@ -292,28 +292,28 @@ - + - + - + - + @@ -326,7 +326,7 @@ - + @@ -340,7 +340,7 @@ - + @@ -401,7 +401,7 @@ - + @@ -410,7 +410,7 @@ - + @@ -419,7 +419,7 @@ - + @@ -428,7 +428,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/EamCaseEditDetailsDialog.java similarity index 96% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/EamCaseEditDetailsDialog.java index d8c24d1a58..80f9c92b03 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamCaseEditDetailsDialog.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/EamCaseEditDetailsDialog.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,12 +16,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.actions; +package org.sleuthkit.autopsy.centralrepository.actions; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Toolkit; -import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -34,18 +33,17 @@ import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamCase; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamOrganization; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel.AddNewOrganizationDialog; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; +import org.sleuthkit.autopsy.centralrepository.optionspanel.AddNewOrganizationDialog; /** - * Handle editing details of cases within the Enterprise Artifacts Manager + * Handle editing details of cases within the Central Repository */ public class EamCaseEditDetailsDialog extends JDialog { @@ -61,12 +59,12 @@ public class EamCaseEditDetailsDialog extends JDialog { private boolean comboboxOrganizationActionListenerActive; /** - * Creates new form EnterpriseArtifactsManagerCasedEditDetailsForm + * Creates new EamCaseEditDetailsDialog form */ - @Messages({"EnterpriseArtifactsManagerCaseEditDetails.window.title=Edit Case Details"}) + @Messages({"EamCaseEditDetailsDialog.window.title=Central Repository Case Properties"}) public EamCaseEditDetailsDialog() { super((JFrame) WindowManager.getDefault().getMainWindow(), - Bundle.EnterpriseArtifactsManagerCaseEditDetails_window_title(), + Bundle.EamCaseEditDetailsDialog_window_title(), true); // NON-NLS try { @@ -414,7 +412,7 @@ public class EamCaseEditDetailsDialog extends JDialog { private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed if (contentChanged) { - updateEnterpriseArtifactsManagerCase(); + updateEamCase(); updateDb(); } dispose(); @@ -513,7 +511,7 @@ public class EamCaseEditDetailsDialog extends JDialog { * Save changed value from text fields and text areas into the EamCase * object. */ - private void updateEnterpriseArtifactsManagerCase() { + private void updateEamCase() { eamCase.setOrg(selectedOrg); eamCase.setExaminerName(tfExaminerNameText.getText()); eamCase.setExaminerEmail(tfExaminerEmailText.getText()); @@ -525,14 +523,14 @@ public class EamCaseEditDetailsDialog extends JDialog { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); if (!EamDb.isEnabled()) { - LOGGER.log(Level.SEVERE, "Enteprise artifacts manager database not enabled"); // NON-NLS + LOGGER.log(Level.SEVERE, "Central Repository database not enabled"); // NON-NLS return; } try { dbManager.updateCase(eamCase); } catch (IllegalArgumentException | EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error connecting to enterprise artifacts manager database", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database", ex); // NON-NLS } finally { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamEditCaseInfoAction.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/EamEditCaseInfoAction.java similarity index 71% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamEditCaseInfoAction.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/EamEditCaseInfoAction.java index 7c13f22530..4123e382ff 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/EamEditCaseInfoAction.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/actions/EamEditCaseInfoAction.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.actions; +package org.sleuthkit.autopsy.centralrepository.actions; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -28,25 +28,25 @@ import org.openide.util.HelpCtx; import org.openide.util.NbBundle.Messages; import org.openide.util.actions.CallableSystemAction; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; /** - * Action to update case details in enterprise artifacts manager database + * Action to update case details in Central Repository database */ @ActionID( category = "Case", - id = "org.sleuthkit.enterpriseartifactsmanager.actions.EnterpriseArtifactsManagerCaseEditCaseInfoAction" + id = "org.sleuthkit.centralrepository.actions.CentralRepositoryCaseProperties" ) @ActionRegistration( - displayName = "#CTL_EnterpriseArtifactsManagerCaseEditCaseInfo", + displayName = "#CTL_CentralRepositoryCaseProperties", lazy = false ) @ActionReference(path = "Menu/Case", position = 650, separatorAfter = 824) -@Messages("CTL_EnterpriseArtifactsManagerCaseEditCaseInfo=Enterprise Artifacts Manager Case Details") +@Messages("CTL_CentralRepositoryCaseProperties=Central Repository Case Properties...") public final class EamEditCaseInfoAction extends CallableSystemAction implements ActionListener { EamEditCaseInfoAction() { - putValue(Action.NAME, Bundle.CTL_EnterpriseArtifactsManagerCaseEditCaseInfo()); // put the action Name + putValue(Action.NAME, Bundle.CTL_CentralRepositoryCaseProperties()); // put the action Name this.setEnabled(true); } @@ -68,7 +68,7 @@ public final class EamEditCaseInfoAction extends CallableSystemAction implements @Override public String getName() { - return Bundle.CTL_EnterpriseArtifactsManagerCaseEditCaseInfo(); + return Bundle.CTL_CentralRepositoryCaseProperties(); } @Override diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/Bundle.properties b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties similarity index 100% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/Bundle.properties rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.form b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form similarity index 87% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.form rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form index f3d1638b95..1567e0f894 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.form +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form @@ -11,28 +11,28 @@ - + - + - + - + @@ -127,7 +127,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java similarity index 89% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index da3c28ac3a..fa2a8ee360 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCases.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.contentviewer; +package org.sleuthkit.autopsy.centralrepository.contentviewer; import java.awt.Component; import java.awt.event.ActionEvent; @@ -47,13 +47,12 @@ import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.contentviewer.Bundle; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactUtil; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamCase; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamGlobalFileInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalFileInstance; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; @@ -61,14 +60,14 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; /** * View correlation results from other cases */ @ServiceProvider(service = DataContentViewer.class, position = 8) -@Messages({"DataContentViewerOtherCases.title=Other Cases", - "DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other cases.",}) +@Messages({"DataContentViewerOtherCases.title=Other Data Sources", + "DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other data sources.",}) public class DataContentViewerOtherCases extends javax.swing.JPanel implements DataContentViewer { private final static Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName()); @@ -118,9 +117,9 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D @Messages({"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.", "# {0} - commonality percentage", - "# {1} - artifact type", - "# {2} - artifact value", - "DataContentViewerOtherCases.correlatedArtifacts.byType={0}% for Artifact Type: {1} and Artifact Value: {2}.\n", + "# {1} - correlation type", + "# {2} - correlation value", + "DataContentViewerOtherCases.correlatedArtifacts.byType={0}% for Correlation Type: {1} and Correlation Value: {2}.\n", "DataContentViewerOtherCases.correlatedArtifacts.title=Commonality Percentages", "DataContentViewerOtherCases.correlatedArtifacts.failed=Failed to get commonality details."}) private void showCommonalityDetails() { @@ -137,8 +136,8 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D for (EamArtifact eamArtifact : correlatedArtifacts) { percentage = dbManager.getCommonalityPercentageForTypeValue(eamArtifact); msg.append(Bundle.DataContentViewerOtherCases_correlatedArtifacts_byType(percentage, - eamArtifact.getArtifactType().getName(), - eamArtifact.getArtifactValue())); + eamArtifact.getCorrelationType().getDisplayName(), + eamArtifact.getCorrelationValue())); } JOptionPane.showConfirmDialog(showCommonalityMenuItem, msg.toString(), @@ -198,7 +197,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D private void saveToCSV() { if (0 != otherCasesTable.getSelectedRowCount()) { Calendar now = Calendar.getInstance(); - String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_cases.csv", now); + String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now); CSVFileChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory())); CSVFileChooser.setSelectedFile(new File(fileName)); CSVFileChooser.setFileFilter(new FileNameExtensionFilter("csv file", "csv")); @@ -359,12 +358,12 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D /** * Scan a Node for blackboard artifacts / content that we can correlate on - * and create the corresponding enterprise artifacts manager artifacts for + * and create the corresponding Central Repository artifacts for * display * * @param node The node to view * - * @return A collection of enterprise artifacts manager artifacts to display + * @return A collection of Central Repository artifacts to display */ private Collection getArtifactsFromCorrelatableAttributes(Node node) { Collection ret = new ArrayList<>(); @@ -379,7 +378,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D List artifactTypes = null; try { EamDb dbManager = EamDb.getInstance(); - artifactTypes = dbManager.getCorrelationArtifactTypes(); + artifactTypes = dbManager.getCorrelationTypes(); if (bbArtifact != null) { EamArtifact eamArtifact = EamArtifactUtil.fromBlackboardArtifact(bbArtifact, false, artifactTypes, false); if (eamArtifact != null) { @@ -387,14 +386,14 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D } } } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error retrieving correlation artifact types", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error retrieving correlation types", ex); // NON-NLS } if (abstractFile != null) { String md5 = abstractFile.getMd5Hash(); if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) { for (EamArtifact.Type aType : artifactTypes) { - if (aType.getName().equals("FILES")) { + if (aType.getId() == EamArtifact.FILES_TYPE_ID) { ret.add(new EamArtifact(aType, md5)); break; } @@ -447,7 +446,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D /** * Query the db for artifact instances from other cases correlated to the - * given enterprise artifacts manager artifact. + * given Central Repository artifact. * * @param eamArtifact The artifact to correlate against * @@ -472,32 +471,30 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D /** * Get the Global File Instances matching the given eamArtifact and convert - * them to Enterprise Artifacts Manager Artifact Instancess. + * them to Central Repository Artifact Instancess. * * @param eamArtifact Artifact to use for ArtifactTypeEnum matching * - * @return List of Enterprise Artifacts Manager Artifact Instances, empty + * @return List of Central Repository Artifact Instances, empty * list if none found */ - public Collection getGlobalFileInstancesAsArtifactInstances(EamArtifact eamArtifact) { + public Collection getReferenceInstancesAsArtifactInstances(EamArtifact eamArtifact) { Collection eamArtifactInstances = new ArrayList<>(); + // FUTURE: support other reference types + if (eamArtifact.getCorrelationType().getId() != EamArtifact.FILES_TYPE_ID) { + return Collections.emptyList(); + } + EamDb dbManager = EamDb.getInstance(); try { - EamDb dbManager = EamDb.getInstance(); - if (dbManager.getCorrelationArtifactTypeByName("FILES").equals(eamArtifact.getArtifactType())) { - try { - Collection eamGlobalFileInstances = dbManager.getGlobalFileInstancesByHash(eamArtifact.getArtifactValue()); - for (EamGlobalFileInstance eamGlobalFileInstance : eamGlobalFileInstances) { - eamArtifactInstances.add(new EamArtifactInstance( - null, null, "", eamGlobalFileInstance.getComment(), eamGlobalFileInstance.getKnownStatus(), EamArtifactInstance.GlobalStatus.GLOBAL - )); - } - return eamArtifactInstances; - } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error getting global file instances from database.", ex); // NON-NLS - } - } + Collection eamGlobalFileInstances = dbManager.getReferenceInstancesByTypeValue(eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue()); + eamGlobalFileInstances.forEach((eamGlobalFileInstance) -> { + eamArtifactInstances.add(new EamArtifactInstance( + null, null, "", eamGlobalFileInstance.getComment(), eamGlobalFileInstance.getKnownStatus(), EamArtifactInstance.GlobalStatus.GLOBAL + )); + }); + return eamArtifactInstances; } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error getting correlation artifact type MD5 from database.", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error getting reference instances from database.", ex); // NON-NLS } return Collections.emptyList(); } @@ -513,7 +510,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D } @Override - @Messages({"DataContentViewerOtherCases.table.nodbconnection=Cannot connect to enterprise artifacts manager database."}) + @Messages({"DataContentViewerOtherCases.table.nodbconnection=Cannot connect to central repository database."}) public void setNode(Node node) { if (!EamDb.isEnabled()) { return; @@ -539,15 +536,15 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D // get local instances Collection eamArtifactInstances = getCorrelatedInstances(eamArtifact, dataSourceName, deviceId); // get global instances - eamArtifactInstances.addAll(getGlobalFileInstancesAsArtifactInstances(eamArtifact)); + eamArtifactInstances.addAll(getReferenceInstancesAsArtifactInstances(eamArtifact)); eamArtifactInstances.forEach((eamArtifactInstance) -> { EamArtifact newCeArtifact = new EamArtifact( - eamArtifact.getArtifactType(), - eamArtifact.getArtifactValue() + eamArtifact.getCorrelationType(), + eamArtifact.getCorrelationValue() ); newCeArtifact.addInstance(eamArtifactInstance); - tableModel.addEnterpriseArtifactManagerArtifact(newCeArtifact); + tableModel.addEamArtifact(newCeArtifact); }); }); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCasesTableCellRenderer.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableCellRenderer.java similarity index 87% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCasesTableCellRenderer.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableCellRenderer.java index d9c453b67e..3a657e3d02 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCasesTableCellRenderer.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableCellRenderer.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.contentviewer; +package org.sleuthkit.autopsy.centralrepository.contentviewer; import java.awt.Color; import java.awt.Component; @@ -24,6 +24,7 @@ import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellRenderer; +import org.sleuthkit.datamodel.TskData; /** * Renderer for cells in data content viewer table @@ -49,19 +50,15 @@ public class DataContentViewerOtherCasesTableCellRenderer implements TableCellRe background = Color.BLUE; } else { String known_status = (String) table.getModel().getValueAt(row, 5); - switch (known_status) { - case "Bad": + if (known_status.equals(TskData.FileKnown.BAD.getName())) { foreground = Color.WHITE; background = Color.RED; - break; - case "Unknown": + } else if (known_status.equals(TskData.FileKnown.UNKNOWN.getName())) { foreground = Color.BLACK; background = Color.YELLOW; - break; - default: + } else { foreground = Color.BLACK; background = Color.WHITE; - break; } } renderer.setForeground(foreground); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCasesTableModel.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java similarity index 84% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCasesTableModel.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java index 9181b6f844..266211493b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/DataContentViewerOtherCasesTableModel.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,14 +16,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.contentviewer; +package org.sleuthkit.autopsy.centralrepository.contentviewer; import java.util.ArrayList; import java.util.List; import javax.swing.table.AbstractTableModel; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance; /** * Model for cells in data content viewer table @@ -34,10 +34,10 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { "DataContentViewerOtherCasesTableModel.device=Device", "DataContentViewerOtherCasesTableModel.dataSource=Data Source", "DataContentViewerOtherCasesTableModel.path=Path", - "DataContentViewerOtherCasesTableModel.type=Artifact Type", - "DataContentViewerOtherCasesTableModel.value=Artifact Value", - "DataContentViewerOtherCasesTableModel.scope=Scope", // was globalStatus - "DataContentViewerOtherCasesTableModel.known=Known", // was knownStatus + "DataContentViewerOtherCasesTableModel.type=Correlation Type", + "DataContentViewerOtherCasesTableModel.value=Correlation Value", + "DataContentViewerOtherCasesTableModel.scope=Scope", + "DataContentViewerOtherCasesTableModel.known=Known", "DataContentViewerOtherCasesTableModel.comment=Comment", "DataContentViewerOtherCasesTableModel.noData=No Data.",}) private enum TableColumns { @@ -48,7 +48,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { DEVICE(Bundle.DataContentViewerOtherCasesTableModel_device(), 145), TYPE(Bundle.DataContentViewerOtherCasesTableModel_type(), 40), VALUE(Bundle.DataContentViewerOtherCasesTableModel_value(), 145), - KNOWN(Bundle.DataContentViewerOtherCasesTableModel_known(), 25), + KNOWN(Bundle.DataContentViewerOtherCasesTableModel_known(), 45), SCOPE(Bundle.DataContentViewerOtherCasesTableModel_scope(), 20), COMMENT(Bundle.DataContentViewerOtherCasesTableModel_comment(), 200), FILE_PATH(Bundle.DataContentViewerOtherCasesTableModel_path(), 250); @@ -151,16 +151,16 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { value = eamArtifactInstance.getFilePath(); break; case TYPE: - value = eamArtifact.getArtifactType().getName(); + value = eamArtifact.getCorrelationType().getDisplayName(); break; case VALUE: - value = eamArtifact.getArtifactValue(); + value = eamArtifact.getCorrelationValue(); break; case SCOPE: value = eamArtifactInstance.getGlobalStatus().toString(); break; case KNOWN: - value = eamArtifactInstance.getKnownStatus().toString(); + value = eamArtifactInstance.getKnownStatus().getName(); break; case COMMENT: value = eamArtifactInstance.getComment(); @@ -175,12 +175,12 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { } /** - * Add one local Enterprise Artifacts Manager Artifact to the table. + * Add one local Central Repository Artifact to the table. * - * @param eamArtifact Enterprise Artifacts Manager Artifact to add to the + * @param eamArtifact Central Repository Artifact to add to the * table */ - public void addEnterpriseArtifactManagerArtifact(EamArtifact eamArtifact) { + public void addEamArtifact(EamArtifact eamArtifact) { eamArtifacts.add(eamArtifact); fireTableDataChanged(); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java similarity index 80% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index fd522ec7dd..0bab99d341 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/AbstractSqlEamDb.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.net.UnknownHostException; import java.util.ArrayList; @@ -32,9 +32,10 @@ import java.sql.Types; import java.time.LocalDate; import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; +import java.util.Set; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.TskData; /** * @@ -45,13 +46,11 @@ public abstract class AbstractSqlEamDb implements EamDb { private final static Logger LOGGER = Logger.getLogger(AbstractSqlEamDb.class.getName()); - protected final List DEFAULT_ARTIFACT_TYPES; + protected final List DEFAULT_CORRELATION_TYPES; private int bulkArtifactsCount; - private int bulkGlobalArtifactsCount; protected int bulkArtifactsThreshold; private final Map> bulkArtifacts; - private final Map> bulkGlobalArtifacts; private final List badTags; /** @@ -60,18 +59,14 @@ public abstract class AbstractSqlEamDb implements EamDb { * @throws UnknownHostException, EamDbException */ protected AbstractSqlEamDb() { - badTags = new ArrayList(); + badTags = new ArrayList<>(); bulkArtifactsCount = 0; - bulkGlobalArtifactsCount = 0; bulkArtifacts = new HashMap<>(); - bulkGlobalArtifacts = new HashMap<>(); - DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes(); - - for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { - bulkArtifacts.put(type.getName(), new ArrayList<>()); - bulkGlobalArtifacts.put(type.getName(), new ArrayList<>()); - } + DEFAULT_CORRELATION_TYPES = EamArtifact.getDefaultCorrelationTypes(); + DEFAULT_CORRELATION_TYPES.forEach((type) -> { + bulkArtifacts.put(type.getDbTableName(), new ArrayList<>()); + }); } /** @@ -100,7 +95,6 @@ public abstract class AbstractSqlEamDb implements EamDb { // } // // else, schema is current // } - /** * Setup and create a connection to the selected database implementation */ @@ -330,7 +324,7 @@ public abstract class AbstractSqlEamDb implements EamDb { preparedStatement.setString(1, caseUUID); resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { - eamCaseResult = getEnterpriseArtifactManagerCaseFromResultSet(resultSet); + eamCaseResult = getEamCaseFromResultSet(resultSet); } } catch (SQLException ex) { throw new EamDbException("Error getting case details.", ex); // NON-NLS @@ -366,7 +360,7 @@ public abstract class AbstractSqlEamDb implements EamDb { preparedStatement = conn.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { - eamCaseResult = getEnterpriseArtifactManagerCaseFromResultSet(resultSet); + eamCaseResult = getEamCaseFromResultSet(resultSet); cases.add(eamCaseResult); } } catch (SQLException ex) { @@ -457,7 +451,7 @@ public abstract class AbstractSqlEamDb implements EamDb { preparedStatement.setString(1, dataSourceDeviceId); resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { - eamDataSourceResult = getEnterpriseArtifactManagerDataSourceFromResultSet(resultSet); + eamDataSourceResult = getEamDataSourceFromResultSet(resultSet); } } catch (SQLException ex) { throw new EamDbException("Error getting case details.", ex); // NON-NLS @@ -490,7 +484,7 @@ public abstract class AbstractSqlEamDb implements EamDb { preparedStatement = conn.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { - eamDataSourceResult = getEnterpriseArtifactManagerDataSourceFromResultSet(resultSet); + eamDataSourceResult = getEamDataSourceFromResultSet(resultSet); dataSources.add(eamDataSourceResult); } } catch (SQLException ex) { @@ -504,10 +498,6 @@ public abstract class AbstractSqlEamDb implements EamDb { return dataSources; } - private String artifactTypeToTableName(EamArtifact.Type type) { - return type.getName() + "_instances"; - } - /** * Inserts new Artifact(s) into the database. Should add associated Case and * Data Source first. @@ -521,7 +511,7 @@ public abstract class AbstractSqlEamDb implements EamDb { List eamInstances = eamArtifact.getInstances(); PreparedStatement preparedStatement = null; - String tableName = artifactTypeToTableName(eamArtifact.getArtifactType()); + String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()); StringBuilder sql = new StringBuilder(); sql.append("INSERT INTO "); sql.append(tableName); @@ -534,7 +524,7 @@ public abstract class AbstractSqlEamDb implements EamDb { for (EamArtifactInstance eamInstance : eamInstances) { preparedStatement.setString(1, eamInstance.getEamCase().getCaseUUID()); preparedStatement.setString(2, eamInstance.getEamDataSource().getDeviceID()); - preparedStatement.setString(3, eamArtifact.getArtifactValue()); + preparedStatement.setString(3, eamArtifact.getCorrelationValue()); preparedStatement.setString(4, eamInstance.getFilePath()); preparedStatement.setString(5, eamInstance.getKnownStatus().name()); preparedStatement.setString(6, eamInstance.getComment()); @@ -550,8 +540,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } /** - * Retrieves eamArtifact instances from the database that are associated with - * the eamArtifactType and eamArtifactValue of the given eamArtifact. + * Retrieves eamArtifact instances from the database that are associated + * with the eamArtifactType and eamArtifactValue of the given eamArtifact. * * @param eamArtifact The type/value to look up (artifact with 0 instances) * @@ -567,7 +557,7 @@ public abstract class AbstractSqlEamDb implements EamDb { PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String tableName = artifactTypeToTableName(eamArtifact.getArtifactType()); + String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()); StringBuilder sql = new StringBuilder(); sql.append("SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment FROM "); sql.append(tableName); @@ -581,10 +571,10 @@ public abstract class AbstractSqlEamDb implements EamDb { try { preparedStatement = conn.prepareStatement(sql.toString()); - preparedStatement.setString(1, eamArtifact.getArtifactValue()); + preparedStatement.setString(1, eamArtifact.getCorrelationValue()); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { - artifactInstance = getEnterpriseArtifactManagerArtifactInstanceFromResultSet(resultSet); + artifactInstance = getEamArtifactInstanceFromResultSet(resultSet); artifactInstances.add(artifactInstance); } } catch (SQLException ex) { @@ -599,13 +589,13 @@ public abstract class AbstractSqlEamDb implements EamDb { } /** - * Retrieves eamArtifact instances from the database that are associated with - * the aType and filePath + * Retrieves eamArtifact instances from the database that are associated + * with the aType and filePath * * @param aType EamArtifact.Type to search for * @param filePath File path to search for * - * @return List of 0 or more EnterpriseArtifactManagerArtifactInstances + * @return List of 0 or more EamArtifactInstances * * @throws EamDbException */ @@ -619,7 +609,7 @@ public abstract class AbstractSqlEamDb implements EamDb { PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String tableName = artifactTypeToTableName(aType); + String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType); StringBuilder sql = new StringBuilder(); sql.append("SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment FROM "); sql.append(tableName); @@ -636,7 +626,7 @@ public abstract class AbstractSqlEamDb implements EamDb { preparedStatement.setString(1, filePath); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { - artifactInstance = getEnterpriseArtifactManagerArtifactInstanceFromResultSet(resultSet); + artifactInstance = getEamArtifactInstanceFromResultSet(resultSet); artifactInstances.add(artifactInstance); } } catch (SQLException ex) { @@ -655,7 +645,7 @@ public abstract class AbstractSqlEamDb implements EamDb { * associated with the ArtifactType and artifactValue of the given artifact. * * @param eamArtifact Artifact with artifactType and artifactValue to search - * for + * for * * @return Number of artifact instances having ArtifactType and * ArtifactValue. @@ -668,7 +658,7 @@ public abstract class AbstractSqlEamDb implements EamDb { PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String tableName = artifactTypeToTableName(eamArtifact.getArtifactType()); + String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()); StringBuilder sql = new StringBuilder(); sql.append("SELECT count(*) FROM "); sql.append(tableName); @@ -676,7 +666,7 @@ public abstract class AbstractSqlEamDb implements EamDb { try { preparedStatement = conn.prepareStatement(sql.toString()); - preparedStatement.setString(1, eamArtifact.getArtifactValue()); + preparedStatement.setString(1, eamArtifact.getCorrelationValue()); resultSet = preparedStatement.executeQuery(); resultSet.next(); instanceCount = resultSet.getLong(1); @@ -698,7 +688,7 @@ public abstract class AbstractSqlEamDb implements EamDb { * case_id/datasource_id tuples in the database) expressed as a percentage. * * @param eamArtifact Artifact with artifactType and artifactValue to search - * for + * for * * @return Int between 0 and 100 */ @@ -716,7 +706,7 @@ public abstract class AbstractSqlEamDb implements EamDb { * the given artifact. * * @param eamArtifact Artifact with artifactType and artifactValue to search - * for + * for * * @return Number of unique tuples */ @@ -728,7 +718,7 @@ public abstract class AbstractSqlEamDb implements EamDb { PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String tableName = artifactTypeToTableName(eamArtifact.getArtifactType()); + String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()); StringBuilder sql = new StringBuilder(); sql.append("SELECT count(*) FROM (SELECT DISTINCT case_id, data_source_id FROM "); sql.append(tableName); @@ -738,7 +728,7 @@ public abstract class AbstractSqlEamDb implements EamDb { try { preparedStatement = conn.prepareStatement(sql.toString()); - preparedStatement.setString(1, eamArtifact.getArtifactValue()); + preparedStatement.setString(1, eamArtifact.getCorrelationValue()); resultSet = preparedStatement.executeQuery(); resultSet.next(); instanceCount = resultSet.getLong(1); @@ -764,7 +754,7 @@ public abstract class AbstractSqlEamDb implements EamDb { Connection conn = connect(); Long instanceCount = 0L; - List artifactTypes = getCorrelationArtifactTypes(); + List artifactTypes = getCorrelationTypes(); PreparedStatement preparedStatement = null; ResultSet resultSet = null; @@ -772,8 +762,7 @@ public abstract class AbstractSqlEamDb implements EamDb { sql.append("SELECT 0 "); for (EamArtifact.Type type : artifactTypes) { - // TODO: when/if custom types are allowed, make this more safe. - String table_name = type.getName() + "_instances"; + String table_name = EamDbUtil.correlationTypeToInstanceTableName(type); sql.append("+ (SELECT count(*) FROM (SELECT DISTINCT case_id, data_source_id FROM "); sql.append(table_name); @@ -806,7 +795,7 @@ public abstract class AbstractSqlEamDb implements EamDb { * @param eamInstance Instance with caseName and dataSource to search for * * @param eamInstance Instance with caseDisplayName and dataSource to search - * for + * for * * @return Number of artifact instances having caseDisplayName and * dataSource @@ -816,7 +805,7 @@ public abstract class AbstractSqlEamDb implements EamDb { Connection conn = connect(); Long instanceCount = 0L; - List artifactTypes = getCorrelationArtifactTypes(); + List artifactTypes = getCorrelationTypes(); PreparedStatement preparedStatement = null; ResultSet resultSet = null; @@ -825,7 +814,7 @@ public abstract class AbstractSqlEamDb implements EamDb { sql.append("SELECT 0 "); for (EamArtifact.Type type : artifactTypes) { - String table_name = type.getName() + "_instances"; + String table_name = EamDbUtil.correlationTypeToInstanceTableName(type); sql.append("+ (SELECT count(*) FROM "); sql.append(table_name); @@ -865,7 +854,7 @@ public abstract class AbstractSqlEamDb implements EamDb { public void prepareBulkArtifact(EamArtifact eamArtifact) throws EamDbException { synchronized (bulkArtifacts) { - bulkArtifacts.get(eamArtifact.getArtifactType().getName()).add(eamArtifact); + bulkArtifacts.get(eamArtifact.getCorrelationType().getDbTableName()).add(eamArtifact); bulkArtifactsCount++; if (bulkArtifactsCount >= bulkArtifactsThreshold) { @@ -874,13 +863,20 @@ public abstract class AbstractSqlEamDb implements EamDb { } } + /** + * Get the conflict clause for bulk update statements + * + * @return The conflict clause for bulk update statements + */ + protected abstract String getConflictClause(); + /** * Executes a bulk insert of the eamArtifacts added from the * prepareBulkArtifact() method */ @Override public void bulkInsertArtifacts() throws EamDbException { - List artifactTypes = getCorrelationArtifactTypes(); + List artifactTypes = getCorrelationTypes(); Connection conn = connect(); PreparedStatement bulkPs = null; @@ -893,24 +889,25 @@ public abstract class AbstractSqlEamDb implements EamDb { for (EamArtifact.Type type : artifactTypes) { - String tableName = artifactTypeToTableName(type); + String tableName = EamDbUtil.correlationTypeToInstanceTableName(type); StringBuilder sql = new StringBuilder(); sql.append("INSERT INTO "); sql.append(tableName); sql.append(" (case_id, data_source_id, value, file_path, known_status, comment) "); sql.append("VALUES ((SELECT id FROM cases WHERE case_uid=? LIMIT 1), "); - sql.append("(SELECT id FROM data_sources WHERE device_id=? LIMIT 1), ?, ?, ?, ?)"); + sql.append("(SELECT id FROM data_sources WHERE device_id=? LIMIT 1), ?, ?, ?, ?) "); + sql.append(getConflictClause()); bulkPs = conn.prepareStatement(sql.toString()); - Collection eamArtifacts = bulkArtifacts.get(type.getName()); + Collection eamArtifacts = bulkArtifacts.get(type.getDbTableName()); for (EamArtifact eamArtifact : eamArtifacts) { List eamInstances = eamArtifact.getInstances(); for (EamArtifactInstance eamInstance : eamInstances) { bulkPs.setString(1, eamInstance.getEamCase().getCaseUUID()); bulkPs.setString(2, eamInstance.getEamDataSource().getDeviceID()); - bulkPs.setString(3, eamArtifact.getArtifactValue()); + bulkPs.setString(3, eamArtifact.getCorrelationValue()); bulkPs.setString(4, eamInstance.getFilePath()); bulkPs.setString(5, eamInstance.getKnownStatus().name()); bulkPs.setString(6, eamInstance.getComment()); @@ -919,7 +916,7 @@ public abstract class AbstractSqlEamDb implements EamDb { } bulkPs.executeBatch(); - bulkArtifacts.get(type.getName()).clear(); + bulkArtifacts.get(type.getDbTableName()).clear(); } // Reset state @@ -949,7 +946,8 @@ public abstract class AbstractSqlEamDb implements EamDb { try { String sql = "INSERT INTO cases(case_uid, org_id, case_name, creation_date, case_number, " + "examiner_name, examiner_email, examiner_phone, notes) " - + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) " + + getConflictClause(); bulkPs = conn.prepareStatement(sql); for (EamCase eamCase : cases) { @@ -987,8 +985,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } /** - * Sets an eamArtifact instance as knownStatus = "Bad". If eamArtifact exists, - * it is updated. If eamArtifact does not exist nothing happens + * Sets an eamArtifact instance as knownStatus = "Bad". If eamArtifact + * exists, it is updated. If eamArtifact does not exist nothing happens * * @param eamArtifact Artifact containing exactly one (1) ArtifactInstance. */ @@ -1007,7 +1005,7 @@ public abstract class AbstractSqlEamDb implements EamDb { PreparedStatement preparedQuery = null; ResultSet resultSet = null; - String tableName = artifactTypeToTableName(eamArtifact.getArtifactType()); + String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()); StringBuilder sqlQuery = new StringBuilder(); sqlQuery.append("SELECT id FROM "); @@ -1027,20 +1025,20 @@ public abstract class AbstractSqlEamDb implements EamDb { preparedQuery = conn.prepareStatement(sqlQuery.toString()); preparedQuery.setString(1, eamInstance.getEamCase().getCaseUUID()); preparedQuery.setString(2, eamInstance.getEamDataSource().getDeviceID()); - preparedQuery.setString(3, eamArtifact.getArtifactValue()); + preparedQuery.setString(3, eamArtifact.getCorrelationValue()); preparedQuery.setString(4, eamInstance.getFilePath()); resultSet = preparedQuery.executeQuery(); if (resultSet.next()) { int instance_id = resultSet.getInt("id"); preparedUpdate = conn.prepareStatement(sqlUpdate.toString()); - preparedUpdate.setString(1, EamArtifactInstance.KnownStatus.BAD.name()); + preparedUpdate.setString(1, TskData.FileKnown.BAD.name()); preparedUpdate.setString(2, eamInstance.getComment()); preparedUpdate.setInt(3, instance_id); preparedUpdate.executeUpdate(); } else { - eamArtifact.getInstances().get(0).setKnownStatus(EamArtifactInstance.KnownStatus.BAD); + eamArtifact.getInstances().get(0).setKnownStatus(TskData.FileKnown.BAD); addArtifact(eamArtifact); } @@ -1055,7 +1053,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } /** - * Gets list of matching eamArtifact instances that have knownStatus = "Bad". + * Gets list of matching eamArtifact instances that have knownStatus = + * "Bad". * * @param eamArtifact Artifact containing Type and Value * @@ -1071,7 +1070,7 @@ public abstract class AbstractSqlEamDb implements EamDb { PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String tableName = artifactTypeToTableName(eamArtifact.getArtifactType()); + String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()); StringBuilder sql = new StringBuilder(); sql.append("SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment FROM "); sql.append(tableName); @@ -1085,11 +1084,11 @@ public abstract class AbstractSqlEamDb implements EamDb { try { preparedStatement = conn.prepareStatement(sql.toString()); - preparedStatement.setString(1, eamArtifact.getArtifactValue()); - preparedStatement.setString(2, EamArtifactInstance.KnownStatus.BAD.name()); + preparedStatement.setString(1, eamArtifact.getCorrelationValue()); + preparedStatement.setString(2, TskData.FileKnown.BAD.name()); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { - artifactInstance = getEnterpriseArtifactManagerArtifactInstanceFromResultSet(resultSet); + artifactInstance = getEamArtifactInstanceFromResultSet(resultSet); artifactInstances.add(artifactInstance); } } catch (SQLException ex) { @@ -1118,7 +1117,7 @@ public abstract class AbstractSqlEamDb implements EamDb { PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String tableName = artifactTypeToTableName(eamArtifact.getArtifactType()); + String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()); StringBuilder sql = new StringBuilder(); sql.append("SELECT count(*) FROM "); sql.append(tableName); @@ -1126,8 +1125,8 @@ public abstract class AbstractSqlEamDb implements EamDb { try { preparedStatement = conn.prepareStatement(sql.toString()); - preparedStatement.setString(1, eamArtifact.getArtifactValue()); - preparedStatement.setString(2, EamArtifactInstance.KnownStatus.BAD.name()); + preparedStatement.setString(1, eamArtifact.getCorrelationValue()); + preparedStatement.setString(2, TskData.FileKnown.BAD.name()); resultSet = preparedStatement.executeQuery(); resultSet.next(); badInstances = resultSet.getLong(1); @@ -1162,7 +1161,7 @@ public abstract class AbstractSqlEamDb implements EamDb { PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String tableName = artifactTypeToTableName(eamArtifact.getArtifactType()); + String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()); StringBuilder sql = new StringBuilder(); sql.append("SELECT DISTINCT case_name FROM "); sql.append(tableName); @@ -1176,8 +1175,8 @@ public abstract class AbstractSqlEamDb implements EamDb { try { preparedStatement = conn.prepareStatement(sql.toString()); - preparedStatement.setString(1, eamArtifact.getArtifactValue()); - preparedStatement.setString(2, EamArtifactInstance.KnownStatus.BAD.name()); + preparedStatement.setString(1, eamArtifact.getCorrelationValue()); + preparedStatement.setString(2, TskData.FileKnown.BAD.name()); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { caseNames.add(resultSet.getString("case_name")); @@ -1194,17 +1193,17 @@ public abstract class AbstractSqlEamDb implements EamDb { } /** - * Is the artifact globally known as bad? + * Is the artifact known as bad according to the reference entries? * * @param eamArtifact Artifact containing Type and Value * * @return Global known status of the artifact */ @Override - public boolean isArtifactGlobalKnownBad(EamArtifact eamArtifact) throws EamDbException { + public boolean isArtifactlKnownBadByReference(EamArtifact eamArtifact) throws EamDbException { - // TEMP: Only support file types - if (!eamArtifact.getArtifactType().equals(getCorrelationArtifactTypeByName("FILES"))) { + // TEMP: Only support file correlation type + if (eamArtifact.getCorrelationType().getId() != EamArtifact.FILES_TYPE_ID) { return false; } @@ -1213,17 +1212,17 @@ public abstract class AbstractSqlEamDb implements EamDb { Long badInstances = 0L; PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String sql = "SELECT count(*) FROM global_files WHERE value=? AND known_status=?"; + String sql = "SELECT count(*) FROM %s WHERE value=? AND known_status=?"; try { - preparedStatement = conn.prepareStatement(sql); - preparedStatement.setString(1, eamArtifact.getArtifactValue()); - preparedStatement.setString(2, EamArtifactInstance.KnownStatus.BAD.name()); + preparedStatement = conn.prepareStatement(String.format(sql, EamDbUtil.correlationTypeToReferenceTableName(eamArtifact.getCorrelationType()))); + preparedStatement.setString(1, eamArtifact.getCorrelationValue()); + preparedStatement.setString(2, TskData.FileKnown.BAD.name()); resultSet = preparedStatement.executeQuery(); resultSet.next(); badInstances = resultSet.getLong(1); } catch (SQLException ex) { - throw new EamDbException("Error determining if artifact is globally known bad.", ex); // NON-NLS + throw new EamDbException("Error determining if artifact is known bad by reference.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closeResultSet(resultSet); @@ -1283,7 +1282,7 @@ public abstract class AbstractSqlEamDb implements EamDb { preparedStatement = conn.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { - orgs.add(getEnterpriseArtifactManagerOrganizationFromResultSet(resultSet)); + orgs.add(getEamOrganizationFromResultSet(resultSet)); } return orgs; @@ -1318,7 +1317,7 @@ public abstract class AbstractSqlEamDb implements EamDb { preparedStatement.setInt(1, orgID); resultSet = preparedStatement.executeQuery(); resultSet.next(); - return getEnterpriseArtifactManagerOrganizationFromResultSet(resultSet); + return getEamOrganizationFromResultSet(resultSet); } catch (SQLException ex) { throw new EamDbException("Error getting organization by id.", ex); // NON-NLS @@ -1339,14 +1338,14 @@ public abstract class AbstractSqlEamDb implements EamDb { * @throws EamDbException */ @Override - public int newGlobalSet(EamGlobalSet eamGlobalSet) throws EamDbException { + public int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException { Connection conn = connect(); PreparedStatement preparedStatement1 = null; PreparedStatement preparedStatement2 = null; ResultSet resultSet = null; - String sql1 = "INSERT INTO global_reference_sets(org_id, set_name, version, import_date) VALUES (?, ?, ?, ?)"; - String sql2 = "SELECT id FROM global_reference_sets WHERE org_id=? AND set_name=? AND version=? AND import_date=? LIMIT 1"; + String sql1 = "INSERT INTO reference_sets(org_id, set_name, version, import_date) VALUES (?, ?, ?, ?)"; + String sql2 = "SELECT id FROM reference_sets WHERE org_id=? AND set_name=? AND version=? AND import_date=? LIMIT 1"; try { preparedStatement1 = conn.prepareStatement(sql1); @@ -1378,31 +1377,31 @@ public abstract class AbstractSqlEamDb implements EamDb { } /** - * Get a global set by ID + * Get a reference set by ID * - * @param globalSetID The ID to look up + * @param referenceSetID The ID to look up * * @return The global set associated with the ID * * @throws EamDbException */ @Override - public EamGlobalSet getGlobalSetByID(int globalSetID) throws EamDbException { + public EamGlobalSet getReferenceSetByID(int referenceSetID) throws EamDbException { Connection conn = connect(); PreparedStatement preparedStatement1 = null; ResultSet resultSet = null; - String sql1 = "SELECT * FROM global_reference_sets WHERE id=?"; + String sql1 = "SELECT * FROM reference_sets WHERE id=?"; try { preparedStatement1 = conn.prepareStatement(sql1); - preparedStatement1.setInt(1, globalSetID); + preparedStatement1.setInt(1, referenceSetID); resultSet = preparedStatement1.executeQuery(); resultSet.next(); - return getEnterpriseArtifactManagerGlobalSetFromResultSet(resultSet); + return getEamGlobalSetFromResultSet(resultSet); } catch (SQLException ex) { - throw new EamDbException("Error getting global set by id.", ex); // NON-NLS + throw new EamDbException("Error getting reference set by id.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement1); EamDbUtil.closeResultSet(resultSet); @@ -1411,29 +1410,30 @@ public abstract class AbstractSqlEamDb implements EamDb { } /** - * Add a new global file instance + * Add a new reference instance * - * @param eamGlobalFileInstance The global file instance to add + * @param eamGlobalFileInstance The reference instance to add + * @param correlationType Correlation Type that this Reference Instance is * * @throws EamDbException */ @Override - public void addGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException { + public void addReferenceInstance(EamGlobalFileInstance eamGlobalFileInstance, EamArtifact.Type correlationType) throws EamDbException { Connection conn = connect(); PreparedStatement preparedStatement = null; - String sql = "INSERT INTO global_files(global_reference_set_id, value, known_status, comment) VALUES (?, ?, ?, ?)"; + String sql = "INSERT INTO %s(reference_set_id, value, known_status, comment) VALUES (?, ?, ?, ?)"; try { - preparedStatement = conn.prepareStatement(sql); + preparedStatement = conn.prepareStatement(String.format(sql, EamDbUtil.correlationTypeToReferenceTableName(correlationType))); preparedStatement.setInt(1, eamGlobalFileInstance.getGlobalSetID()); preparedStatement.setString(2, eamGlobalFileInstance.getMD5Hash()); preparedStatement.setString(3, eamGlobalFileInstance.getKnownStatus().name()); preparedStatement.setString(4, eamGlobalFileInstance.getComment()); preparedStatement.executeUpdate(); } catch (SQLException ex) { - throw new EamDbException("Error inserting new global file instance into global_files table.", ex); // NON-NLS + throw new EamDbException("Error inserting new reference instance into reference_ table.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closeConnection(conn); @@ -1441,97 +1441,69 @@ public abstract class AbstractSqlEamDb implements EamDb { } /** - * Add a new global file instance to the bulk collection - * - * @param eamGlobalFileInstance The global file instance to add - * @throws EamDbException + * Insert the bulk collection of Reference Type Instances + * + * @throws EamDbException */ @Override - public void prepareGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException { - synchronized (bulkGlobalArtifacts) { - bulkGlobalArtifacts.get("FILES").add(eamGlobalFileInstance); // NON-NLS - bulkGlobalArtifactsCount++; - - if (bulkGlobalArtifactsCount >= bulkArtifactsThreshold) { - bulkInsertGlobalFileInstances(); - } - } - } - - /** - * Insert the bulk collection of Global File Instances - * - * @throws EamDbException - */ - @Override - public void bulkInsertGlobalFileInstances() throws EamDbException { - List artifactTypes = getCorrelationArtifactTypes(); - + public void bulkInsertReferenceTypeEntries(Set globalInstances, EamArtifact.Type contentType) throws EamDbException { Connection conn = connect(); - synchronized (bulkGlobalArtifacts) { - if (bulkGlobalArtifactsCount == 0) { - return; + + PreparedStatement bulkPs = null; + try { + // FUTURE: have a separate global_files table for each Type. + String sql = "INSERT INTO %s(reference_set_id, value, known_status, comment) VALUES (?, ?, ?, ?) " + + getConflictClause(); + + bulkPs = conn.prepareStatement(String.format(sql, EamDbUtil.correlationTypeToReferenceTableName(contentType))); + + for (EamGlobalFileInstance globalInstance : globalInstances) { + bulkPs.setInt(1, globalInstance.getGlobalSetID()); + bulkPs.setString(2, globalInstance.getMD5Hash()); + bulkPs.setString(3, globalInstance.getKnownStatus().name()); + bulkPs.setString(4, globalInstance.getComment()); + bulkPs.addBatch(); } - PreparedStatement bulkPs = null; - try { - for (EamArtifact.Type type : artifactTypes) { - String sql = "INSERT INTO global_files(global_reference_set_id, value, known_status, comment) VALUES (?, ?, ?, ?)"; - - bulkPs = conn.prepareStatement(sql); - - Collection eamGlobalFileInstances = bulkGlobalArtifacts.get(type.getName()); - for (EamGlobalFileInstance eamGlobalFileInstance : eamGlobalFileInstances) { - - bulkPs.setInt(1, eamGlobalFileInstance.getGlobalSetID()); - bulkPs.setString(2, eamGlobalFileInstance.getMD5Hash()); - bulkPs.setString(3, eamGlobalFileInstance.getKnownStatus().name()); - bulkPs.setString(4, eamGlobalFileInstance.getComment()); - bulkPs.addBatch(); - } - - bulkPs.executeBatch(); - bulkGlobalArtifacts.get(type.getName()).clear(); - } - - // Reset state - bulkGlobalArtifactsCount = 0; - } catch (SQLException ex) { - throw new EamDbException("Error inserting bulk artifacts.", ex); // NON-NLS - } finally { - EamDbUtil.closePreparedStatement(bulkPs); - EamDbUtil.closeConnection(conn); - } + bulkPs.executeBatch(); + } catch (SQLException ex) { + throw new EamDbException("Error inserting bulk artifacts.", ex); // NON-NLS + } finally { + EamDbUtil.closePreparedStatement(bulkPs); + EamDbUtil.closeConnection(conn); } } /** - * Get all global file instances having a given MD5 hash - * - * @param MD5Hash The hash to lookup - * @return List of all global file instances with a given hash - * @throws EamDbException + * Get all reference entries having a given correlation type and value + * + * @param aType Type to use for matching + * @param aValue Value to use for matching + * + * @return List of all global file instances with a type and value + * + * @throws EamDbException */ @Override - public List getGlobalFileInstancesByHash(String MD5Hash) throws EamDbException { + public List getReferenceInstancesByTypeValue(EamArtifact.Type aType, String aValue) throws EamDbException { Connection conn = connect(); List globalFileInstances = new ArrayList<>(); PreparedStatement preparedStatement1 = null; ResultSet resultSet = null; - String sql1 = "SELECT * FROM global_files WHERE value=?"; + String sql1 = "SELECT * FROM %s WHERE value=?"; try { - preparedStatement1 = conn.prepareStatement(sql1); - preparedStatement1.setString(1, MD5Hash); + preparedStatement1 = conn.prepareStatement(String.format(sql1, EamDbUtil.correlationTypeToReferenceTableName(aType))); + preparedStatement1.setString(1, aValue); resultSet = preparedStatement1.executeQuery(); while (resultSet.next()) { - globalFileInstances.add(getEnterpriseArtifactManagerGlobalFileInstanceFromResultSet(resultSet)); + globalFileInstances.add(getEamGlobalFileInstanceFromResultSet(resultSet)); } return globalFileInstances; } catch (SQLException ex) { - throw new EamDbException("Error getting global set by id.", ex); // NON-NLS + throw new EamDbException("Error getting reference instances by type and value.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement1); EamDbUtil.closeResultSet(resultSet); @@ -1543,30 +1515,64 @@ public abstract class AbstractSqlEamDb implements EamDb { * Add a new EamArtifact.Type to the db. * * @param newType New type to add. - * @throws EamDbException + * + * @return ID of this new Correlation Type + * @throws EamDbException */ @Override - public void newCorrelationArtifactType(EamArtifact.Type newType) throws EamDbException { + public int newCorrelationType(EamArtifact.Type newType) throws EamDbException { Connection conn = connect(); PreparedStatement preparedStatement = null; - - String sql = "INSERT INTO artifact_types(name, supported, enabled) VALUES (?, ?, ?)"; + PreparedStatement preparedStatementQuery = null; + ResultSet resultSet = null; + int typeId = 0; + String insertSql; + String querySql; + // if we have a known ID, use it, if not (is -1) let the db assign it. + if (-1 == newType.getId()) { + insertSql = "INSERT INTO correlation_types(display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?)"; + } else { + insertSql = "INSERT INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?)"; + } + querySql = "SELECT id FROM correlation_types WHERE display_name=? AND db_table_name=?"; try { - preparedStatement = conn.prepareStatement(sql); + preparedStatement = conn.prepareStatement(insertSql); - preparedStatement.setString(1, newType.getName()); - preparedStatement.setInt(2, newType.isSupported() ? 1 : 0); - preparedStatement.setInt(3, newType.isEnabled() ? 1 : 0); + if (-1 == newType.getId()) { + preparedStatement.setString(1, newType.getDisplayName()); + preparedStatement.setString(2, newType.getDbTableName()); + preparedStatement.setInt(3, newType.isSupported() ? 1 : 0); + preparedStatement.setInt(4, newType.isEnabled() ? 1 : 0); + } else { + preparedStatement.setInt(1, newType.getId()); + preparedStatement.setString(2, newType.getDisplayName()); + preparedStatement.setString(3, newType.getDbTableName()); + preparedStatement.setInt(4, newType.isSupported() ? 1 : 0); + preparedStatement.setInt(5, newType.isEnabled() ? 1 : 0); + } preparedStatement.executeUpdate(); + + preparedStatementQuery = conn.prepareStatement(querySql); + preparedStatementQuery.setString(1, newType.getDisplayName()); + preparedStatementQuery.setString(2, newType.getDbTableName()); + + resultSet = preparedStatementQuery.executeQuery(); + if (resultSet.next()) { + EamArtifact.Type correlationType = getCorrelationTypeFromResultSet(resultSet); + typeId = correlationType.getId(); + } } catch (SQLException ex) { - throw new EamDbException("Error inserting new correlation artifact type.", ex); // NON-NLS + throw new EamDbException("Error inserting new correlation type.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement); + EamDbUtil.closePreparedStatement(preparedStatementQuery); + EamDbUtil.closeResultSet(resultSet); EamDbUtil.closeConnection(conn); } + return typeId; } /** @@ -1575,27 +1581,28 @@ public abstract class AbstractSqlEamDb implements EamDb { * * @return List of EamArtifact.Type's. If none are defined in the database, * the default list will be returned. - * @throws EamDbException + * + * @throws EamDbException */ @Override - public List getCorrelationArtifactTypes() throws EamDbException { + public List getCorrelationTypes() throws EamDbException { Connection conn = connect(); List aTypes = new ArrayList<>(); PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String sql = "SELECT * FROM artifact_types"; + String sql = "SELECT * FROM correlation_types"; try { preparedStatement = conn.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { - aTypes.add(getCorrelationArtifactTypeFromResultSet(resultSet)); + aTypes.add(getCorrelationTypeFromResultSet(resultSet)); } return aTypes; } catch (SQLException ex) { - throw new EamDbException("Error getting all correlation artifact types.", ex); // NON-NLS + throw new EamDbException("Error getting all correlation types.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closeResultSet(resultSet); @@ -1609,27 +1616,28 @@ public abstract class AbstractSqlEamDb implements EamDb { * * @return List of enabled EamArtifact.Type's. If none are defined in the * database, the default list will be returned. - * @throws EamDbException + * + * @throws EamDbException */ @Override - public List getEnabledCorrelationArtifactTypes() throws EamDbException { + public List getEnabledCorrelationTypes() throws EamDbException { Connection conn = connect(); List aTypes = new ArrayList<>(); PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String sql = "SELECT * FROM artifact_types WHERE enabled=1"; + String sql = "SELECT * FROM correlation_types WHERE enabled=1"; try { preparedStatement = conn.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { - aTypes.add(getCorrelationArtifactTypeFromResultSet(resultSet)); + aTypes.add(getCorrelationTypeFromResultSet(resultSet)); } return aTypes; } catch (SQLException ex) { - throw new EamDbException("Error getting enabled correlation artifact types.", ex); // NON-NLS + throw new EamDbException("Error getting enabled correlation types.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closeResultSet(resultSet); @@ -1643,27 +1651,28 @@ public abstract class AbstractSqlEamDb implements EamDb { * * @return List of supported EamArtifact.Type's. If none are defined in the * database, the default list will be returned. - * @throws EamDbException + * + * @throws EamDbException */ @Override - public List getSupportedCorrelationArtifactTypes() throws EamDbException { + public List getSupportedCorrelationTypes() throws EamDbException { Connection conn = connect(); List aTypes = new ArrayList<>(); PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String sql = "SELECT * FROM artifact_types WHERE supported=1"; + String sql = "SELECT * FROM correlation_types WHERE supported=1"; try { preparedStatement = conn.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { - aTypes.add(getCorrelationArtifactTypeFromResultSet(resultSet)); + aTypes.add(getCorrelationTypeFromResultSet(resultSet)); } return aTypes; } catch (SQLException ex) { - throw new EamDbException("Error getting supported correlation artifact types.", ex); // NON-NLS + throw new EamDbException("Error getting supported correlation types.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closeResultSet(resultSet); @@ -1675,25 +1684,27 @@ public abstract class AbstractSqlEamDb implements EamDb { * Update a EamArtifact.Type. * * @param aType EamArtifact.Type to update. - * @throws EamDbException + * + * @throws EamDbException */ @Override - public void updateCorrelationArtifactType(EamArtifact.Type aType) throws EamDbException { + public void updateCorrelationType(EamArtifact.Type aType) throws EamDbException { Connection conn = connect(); PreparedStatement preparedStatement = null; - String sql = "UPDATE artifact_types SET name=?, supported=?, enabled=? WHERE id=?"; + String sql = "UPDATE correlation_types SET display_name=?, db_table_name=?, supported=?, enabled=? WHERE id=?"; try { preparedStatement = conn.prepareStatement(sql); - preparedStatement.setString(1, aType.getName()); - preparedStatement.setInt(2, aType.isSupported() ? 1 : 0); - preparedStatement.setInt(3, aType.isEnabled() ? 1 : 0); - preparedStatement.setInt(4, aType.getId()); + preparedStatement.setString(1, aType.getDisplayName()); + preparedStatement.setString(2, aType.getDbTableName()); + preparedStatement.setInt(3, aType.isSupported() ? 1 : 0); + preparedStatement.setInt(4, aType.isEnabled() ? 1 : 0); + preparedStatement.setInt(5, aType.getId()); preparedStatement.executeUpdate(); } catch (SQLException ex) { - throw new EamDbException("Error getting correlation artifact type by name.", ex); // NON-NLS + throw new EamDbException("Error updating correlation type.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closeConnection(conn); @@ -1702,32 +1713,33 @@ public abstract class AbstractSqlEamDb implements EamDb { } /** - * Get the EamArtifact.Type that has name of typeName. + * Get the EamArtifact.Type that has the given Type.Id. * - * @param typeName Name of Type to get + * @param typeId Type.Id of Correlation Type to get * * @return EamArtifact.Type or null if it doesn't exist. - * @throws EamDbException + * + * @throws EamDbException */ @Override - public EamArtifact.Type getCorrelationArtifactTypeByName(String typeName) throws EamDbException { + public EamArtifact.Type getCorrelationTypeById(int typeId) throws EamDbException { Connection conn = connect(); EamArtifact.Type aType; PreparedStatement preparedStatement = null; ResultSet resultSet = null; - String sql = "SELECT * FROM artifact_types WHERE name=?"; + String sql = "SELECT * FROM correlation_types WHERE id=?"; try { preparedStatement = conn.prepareStatement(sql); - preparedStatement.setString(1, typeName); + preparedStatement.setInt(1, typeId); resultSet = preparedStatement.executeQuery(); resultSet.next(); - aType = getCorrelationArtifactTypeFromResultSet(resultSet); + aType = getCorrelationTypeFromResultSet(resultSet); return aType; } catch (SQLException ex) { - throw new EamDbException("Error getting correlation artifact type by name.", ex); // NON-NLS + throw new EamDbException("Error getting correlation type by id.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closeResultSet(resultSet); @@ -1745,7 +1757,7 @@ public abstract class AbstractSqlEamDb implements EamDb { * * @throws SQLException when an expected column name is not in the resultSet */ - private EamCase getEnterpriseArtifactManagerCaseFromResultSet(ResultSet resultSet) throws SQLException { + private EamCase getEamCaseFromResultSet(ResultSet resultSet) throws SQLException { if (null == resultSet) { return null; } @@ -1775,7 +1787,7 @@ public abstract class AbstractSqlEamDb implements EamDb { return eamCase; } - private EamDataSource getEnterpriseArtifactManagerDataSourceFromResultSet(ResultSet resultSet) throws SQLException { + private EamDataSource getEamDataSourceFromResultSet(ResultSet resultSet) throws SQLException { if (null == resultSet) { return null; } @@ -1789,20 +1801,20 @@ public abstract class AbstractSqlEamDb implements EamDb { return eamDataSource; } - private EamArtifact.Type getCorrelationArtifactTypeFromResultSet(ResultSet resultSet) throws SQLException { + private EamArtifact.Type getCorrelationTypeFromResultSet(ResultSet resultSet) throws SQLException { if (null == resultSet) { return null; } EamArtifact.Type eamArtifactType = new EamArtifact.Type( resultSet.getInt("id"), - resultSet.getString("name"), + resultSet.getString("display_name"), + resultSet.getString("db_table_name"), resultSet.getBoolean("supported"), resultSet.getBoolean("enabled") ); return eamArtifactType; - } /** @@ -1815,7 +1827,7 @@ public abstract class AbstractSqlEamDb implements EamDb { * * @throws SQLException when an expected column name is not in the resultSet */ - private EamArtifactInstance getEnterpriseArtifactManagerArtifactInstanceFromResultSet(ResultSet resultSet) throws SQLException { + private EamArtifactInstance getEamArtifactInstanceFromResultSet(ResultSet resultSet) throws SQLException { if (null == resultSet) { return null; } @@ -1824,14 +1836,14 @@ public abstract class AbstractSqlEamDb implements EamDb { new EamDataSource(resultSet.getString("device_id"), resultSet.getString("name")), resultSet.getString("file_path"), resultSet.getString("comment"), - EamArtifactInstance.KnownStatus.valueOf(resultSet.getString("known_status")), + TskData.FileKnown.valueOf(resultSet.getString("known_status")), EamArtifactInstance.GlobalStatus.LOCAL ); return eamArtifactInstance; } - private EamOrganization getEnterpriseArtifactManagerOrganizationFromResultSet(ResultSet resultSet) throws SQLException { + private EamOrganization getEamOrganizationFromResultSet(ResultSet resultSet) throws SQLException { if (null == resultSet) { return null; } @@ -1847,7 +1859,7 @@ public abstract class AbstractSqlEamDb implements EamDb { return eamOrganization; } - private EamGlobalSet getEnterpriseArtifactManagerGlobalSetFromResultSet(ResultSet resultSet) throws SQLException { + private EamGlobalSet getEamGlobalSetFromResultSet(ResultSet resultSet) throws SQLException { if (null == resultSet) { return null; } @@ -1863,16 +1875,16 @@ public abstract class AbstractSqlEamDb implements EamDb { return eamGlobalSet; } - private EamGlobalFileInstance getEnterpriseArtifactManagerGlobalFileInstanceFromResultSet(ResultSet resultSet) throws SQLException { + private EamGlobalFileInstance getEamGlobalFileInstanceFromResultSet(ResultSet resultSet) throws SQLException { if (null == resultSet) { return null; } EamGlobalFileInstance eamGlobalFileInstance = new EamGlobalFileInstance( resultSet.getInt("id"), - resultSet.getInt("global_reference_set_id"), + resultSet.getInt("reference_set_id"), resultSet.getString("value"), - EamArtifactInstance.KnownStatus.valueOf(resultSet.getString("known_status")), + TskData.FileKnown.valueOf(resultSet.getString("known_status")), resultSet.getString("comment") ); diff --git a/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifact.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifact.java new file mode 100644 index 0000000000..f8ad30e051 --- /dev/null +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifact.java @@ -0,0 +1,336 @@ +/* + * Central Repository + * + * Copyright 2015-2017 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.centralrepository.datamodel; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import org.openide.util.NbBundle.Messages; + +/** + * + * Used to store info about a specific artifact. + */ +public class EamArtifact implements Serializable { + + private static final long serialVersionUID = 1L; + + private String ID; + private String correlationValue; + private Type correlationType; + private final List artifactInstances; + + // Type ID's for Default Correlation Types + public static final int FILES_TYPE_ID = 0; + public static final int DOMAIN_TYPE_ID = 1; + public static final int EMAIL_TYPE_ID = 2; + public static final int PHONE_TYPE_ID = 3; + public static final int USBID_TYPE_ID = 4; + + /** + * Load the default correlation types + */ + @Messages({"CorrelationType.FILES.displayName=Files", + "CorrelationType.DOMAIN.displayName=Domains", + "CorrelationType.EMAIL.displayName=Email Addresses", + "CorrelationType.PHONE.displayName=Phone Numbers", + "CorrelationType.USBID.displayName=USB Devices"}) + public static List getDefaultCorrelationTypes() { + List DEFAULT_CORRELATION_TYPES = new ArrayList<>(); + DEFAULT_CORRELATION_TYPES.add(new EamArtifact.Type(FILES_TYPE_ID, Bundle.CorrelationType_FILES_displayName(), "file", true, true)); // NON-NLS + DEFAULT_CORRELATION_TYPES.add(new EamArtifact.Type(DOMAIN_TYPE_ID, Bundle.CorrelationType_DOMAIN_displayName(), "domain", true, false)); // NON-NLS + DEFAULT_CORRELATION_TYPES.add(new EamArtifact.Type(EMAIL_TYPE_ID, Bundle.CorrelationType_EMAIL_displayName(), "email_address", true, false)); // NON-NLS + DEFAULT_CORRELATION_TYPES.add(new EamArtifact.Type(PHONE_TYPE_ID, Bundle.CorrelationType_PHONE_displayName(), "phone_number", true, false)); // NON-NLS + DEFAULT_CORRELATION_TYPES.add(new EamArtifact.Type(USBID_TYPE_ID, Bundle.CorrelationType_USBID_displayName(), "usb_devices", true, false)); // NON-NLS + return DEFAULT_CORRELATION_TYPES; + } + + public EamArtifact(Type correlationType, String correlationValue) { + this.ID = ""; + this.correlationType = correlationType; + this.correlationValue = correlationValue; + this.artifactInstances = new ArrayList<>(); + } + + public Boolean equals(EamArtifact otherArtifact) { + return ((this.getID().equals(otherArtifact.getID())) + && (this.getCorrelationType().equals(otherArtifact.getCorrelationType())) + && (this.getCorrelationValue().equals(otherArtifact.getCorrelationValue())) + && (this.getInstances().equals(otherArtifact.getInstances()))); + } + + @Override + public String toString() { + String result = this.getID() + + this.getCorrelationType().toString() + + this.getCorrelationValue(); + result = this.getInstances().stream().map((inst) -> inst.toString()).reduce(result, String::concat); + return result; + } + + /** + * @return the ID + */ + public String getID() { + return ID; + } + + /** + * @param ID the ID to set + */ + public void setID(String ID) { + this.ID = ID; + } + + /** + * @return the correlationValue + */ + public String getCorrelationValue() { + return correlationValue; + } + + /** + * @param correlationValue the correlationValue to set + */ + public void setCorrelationValue(String correlationValue) { + this.correlationValue = correlationValue; + } + + /** + * @return the correlation Type + */ + public Type getCorrelationType() { + return correlationType; + } + + /** + * @param correlationType the correlation Type to set + */ + public void setCorrelationType(Type correlationType) { + this.correlationType = correlationType; + } + + /** + * @return the List of artifactInstances; empty list of none have been + * added. + */ + public List getInstances() { + return new ArrayList<>(artifactInstances); + } + + /** + * @param artifactInstances the List of artifactInstances to set. + */ + public void setInstances(List artifactInstances) { + this.artifactInstances.clear(); + if (null != artifactInstances) { + this.artifactInstances.addAll(artifactInstances); + } + } + + /** + * @param instance the instance to add + */ + public void addInstance(EamArtifactInstance artifactInstance) { + this.artifactInstances.add(artifactInstance); + } + + public static class Type implements Serializable { + + private int id; + private String displayName; + private String dbTableName; + private Boolean supported; + private Boolean enabled; + + /** + * + * @param id Unique ID for this Correlation Type + * @param displayName Name of this type displayed in the UI. + * @param dbTableName Central Repository db table where data of this type is stored + * @param supported Is this Type currently supported + * @param enabled Is this Type currentl enabled. + */ + public Type(int id, String displayName, String dbTableName, Boolean supported, Boolean enabled) { + this.id = id; + this.displayName = displayName; + this.dbTableName = dbTableName; + this.supported = supported; + this.enabled = enabled; + } + + /** + * Constructior for custom types where we do not know the Type ID until + * the row has been entered into the correlation_types table + * in the Central Repository. + * + * @param displayName Name of this type displayed in the UI. + * @param dbTableName Central Repository db table where data of this type is stored + * @param supported Is this Type currently supported + * @param enabled Is this Type currentl enabled. + */ + public Type(String displayName, String dbTableName, Boolean supported, Boolean enabled) { + this(-1, displayName, dbTableName, supported, enabled); + } + + /** + * Determine if 2 Type objects are equal + * + * @param otherType Type object for comparison. + * + * @return true or false + */ + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } else if (!(that instanceof EamArtifact.Type)) { + return false; + } else { + return ((EamArtifact.Type) that).sameType(this); + } + } + + /** + * Determines if the content of this artifact type object is equivalent + * to the content of another artifact type object. + * + * @param that the other type + * + * @return true if it is the same type + */ + private boolean sameType(EamArtifact.Type that) { + return this.id == that.getId() + && Objects.equals(this.supported, that.isSupported()) + && Objects.equals(this.enabled, that.isEnabled()); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 67 * hash + Objects.hashCode(this.id); + hash = 67 * hash + Objects.hashCode(this.supported); + hash = 67 * hash + Objects.hashCode(this.enabled); + return hash; + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append("(id=").append(getId()); + str.append(", displayName=").append(getDisplayName()); + str.append(", dbTableName=").append(getDbTableName()); + str.append(", supported=").append(isSupported().toString()); + str.append(", enabled=").append(isEnabled().toString()); + str.append(")"); + return str.toString(); + } + + /** + * @return the id + */ + public int getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(int id) { + this.id = id; + } + + /** + * Check if this Artifact Type is supported. + * + * @return true or false + */ + public Boolean isSupported() { + return supported; + } + + /** + * Set this Artifact Type as supported or not supported. + * + * @param supported the supported to set + */ + public void setSupported(Boolean supported) { + this.supported = supported; + } + + /** + * Check if this Artifact Type is enabled. + * + * @return true or false + */ + public Boolean isEnabled() { + return enabled; + } + + /** + * Set this Artifact Type as enabled or not enabled. + * + * @param enabled the enabled to set + */ + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + /** + * @return the displayName + */ + public String getDisplayName() { + return displayName; + } + + /** + * @param displayName the displayName to set + */ + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + /** + * To support having different database tables for each Type, + * this field provides the prefix/suffix of the table name, + * which allows us to automatically compute the table names + * and indicies. + * + * It is the prefix for the instances tables *_instances. + * It is the suffix for the reference tables reference_*. + * + * When custom Types are added in the future, they are already supported + * by just giving the desired value for the table name for each custom + * Type. Possibly having all custom Types use a common table name. + * + * @return the dbTableName + */ + public String getDbTableName() { + return dbTableName; + } + + /** + * @param dbTableName the dbTableName to set + */ + public void setDbTableName(String dbTableName) { + this.dbTableName = dbTableName; + } + } +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifactInstance.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactInstance.java similarity index 75% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifactInstance.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactInstance.java index 821a291b95..27fe3ebee2 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifactInstance.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactInstance.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,26 +16,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.io.Serializable; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.datamodel.TskData; /** * * Used to store info about a specific Artifact Instance. * */ -@Messages({"EnterpriseArtifactsManagerArtifactInstances.globalStatus.local=Local", - "EnterpriseArtifactsManagerArtifactInstances.globalStatus.global=Global", - "EnterpriseArtifactsManagerArtifactInstances.knownStatus.bad=Bad", - "EnterpriseArtifactsManagerArtifactInstances.knownStatus.known=Known", - "EnterpriseArtifactsManagerArtifactInstances.knownStatus.unknown=Unknown"}) +@Messages({"EamArtifactInstances.globalStatus.local=Local", + "EamArtifactInstances.globalStatus.global=Global", + "EamArtifactInstances.knownStatus.bad=Bad", + "EamArtifactInstances.knownStatus.known=Known", + "EamArtifactInstances.knownStatus.unknown=Unknown"}) public class EamArtifactInstance implements Serializable { public enum GlobalStatus { - LOCAL(Bundle.EnterpriseArtifactsManagerArtifactInstances_globalStatus_local()), - GLOBAL(Bundle.EnterpriseArtifactsManagerArtifactInstances_globalStatus_global()); + LOCAL(Bundle.EamArtifactInstances_globalStatus_local()), + GLOBAL(Bundle.EamArtifactInstances_globalStatus_global()); private final String globalStatus; @@ -49,22 +50,22 @@ public class EamArtifactInstance implements Serializable { } } - public enum KnownStatus { - UNKNOWN(Bundle.EnterpriseArtifactsManagerArtifactInstances_knownStatus_unknown()), - KNOWN(Bundle.EnterpriseArtifactsManagerArtifactInstances_knownStatus_known()), - BAD(Bundle.EnterpriseArtifactsManagerArtifactInstances_knownStatus_bad()); - - private final String knownStatus; - - private KnownStatus(String knownStatus) { - this.knownStatus = knownStatus; - } - - @Override - public String toString() { - return knownStatus; - } - } +// public enum FileKnown { +// UNKNOWN(Bundle.EamArtifactInstances_knownStatus_unknown()), +// KNOWN(Bundle.EamArtifactInstances_knownStatus_known()), +// BAD(Bundle.EamArtifactInstances_knownStatus_bad()); +// +// private final String knownStatus; +// +// private FileKnown(String knownStatus) { +// this.knownStatus = knownStatus; +// } +// +// @Override +// public String toString() { +// return knownStatus; +// } +// } private static final long serialVersionUID = 1L; @@ -73,14 +74,14 @@ public class EamArtifactInstance implements Serializable { private EamDataSource eamDataSource; private String filePath; private String comment; - private KnownStatus knownStatus; + private TskData.FileKnown knownStatus; private GlobalStatus globalStatus; public EamArtifactInstance( EamCase eamCase, EamDataSource eamDataSource ) { - this("", eamCase, eamDataSource, "", "", KnownStatus.UNKNOWN, GlobalStatus.LOCAL); + this("", eamCase, eamDataSource, "", "", TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL); } public EamArtifactInstance( @@ -88,7 +89,7 @@ public class EamArtifactInstance implements Serializable { EamDataSource eamDataSource, String filePath ) { - this("", eamCase, eamDataSource, filePath, "", KnownStatus.UNKNOWN, GlobalStatus.LOCAL); + this("", eamCase, eamDataSource, filePath, "", TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL); } public EamArtifactInstance( @@ -97,7 +98,7 @@ public class EamArtifactInstance implements Serializable { String filePath, String comment ) { - this("", eamCase, eamDataSource, filePath, comment, KnownStatus.UNKNOWN, GlobalStatus.LOCAL); + this("", eamCase, eamDataSource, filePath, comment, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL); } public EamArtifactInstance( @@ -105,7 +106,7 @@ public class EamArtifactInstance implements Serializable { EamDataSource eamDataSource, String filePath, String comment, - KnownStatus knownStatus, + TskData.FileKnown knownStatus, GlobalStatus globalStatus ) { this("", eamCase, eamDataSource, filePath, comment, knownStatus, globalStatus); @@ -117,7 +118,7 @@ public class EamArtifactInstance implements Serializable { EamDataSource eamDataSource, String filePath, String comment, - KnownStatus knownStatus, + TskData.FileKnown knownStatus, GlobalStatus globalStatus ) { this.ID = ID; @@ -223,14 +224,14 @@ public class EamArtifactInstance implements Serializable { /** * @return the knownStatus */ - public KnownStatus getKnownStatus() { + public TskData.FileKnown getKnownStatus() { return knownStatus; } /** * @param knownStatus the knownStatus to set */ - public void setKnownStatus(KnownStatus knownStatus) { + public void setKnownStatus(TskData.FileKnown knownStatus) { this.knownStatus = knownStatus; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifactUtil.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java similarity index 91% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifactUtil.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java index 4741961e75..21acbc4fb4 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifactUtil.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.util.List; import java.util.logging.Level; @@ -27,6 +27,7 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskDataException; /** @@ -40,9 +41,9 @@ public class EamArtifactUtil { public EamArtifactUtil() { } - @Messages({"enterpriseartifactsmanagerartifact.emailaddresses.text=Email Addresses"}) + @Messages({"EamArtifactUtil.emailaddresses.text=Email Addresses"}) public static String getEmailAddressAttrString() { - return Bundle.enterpriseartifactsmanagerartifact_emailaddresses_text(); + return Bundle.EamArtifactUtil_emailaddresses_text(); } /* @@ -88,7 +89,7 @@ public class EamArtifactUtil { new EamDataSource(deviceId, af.getDataSource().getName()), af.getParentPath() + af.getName(), "", - EamArtifactInstance.KnownStatus.UNKNOWN, + TskData.FileKnown.UNKNOWN, EamArtifactInstance.GlobalStatus.LOCAL ); eamArtifact.addInstance(eamInstance); @@ -104,7 +105,7 @@ public class EamArtifactUtil { /** * Convert a blackboard artifact to an EamArtifact * - * @param aType The enterprise artifacts manager artifact type to create + * @param aType The Central Repository artifact type to create * @param bbArtifact The blackboard artifact to convert * * @return @@ -114,7 +115,7 @@ public class EamArtifactUtil { int artifactTypeID = bbArtifact.getArtifactTypeID(); try { - if (aType.getName().equals("EMAIL") + if (aType.getId() == EamArtifact.EMAIL_TYPE_ID && BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() == artifactTypeID) { BlackboardAttribute setNameAttr = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)); @@ -122,7 +123,7 @@ public class EamArtifactUtil { && EamArtifactUtil.getEmailAddressAttrString().equals(setNameAttr.getValueString())) { value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD)).getValueString(); } - } else if (aType.getName().equals("DOMAIN") + } else if (aType.getId() == EamArtifact.DOMAIN_TYPE_ID && (BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() == artifactTypeID || BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() == artifactTypeID || BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == artifactTypeID @@ -130,7 +131,7 @@ public class EamArtifactUtil { value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN)).getValueString(); - } else if (aType.getName().equals("PHONE") + } else if (aType.getId() == EamArtifact.PHONE_TYPE_ID && (BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID() == artifactTypeID || BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() == artifactTypeID || BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == artifactTypeID)) { @@ -143,7 +144,7 @@ public class EamArtifactUtil { value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)).getValueString(); } - } else if (aType.getName().equals("USBID") + } else if (aType.getId() == EamArtifact.USBID_TYPE_ID && BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID() == artifactTypeID) { value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID)).getValueString(); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamCase.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamCase.java similarity index 82% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamCase.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamCase.java index ad30eb5624..f0ba45d0cf 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamCase.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamCase.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.io.Serializable; import java.text.DateFormat; @@ -89,49 +89,49 @@ public class EamCase implements Serializable { return str.toString(); } - @Messages({"EnterpriseArtifactsManagerCase.title.caseUUID=Case UUID: "}) + @Messages({"EamCase.title.caseUUID=Case UUID: "}) public String getTitleCaseUUID() { - return Bundle.EnterpriseArtifactsManagerCase_title_caseUUID(); + return Bundle.EamCase_title_caseUUID(); } - @Messages({"EnterpriseArtifactsManagerCase.title.creationDate=Creation Date: "}) + @Messages({"EamCase.title.creationDate=Creation Date: "}) public String getTitleCreationDate() { - return Bundle.EnterpriseArtifactsManagerCase_title_creationDate(); + return Bundle.EamCase_title_creationDate(); } - @Messages({"EnterpriseArtifactsManagerCase.title.caseDisplayName=Case Name: "}) + @Messages({"EamCase.title.caseDisplayName=Case Name: "}) public String getTitleCaseDisplayName() { - return Bundle.EnterpriseArtifactsManagerCase_title_caseDisplayName(); + return Bundle.EamCase_title_caseDisplayName(); } - @Messages({"EnterpriseArtifactsManagerCase.title.caseNumber=Case Number: "}) + @Messages({"EamCase.title.caseNumber=Case Number: "}) public String getTitleCaseNumber() { - return Bundle.EnterpriseArtifactsManagerCase_title_caseNumber(); + return Bundle.EamCase_title_caseNumber(); } - @Messages({"EnterpriseArtifactsManagerCase.title.examinerName=Examiner Name: "}) + @Messages({"EamCase.title.examinerName=Examiner Name: "}) public String getTitleExaminerName() { - return Bundle.EnterpriseArtifactsManagerCase_title_examinerName(); + return Bundle.EamCase_title_examinerName(); } - @Messages({"EnterpriseArtifactsManagerCase.title.examinerEmail=Examiner Email: "}) + @Messages({"EamCase.title.examinerEmail=Examiner Email: "}) public String getTitleExaminerEmail() { - return Bundle.EnterpriseArtifactsManagerCase_title_examinerEmail(); + return Bundle.EamCase_title_examinerEmail(); } - @Messages({"EnterpriseArtifactsManagerCase.title.examinerPhone=Examiner Phone: "}) + @Messages({"EamCase.title.examinerPhone=Examiner Phone: "}) public String getTitleExaminerPhone() { - return Bundle.EnterpriseArtifactsManagerCase_title_examinerPhone(); + return Bundle.EamCase_title_examinerPhone(); } - @Messages({"EnterpriseArtifactsManagerCase.title.org=Organization: "}) + @Messages({"EamCase.title.org=Organization: "}) public String getTitleOrganization() { - return Bundle.EnterpriseArtifactsManagerCase_title_org(); + return Bundle.EamCase_title_org(); } - @Messages({"EnterpriseArtifactsManagerCase.title.notes=Notes: "}) + @Messages({"EamCase.title.notes=Notes: "}) public String getTitleNotes() { - return Bundle.EnterpriseArtifactsManagerCase_title_notes(); + return Bundle.EamCase_title_notes(); } public String getCaseDetailsOptionsPaneDialog() { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDataSource.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDataSource.java similarity index 95% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDataSource.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDataSource.java index 7f551c866a..cde6536e62 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDataSource.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDataSource.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.io.Serializable; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java similarity index 81% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index 0f7a1839cc..d61f8f1b6b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDb.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,9 +16,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.util.List; +import java.util.Set; /** * Main interface for interacting with the database @@ -47,8 +48,26 @@ public interface EamDb { } } + /** + * Shutdown the connection pool. + * + * This closes the connection pool including all idle database connections. + * It will not close active/in-use connections. + * Thus, it is vital that there are no in-use connections + * when you call this method. + * + * @throws EamDbException if there is a problem closing the connection pool. + */ + void shutdownConnections() throws EamDbException; + /** * Update settings + * + * When using updateSettings, + * if any database settings have changed, you should call + * shutdownConnections() before using any API methods. + * That will ensure that any old connections are closed + * and all new connections will be made using the new settings. */ void updateSettings(); @@ -203,7 +222,7 @@ public interface EamDb { * @param aType EamArtifact.Type to search for * @param filePath File path to search for * - * @return List of 0 or more EnterpriseArtifactManagerArtifactInstances + * @return List of 0 or more EamArtifactInstances * * @throws EamDbException */ @@ -329,13 +348,13 @@ public interface EamDb { List getListCasesHavingArtifactInstancesKnownBad(EamArtifact eamArtifact) throws EamDbException; /** - * Is the artifact globally known as bad? + * Is the artifact known as bad according to the reference entries? * * @param eamArtifact Artifact containing Type and Value * * @return Global known status of the artifact */ - boolean isArtifactGlobalKnownBad(EamArtifact eamArtifact) throws EamDbException; + boolean isArtifactlKnownBadByReference(EamArtifact eamArtifact) throws EamDbException; /** * Add a new organization @@ -375,7 +394,7 @@ public interface EamDb { * * @throws EamDbException */ - int newGlobalSet(EamGlobalSet eamGlobalSet) throws EamDbException; + int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException; /** * Get a global set by ID @@ -386,17 +405,18 @@ public interface EamDb { * * @throws EamDbException */ - EamGlobalSet getGlobalSetByID(int globalSetID) throws EamDbException; + EamGlobalSet getReferenceSetByID(int globalSetID) throws EamDbException; /** - * Add a new global file instance + * Add a new reference instance * - * @param eamGlobalFileInstance The global file instance to add + * @param eamGlobalFileInstance The reference instance to add + * @param correlationType Correlation Type that this Reference Instance is * * @throws EamDbException */ - void addGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException; - + void addReferenceInstance(EamGlobalFileInstance eamGlobalFileInstance, EamArtifact.Type correlationType) throws EamDbException ; + /** * Add a new global file instance to the bulk collection * @@ -404,34 +424,39 @@ public interface EamDb { * * @throws EamDbException */ - void prepareGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException; +// void prepareGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException; /** * Insert the bulk collection of Global File Instances * + * @param globalInstances a Set of EamGlobalFileInstances to insert into the db. + * @param contentType the Type of the global instances + * * @throws EamDbException */ - void bulkInsertGlobalFileInstances() throws EamDbException; + void bulkInsertReferenceTypeEntries(Set globalInstances, EamArtifact.Type contentType) throws EamDbException; /** - * Get all global file instances having a given MD5 hash + * Get all reference entries having a given correlation type and value * - * @param MD5Hash The hash to lookup + * @param aType Type to use for matching + * @param aValue Value to use for matching * - * @return List of all global file instances with a given hash + * @return List of all global file instances with a type and value * * @throws EamDbException */ - List getGlobalFileInstancesByHash(String MD5Hash) throws EamDbException; + List getReferenceInstancesByTypeValue(EamArtifact.Type aType, String aValue) throws EamDbException; /** * Add a new EamArtifact.Type to the db. * * @param newType New type to add. * + * @return Type.ID for newType * @throws EamDbException */ - public void newCorrelationArtifactType(EamArtifact.Type newType) throws EamDbException; + public int newCorrelationType(EamArtifact.Type newType) throws EamDbException; /** * Get the list of EamArtifact.Type's that will be used to correlate @@ -442,7 +467,7 @@ public interface EamDb { * * @throws EamDbException */ - public List getCorrelationArtifactTypes() throws EamDbException; + public List getCorrelationTypes() throws EamDbException; /** * Get the list of enabled EamArtifact.Type's that will be used to correlate @@ -453,7 +478,7 @@ public interface EamDb { * * @throws EamDbException */ - public List getEnabledCorrelationArtifactTypes() throws EamDbException; + public List getEnabledCorrelationTypes() throws EamDbException; /** * Get the list of supported EamArtifact.Type's that can be used to @@ -464,7 +489,7 @@ public interface EamDb { * * @throws EamDbException */ - public List getSupportedCorrelationArtifactTypes() throws EamDbException; + public List getSupportedCorrelationTypes() throws EamDbException; /** * Update a EamArtifact.Type. @@ -473,16 +498,16 @@ public interface EamDb { * * @throws EamDbException */ - public void updateCorrelationArtifactType(EamArtifact.Type aType) throws EamDbException; + public void updateCorrelationType(EamArtifact.Type aType) throws EamDbException; /** - * Get the EamArtifact.Type that has name of typeName. + * Get the EamArtifact.Type that has the given Type.Id. * - * @param typeName Name of Type to get + * @param typeId Type.Id of Correlation Type to get * * @return EamArtifact.Type or null if it doesn't exist. * * @throws EamDbException */ - public EamArtifact.Type getCorrelationArtifactTypeByName(String typeName) throws EamDbException; + public EamArtifact.Type getCorrelationTypeById(int typeId) throws EamDbException; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbException.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbException.java similarity index 92% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbException.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbException.java index 5f7e6019b2..a410f7f182 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbException.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbException.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; /* * An exception to be thrown by an artifact manager. @@ -43,5 +43,4 @@ public class EamDbException extends Exception { public EamDbException(String message, Throwable cause) { super(message, cause); } - } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbPlatformEnum.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbPlatformEnum.java similarity index 91% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbPlatformEnum.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbPlatformEnum.java index 2b117d326d..6210d5d528 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbPlatformEnum.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbPlatformEnum.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -41,7 +41,7 @@ public enum EamDbPlatformEnum { * Load the selectedPlatform boolean from the config file, if it is set. */ private void loadSettings() { - String selectedPlatformString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.selectedPlatform"); // NON-NLS + String selectedPlatformString = ModuleSettings.getConfigSetting("CentralRepository", "db.selectedPlatform"); // NON-NLS if (null != selectedPlatformString) { selected = this.toString().equalsIgnoreCase(selectedPlatformString); @@ -86,7 +86,7 @@ public enum EamDbPlatformEnum { selectedPlatform = p; } } - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.selectedPlatform", selectedPlatform.name()); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.selectedPlatform", selectedPlatform.name()); // NON-NLS } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbUtil.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbUtil.java similarity index 75% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbUtil.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbUtil.java index 3d5dbe3d5c..d97dfe65ea 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamDbUtil.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbUtil.java @@ -4,18 +4,17 @@ * and open the template in the editor. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.sql.Connection; -import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import java.util.logging.Level; +import static org.sleuthkit.autopsy.centralrepository.datamodel.EamDb.SCHEMA_VERSION; import org.sleuthkit.autopsy.coreutils.Logger; -import static org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb.SCHEMA_VERSION; /** * @@ -75,27 +74,30 @@ public class EamDbUtil { } /** - * Insert the default artifact types into the database. + * Insert the default correlation types into the database. * * @param conn Open connection to use. * @return true on success, else false */ - public static boolean insertDefaultArtifactTypes(Connection conn) { + public static boolean insertDefaultCorrelationTypes(Connection conn) { PreparedStatement preparedStatement = null; - List DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes(); - String sql = "INSERT INTO artifact_types(name, supported, enabled) VALUES (?, ?, ?)"; + List DEFAULT_CORRELATION_TYPES = EamArtifact.getDefaultCorrelationTypes(); + String sql = "INSERT INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?)"; try { preparedStatement = conn.prepareStatement(sql); - for (EamArtifact.Type newType : DEFAULT_ARTIFACT_TYPES) { - preparedStatement.setString(1, newType.getName()); - preparedStatement.setInt(2, newType.isSupported() ? 1 : 0); - preparedStatement.setInt(3, newType.isEnabled() ? 1 : 0); + for (EamArtifact.Type newType : DEFAULT_CORRELATION_TYPES) { + preparedStatement.setInt(1, newType.getId()); + preparedStatement.setString(2, newType.getDisplayName()); + preparedStatement.setString(3, newType.getDbTableName()); + preparedStatement.setInt(4, newType.isSupported() ? 1 : 0); + preparedStatement.setInt(5, newType.isEnabled() ? 1 : 0); + preparedStatement.addBatch(); } preparedStatement.executeBatch(); } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error inserting default correlation artifact types.", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error inserting default correlation types.", ex); // NON-NLS return false; } finally { EamDbUtil.closePreparedStatement(preparedStatement); @@ -181,4 +183,26 @@ public class EamDbUtil { return false; } + + + /** + * Conver thte Type's DbTableName string to the *_instances table name. + * + * @param type Correlation Type + * @return Instance table name for this Type. + */ + public static String correlationTypeToInstanceTableName(EamArtifact.Type type) { + return type.getDbTableName() + "_instances"; + } + + /** + * Convert the Type's DbTableName string to the reference_* table name. + * + * @param type Correlation Type + * @return Reference table name for this Type. + */ + public static String correlationTypeToReferenceTableName(EamArtifact.Type type) { + return "reference_" + type.getDbTableName(); + } + } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamGlobalFileInstance.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java similarity index 73% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamGlobalFileInstance.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java index 70067622f6..2a1e4ce24d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamGlobalFileInstance.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,9 +16,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance.KnownStatus; +import java.util.Objects; +import org.sleuthkit.datamodel.TskData; /** * Global file hash instance @@ -28,14 +29,14 @@ public class EamGlobalFileInstance { private int instanceID; private int globalSetID; private String MD5Hash; - private KnownStatus knownStatus; + private TskData.FileKnown knownStatus; private String comment; public EamGlobalFileInstance( int instanceID, int globalSetID, String MD5Hash, - KnownStatus knownStatus, + TskData.FileKnown knownStatus, String comment) { this.instanceID = instanceID; this.globalSetID = globalSetID; @@ -47,11 +48,30 @@ public class EamGlobalFileInstance { public EamGlobalFileInstance( int globalSetID, String MD5Hash, - KnownStatus knownStatus, + TskData.FileKnown knownStatus, String comment) { this(-1, globalSetID, MD5Hash, knownStatus, comment); } + @Override + public boolean equals(Object otherInstance) { + if (this == otherInstance) { + return true; + } else if (!(otherInstance instanceof EamGlobalFileInstance)) { + return false; + } else { + return (this.hashCode() == otherInstance.hashCode()); + } + } + + @Override + public int hashCode() { + int hash = 5; + hash = 59 * hash + this.globalSetID; + hash = 59 * hash + Objects.hashCode(this.MD5Hash); + hash = 59 * hash + this.knownStatus.hashCode(); + return hash; + } /** * @return the instanceID */ @@ -97,14 +117,14 @@ public class EamGlobalFileInstance { /** * @return the knownStatus */ - public KnownStatus getKnownStatus() { + public TskData.FileKnown getKnownStatus() { return knownStatus; } /** * @param knownStatus the knownStatus to set */ - public void setKnownStatus(KnownStatus knownStatus) { + public void setKnownStatus(TskData.FileKnown knownStatus) { this.knownStatus = knownStatus; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamGlobalSet.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java similarity index 93% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamGlobalSet.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java index a487dd61fa..21b4bd282c 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamGlobalSet.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalSet.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,12 +16,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.time.LocalDate; /** - * A global set in the enterprise artifacts manager database + * A global set in the Central Repository database */ public class EamGlobalSet { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamOrganization.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamOrganization.java similarity index 94% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamOrganization.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamOrganization.java index 7ff863bbbd..3bebf6d5f3 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamOrganization.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamOrganization.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,10 +16,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; /** - * An organization in the enterprise artifacts manager database + * An organization in the Central Repository database */ public class EamOrganization { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java similarity index 74% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java index 0815d9997b..3b9ec68fa2 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDb.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,23 +16,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.List; +import java.util.logging.Level; import org.apache.commons.dbcp2.BasicDataSource; import org.sleuthkit.autopsy.coreutils.Logger; /** - * Enterprise artifacts manager database implementation using Postgres as a + * Central Repository database implementation using Postgres as a * backend */ public class PostgresEamDb extends AbstractSqlEamDb { private final static Logger LOGGER = Logger.getLogger(PostgresEamDb.class.getName()); + private final static String CONFLICT_CLAUSE = "ON CONFLICT DO NOTHING"; + private static PostgresEamDb instance; private static final int CONN_POOL_SIZE = 10; @@ -50,7 +53,19 @@ public class PostgresEamDb extends AbstractSqlEamDb { private PostgresEamDb() { dbSettings = new PostgresEamDbSettings(); - updateSettings(); + bulkArtifactsThreshold = dbSettings.getBulkThreshold(); + } + + @Override + public void shutdownConnections() throws EamDbException { + try { + synchronized(this) { + connectionPool.close(); + connectionPool = null; // force it to be re-created on next connect() + } + } catch (SQLException ex) { + throw new EamDbException("Failed to close existing database connections.", ex); // NON-NLS + } } @Override @@ -77,18 +92,21 @@ public class PostgresEamDb extends AbstractSqlEamDb { dropContent.executeUpdate("TRUNCATE TABLE organizations RESTART IDENTITY CASCADE"); dropContent.executeUpdate("TRUNCATE TABLE cases RESTART IDENTITY CASCADE"); dropContent.executeUpdate("TRUNCATE TABLE data_sources RESTART IDENTITY CASCADE"); - dropContent.executeUpdate("TRUNCATE TABLE global_reference_sets RESTART IDENTITY CASCADE"); - dropContent.executeUpdate("TRUNCATE TABLE global_files RESTART IDENTITY CASCADE"); - dropContent.executeUpdate("TRUNCATE TABLE artifact_types RESTART IDENTITY CASCADE"); + dropContent.executeUpdate("TRUNCATE TABLE reference_sets RESTART IDENTITY CASCADE"); + dropContent.executeUpdate("TRUNCATE TABLE correlation_types RESTART IDENTITY CASCADE"); dropContent.executeUpdate("TRUNCATE TABLE db_info RESTART IDENTITY CASCADE"); String instancesTemplate = "TRUNCATE TABLE %s_instances RESTART IDENTITY CASCADE"; - for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { - dropContent.executeUpdate(String.format(instancesTemplate, type.getName().toLowerCase())); + String referencesTemplate = "TRUNCATE TABLE reference_%s RESTART IDENTITY CASCADE"; + for (EamArtifact.Type type : DEFAULT_CORRELATION_TYPES) { + dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName())); + // FUTURE: support other reference types + if (type.getId() == EamArtifact.FILES_TYPE_ID) { + dropContent.executeUpdate(String.format(referencesTemplate, type.getDbTableName())); + } } - } catch (SQLException ex) { - //LOGGER.log(Level.WARNING, "Failed to reset database.", ex); + LOGGER.log(Level.WARNING, "Failed to reset database.", ex); } finally { EamDbUtil.closeConnection(conn); } @@ -135,7 +153,7 @@ public class PostgresEamDb extends AbstractSqlEamDb { protected Connection connect() throws EamDbException { synchronized (this) { if (!EamDb.isEnabled()) { - throw new EamDbException("Enterprise artifacts manager is not enabled"); // NON-NLS + throw new EamDbException("Central Repository module is not enabled"); // NON-NLS } if (connectionPool == null) { @@ -150,6 +168,11 @@ public class PostgresEamDb extends AbstractSqlEamDb { } } + @Override + protected String getConflictClause() { + return CONFLICT_CLAUSE; + } + @Override public List getBadTags() { return dbSettings.getBadTags(); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java similarity index 69% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java index 58d99981a6..dcab3f6648 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/PostgresEamDbSettings.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.sql.Connection; import java.sql.DriverManager; @@ -36,15 +36,14 @@ import org.sleuthkit.autopsy.coreutils.TextConverter; import org.sleuthkit.autopsy.coreutils.TextConverterException; /** - * Settings for the Postgres implementation of the enterprise artifacts manager - * database + * Settings for the Postgres implementation of the Central Repository database */ public final class PostgresEamDbSettings { private final static Logger LOGGER = Logger.getLogger(PostgresEamDbSettings.class.getName()); private final String DEFAULT_HOST = "localhost"; // NON-NLS private final int DEFAULT_PORT = 5432; - private final String DEFAULT_DBNAME = "enterpriseartifacts"; // NON-NLS + private final String DEFAULT_DBNAME = "central_repository"; // NON-NLS private final int DEFAULT_BULK_THRESHHOLD = 1000; private final String DEFAULT_USERNAME = ""; private final String DEFAULT_PASSWORD = ""; @@ -67,13 +66,13 @@ public final class PostgresEamDbSettings { } public void loadSettings() { - host = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.host"); // NON-NLS + host = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.host"); // NON-NLS if (host == null || host.isEmpty()) { host = DEFAULT_HOST; } try { - String portString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.port"); // NON-NLS + String portString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.port"); // NON-NLS if (portString == null || portString.isEmpty()) { port = DEFAULT_PORT; } else { @@ -86,13 +85,13 @@ public final class PostgresEamDbSettings { port = DEFAULT_PORT; } - dbName = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.dbName"); // NON-NLS + dbName = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.dbName"); // NON-NLS if (dbName == null || dbName.isEmpty()) { dbName = DEFAULT_DBNAME; } try { - String bulkThresholdString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.bulkThreshold"); // NON-NLS + String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.bulkThreshold"); // NON-NLS if (bulkThresholdString == null || bulkThresholdString.isEmpty()) { this.bulkThreshold = DEFAULT_BULK_THRESHHOLD; } else { @@ -105,12 +104,12 @@ public final class PostgresEamDbSettings { this.bulkThreshold = DEFAULT_BULK_THRESHHOLD; } - userName = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.user"); // NON-NLS + userName = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.user"); // NON-NLS if (userName == null || userName.isEmpty()) { userName = DEFAULT_USERNAME; } - password = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.password"); // NON-NLS + password = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.password"); // NON-NLS if (password == null || password.isEmpty()) { password = DEFAULT_PASSWORD; } else { @@ -122,7 +121,7 @@ public final class PostgresEamDbSettings { } } - String badTagsStr = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.badTags"); // NON-NLS + String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS if (badTagsStr == null || badTagsStr.isEmpty()) { badTagsStr = DEFAULT_BAD_TAGS; } @@ -130,26 +129,26 @@ public final class PostgresEamDbSettings { } public void saveSettings() { - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.host", getHost()); // NON-NLS - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.port", Integer.toString(port)); // NON-NLS - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.dbName", getDbName()); // NON-NLS - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.user", getUserName()); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.host", getHost()); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.port", Integer.toString(port)); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.dbName", getDbName()); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.user", getUserName()); // NON-NLS try { - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.password", TextConverter.convertTextToHexText(getPassword())); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.password", TextConverter.convertTextToHexText(getPassword())); // NON-NLS } catch (TextConverterException ex) { LOGGER.log(Level.SEVERE, "Failed to convert password from text to hex text.", ex); } - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.badTags", String.join(",", badTags)); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.badTags", String.join(",", badTags)); // NON-NLS } /** * Get the full connection URL as a String * * @param usePostgresDb Connect to the 'postgres' database when testing - * connectivity and creating the main database. - * + * connectivity and creating the main database. + * * @return */ public String getConnectionURL(boolean usePostgresDb) { @@ -167,8 +166,9 @@ public final class PostgresEamDbSettings { } /** - * Use the current settings to get an ephemeral client connection for testing. - * + * Use the current settings to get an ephemeral client connection for + * testing. + * * @return Connection or null. */ private Connection getEphemeralConnection(boolean usePostgresDb) { @@ -191,9 +191,9 @@ public final class PostgresEamDbSettings { } /** - * Use the current settings and the validation query - * to test the connection to the database. - * + * Use the current settings and the validation query to test the connection + * to the database. + * * @return true if successfull connection, else false. */ public boolean verifyConnection() { @@ -201,7 +201,7 @@ public final class PostgresEamDbSettings { if (null == conn) { return false; } - + boolean result = EamDbUtil.executeValidationQuery(conn, VALIDATION_QUERY); EamDbUtil.closeConnection(conn); return result; @@ -209,7 +209,7 @@ public final class PostgresEamDbSettings { /** * Check to see if the database exists. - * + * * @return true if exists, else false */ public boolean verifyDatabaseExists() { @@ -238,11 +238,11 @@ public final class PostgresEamDbSettings { } return false; } - + /** - * Use the current settings and the schema version query - * to test the database schema. - * + * Use the current settings and the schema version query to test the + * database schema. + * * @return true if successfull connection, else false. */ public boolean verifyDatabaseSchema() { @@ -275,8 +275,9 @@ public final class PostgresEamDbSettings { EamDbUtil.closeConnection(conn); } return true; - + } + /** * Initialize the database schema. * @@ -305,7 +306,6 @@ public final class PostgresEamDbSettings { // NOTE: The organizations will only have a small number of rows, so // an index is probably not worthwhile. - StringBuilder createCasesTable = new StringBuilder(); createCasesTable.append("CREATE TABLE IF NOT EXISTS cases ("); createCasesTable.append("id SERIAL PRIMARY KEY,"); @@ -318,7 +318,7 @@ public final class PostgresEamDbSettings { createCasesTable.append("examiner_email text NOT NULL,"); createCasesTable.append("examiner_phone text NOT NULL,"); createCasesTable.append("notes text NOT NULL,"); - createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); + createCasesTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL"); createCasesTable.append(")"); // NOTE: when there are few cases in the cases table, these indices may not be worthwhile @@ -335,46 +335,47 @@ public final class PostgresEamDbSettings { String dataSourceIdx1 = "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)"; - StringBuilder createGlobalReferenceSetsTable = new StringBuilder(); - createGlobalReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS global_reference_sets ("); - createGlobalReferenceSetsTable.append("id SERIAL PRIMARY KEY,"); - createGlobalReferenceSetsTable.append("org_id integer,"); - createGlobalReferenceSetsTable.append("set_name text NOT NULL,"); - createGlobalReferenceSetsTable.append("version text NOT NULL,"); - createGlobalReferenceSetsTable.append("import_date text NOT NULL,"); - createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); - createGlobalReferenceSetsTable.append(")"); + StringBuilder createReferenceSetsTable = new StringBuilder(); + createReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS reference_sets ("); + createReferenceSetsTable.append("id SERIAL PRIMARY KEY,"); + createReferenceSetsTable.append("org_id integer,"); + createReferenceSetsTable.append("set_name text NOT NULL,"); + createReferenceSetsTable.append("version text NOT NULL,"); + createReferenceSetsTable.append("import_date text NOT NULL,"); + createReferenceSetsTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL"); + createReferenceSetsTable.append(")"); - String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)"; + String referenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS reference_sets_org_id ON reference_sets (org_id)"; - StringBuilder createGlobalFilesTable = new StringBuilder(); - createGlobalFilesTable.append("CREATE TABLE IF NOT EXISTS global_files ("); - createGlobalFilesTable.append("id SERIAL PRIMARY KEY,"); - createGlobalFilesTable.append("global_reference_set_id integer,"); - createGlobalFilesTable.append("value text NOT NULL,"); - createGlobalFilesTable.append("known_status text NOT NULL,"); - createGlobalFilesTable.append("comment text NOT NULL,"); - createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE (global_reference_set_id,value),"); - createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null"); - createGlobalFilesTable.append(")"); + // Each "%s" will be replaced with the relevant reference_TYPE table name. + StringBuilder createReferenceTypesTableTemplate = new StringBuilder(); + createReferenceTypesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s ("); + createReferenceTypesTableTemplate.append("id SERIAL PRIMARY KEY,"); + createReferenceTypesTableTemplate.append("reference_set_id integer,"); + createReferenceTypesTableTemplate.append("value text NOT NULL,"); + createReferenceTypesTableTemplate.append("known_status text NOT NULL,"); + createReferenceTypesTableTemplate.append("comment text NOT NULL,"); + createReferenceTypesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE (reference_set_id, value),"); + createReferenceTypesTableTemplate.append("foreign key (reference_set_id) references reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL"); + createReferenceTypesTableTemplate.append(")"); - String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)"; - String globalFilesIdx2 = "CREATE INDEX IF NOT EXISTS global_files_value_known_status ON global_files (value, known_status)"; + // Each "%s" will be replaced with the relevant reference_TYPE table name. + String referenceTypesIdx1 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)"; + String referenceTypesIdx2 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)"; - StringBuilder createArtifactTypesTable = new StringBuilder(); - createArtifactTypesTable.append("CREATE TABLE IF NOT EXISTS artifact_types ("); - createArtifactTypesTable.append("id SERIAL PRIMARY KEY,"); - createArtifactTypesTable.append("name text NOT NULL,"); - createArtifactTypesTable.append("supported integer NOT NULL,"); - createArtifactTypesTable.append("enabled integer NOT NULL,"); - createArtifactTypesTable.append("CONSTRAINT artifact_type_name_unique UNIQUE (name)"); - createArtifactTypesTable.append(")"); + StringBuilder createCorrelationTypesTable = new StringBuilder(); + createCorrelationTypesTable.append("CREATE TABLE IF NOT EXISTS correlation_types ("); + createCorrelationTypesTable.append("id SERIAL PRIMARY KEY,"); + createCorrelationTypesTable.append("display_name text NOT NULL,"); + createCorrelationTypesTable.append("db_table_name text NOT NULL,"); + createCorrelationTypesTable.append("supported integer NOT NULL,"); + createCorrelationTypesTable.append("enabled integer NOT NULL,"); + createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)"); + createCorrelationTypesTable.append(")"); - // NOTE: there are API methods that query by one of: name, supported, or enabled. - // Only name is currently implemented, but, there will only be a small number - // of artifact_types, so there is no benefit to having any indices. + // Each "%s" will be replaced with the relevant TYPE_instances table name. StringBuilder createArtifactInstancesTableTemplate = new StringBuilder(); - createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s_instances ("); + createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s ("); createArtifactInstancesTableTemplate.append("id SERIAL PRIMARY KEY,"); createArtifactInstancesTableTemplate.append("case_id integer,"); createArtifactInstancesTableTemplate.append("data_source_id integer,"); @@ -382,16 +383,16 @@ public final class PostgresEamDbSettings { createArtifactInstancesTableTemplate.append("file_path text NOT NULL,"); createArtifactInstancesTableTemplate.append("known_status text NOT NULL,"); createArtifactInstancesTableTemplate.append("comment text NOT NULL,"); - createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique_ UNIQUE (case_id, data_source_id, value, file_path),"); - createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,"); - createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null"); + createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique_ UNIQUE (case_id, data_source_id, value, file_path),"); + createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"); + createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL"); createArtifactInstancesTableTemplate.append(")"); - // TODO: do we need any more indices? - String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_instances_case_id ON %s_instances (case_id)"; - String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_instances_data_source_id ON %s_instances (data_source_id)"; - String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_instances_value ON %s_instances (value)"; - String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_instances_value_known_status ON %s_instances (value, known_status)"; + // Each "%s" will be replaced with the relevant TYPE_instances table name. + String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)"; + String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)"; + String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)"; + String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)"; StringBuilder createDbInfoTable = new StringBuilder(); createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info ("); @@ -402,7 +403,6 @@ public final class PostgresEamDbSettings { // NOTE: the db_info table currenly only has 1 row, so having an index // provides no benefit. - Connection conn = null; try { conn = getEphemeralConnection(false); @@ -420,28 +420,36 @@ public final class PostgresEamDbSettings { stmt.execute(createDataSourcesTable.toString()); stmt.execute(dataSourceIdx1); - stmt.execute(createGlobalReferenceSetsTable.toString()); - stmt.execute(globalReferenceSetsIdx1); + stmt.execute(createReferenceSetsTable.toString()); + stmt.execute(referenceSetsIdx1); - stmt.execute(createGlobalFilesTable.toString()); - stmt.execute(globalFilesIdx1); - stmt.execute(globalFilesIdx2); - - stmt.execute(createArtifactTypesTable.toString()); + stmt.execute(createCorrelationTypesTable.toString()); stmt.execute(createDbInfoTable.toString()); - // Create a separate table for each artifact type - List DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes(); - String type_name; - for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { - type_name = type.getName(); - stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), type_name, type_name)); - stmt.execute(String.format(instancesIdx1, type_name, type_name)); - stmt.execute(String.format(instancesIdx2, type_name, type_name)); - stmt.execute(String.format(instancesIdx3, type_name, type_name)); - stmt.execute(String.format(instancesIdx4, type_name, type_name)); + // Create a separate instance and reference table for each correlation type + List DEFAULT_CORRELATION_TYPES = EamArtifact.getDefaultCorrelationTypes(); + + String reference_type_dbname; + String instance_type_dbname; + for (EamArtifact.Type type : DEFAULT_CORRELATION_TYPES) { + reference_type_dbname = EamDbUtil.correlationTypeToReferenceTableName(type); + instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type); + + stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesIdx1, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesIdx2, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesIdx3, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesIdx4, instance_type_dbname, instance_type_dbname)); + + // FUTURE: allow more than the FILES type + if (type.getId() == EamArtifact.FILES_TYPE_ID) { + stmt.execute(String.format(createReferenceTypesTableTemplate.toString(), reference_type_dbname, reference_type_dbname)); + stmt.execute(String.format(referenceTypesIdx1, reference_type_dbname, reference_type_dbname)); + stmt.execute(String.format(referenceTypesIdx2, reference_type_dbname, reference_type_dbname)); + } } + } catch (SQLException ex) { LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS return false; @@ -457,7 +465,7 @@ public final class PostgresEamDbSettings { return false; } - boolean result = EamDbUtil.insertDefaultArtifactTypes(conn) + boolean result = EamDbUtil.insertDefaultCorrelationTypes(conn) && EamDbUtil.insertSchemaVersion(conn); EamDbUtil.closeConnection(conn); @@ -465,12 +473,12 @@ public final class PostgresEamDbSettings { } public boolean isChanged() { - String hostString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.host"); // NON-NLS - String portString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.port"); // NON-NLS - String dbNameString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.dbName"); // NON-NLS - String bulkThresholdString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.bulkThreshold"); // NON-NLS - String userNameString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.user"); // NON-NLS - String userPasswordString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.password"); // NON-NLS + String hostString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.host"); // NON-NLS + String portString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.port"); // NON-NLS + String dbNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.dbName"); // NON-NLS + String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.bulkThreshold"); // NON-NLS + String userNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.user"); // NON-NLS + String userPasswordString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.password"); // NON-NLS return !host.equals(hostString) || !Integer.toString(port).equals(portString) || !dbName.equals(dbNameString) || !Integer.toString(bulkThreshold).equals(bulkThresholdString) @@ -514,9 +522,9 @@ public final class PostgresEamDbSettings { } /** - * To prevent issues where one command can honor case and another cannot, - * we will force the dbname to lower case. - * + * To prevent issues where one command can honor case and another cannot, we + * will force the dbname to lower case. + * * @return the dbName */ public String getDbName() { @@ -550,7 +558,7 @@ public final class PostgresEamDbSettings { if (bulkThreshold > 0) { this.bulkThreshold = bulkThreshold; } else { - throw new EamDbException("Invalid bulk threshold for database connection."); // NON-NLS + throw new EamDbException("Invalid bulk threshold."); // NON-NLS } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java similarity index 74% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index e720955308..7480b63507 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDb.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.io.File; import java.sql.Connection; @@ -28,7 +28,7 @@ import org.apache.commons.dbcp2.BasicDataSource; import org.sleuthkit.autopsy.coreutils.Logger; /** - * Sqlite implementation of the enterprise artifacts manager database + * Sqlite implementation of the Central Repository database */ public class SqliteEamDb extends AbstractSqlEamDb { @@ -50,9 +50,23 @@ public class SqliteEamDb extends AbstractSqlEamDb { private SqliteEamDb() { dbSettings = new SqliteEamDbSettings(); - updateSettings(); + bulkArtifactsThreshold = dbSettings.getBulkThreshold(); } + @Override + public void shutdownConnections() throws EamDbException { + try { + synchronized(this) { + if (null != connectionPool) { + connectionPool.close(); + connectionPool = null; // force it to be re-created on next connect() + } + } + } catch (SQLException ex) { + throw new EamDbException("Failed to close existing database connections.", ex); // NON-NLS + } + } + @Override public void updateSettings() { synchronized (this) { @@ -77,24 +91,28 @@ public class SqliteEamDb extends AbstractSqlEamDb { dropContent.executeUpdate("DELETE FROM organizations"); dropContent.executeUpdate("DELETE FROM cases"); dropContent.executeUpdate("DELETE FROM data_sources"); - dropContent.executeUpdate("DELETE FROM global_reference_sets"); - dropContent.executeUpdate("DELETE FROM global_files"); + dropContent.executeUpdate("DELETE FROM reference_sets"); dropContent.executeUpdate("DELETE FROM artifact_types"); dropContent.executeUpdate("DELETE FROM db_info"); String instancesTemplate = "DELETE FROM %s_instances"; - for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { - dropContent.executeUpdate(String.format(instancesTemplate, type.getName().toLowerCase())); + String referencesTemplate = "DELETE FROM global_files"; + for (EamArtifact.Type type : DEFAULT_CORRELATION_TYPES) { + dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName())); + // FUTURE: support other reference types + if (type.getId() == EamArtifact.FILES_TYPE_ID) { + dropContent.executeUpdate(String.format(referencesTemplate, type.getDbTableName())); + } } dropContent.executeUpdate("VACUUM"); - dbSettings.insertDefaultDatabaseContent(); - } catch (SQLException ex) { LOGGER.log(Level.WARNING, "Failed to reset database.", ex); } finally { EamDbUtil.closeConnection(conn); } + + dbSettings.insertDefaultDatabaseContent(); } /** @@ -132,7 +150,7 @@ public class SqliteEamDb extends AbstractSqlEamDb { protected Connection connect() throws EamDbException { synchronized (this) { if (!EamDb.isEnabled()) { - throw new EamDbException("Enterprise artifacts manager is not enabled"); // NON-NLS + throw new EamDbException("Central Repository module is not enabled"); // NON-NLS } if (connectionPool == null) { @@ -147,6 +165,12 @@ public class SqliteEamDb extends AbstractSqlEamDb { } } + @Override + protected String getConflictClause() { + // For sqlite, our conflict clause is part of the table schema + return ""; + } + @Override public List getBadTags() { return dbSettings.getBadTags(); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java similarity index 69% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java index 742863ab33..9d14a26c74 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/SqliteEamDbSettings.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.io.File; import java.io.IOException; @@ -35,13 +35,13 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.PlatformUtil; /** - * Settings for the sqlite implementation of the enterprise artifacts manager database + * Settings for the sqlite implementation of the Central Repository database */ public final class SqliteEamDbSettings { private final static Logger LOGGER = Logger.getLogger(SqliteEamDbSettings.class.getName()); - private final String DEFAULT_DBNAME = "EnterpriseArtifacts.db"; // NON-NLS - private final String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "enterprise_artifacts_manager"; // NON-NLS + private final String DEFAULT_DBNAME = "central_repository.db"; // NON-NLS + private final String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "central_repository"; // NON-NLS private final int DEFAULT_BULK_THRESHHOLD = 1000; private final String DEFAULT_BAD_TAGS = "Evidence"; // NON-NLS private final String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS @@ -65,18 +65,18 @@ public final class SqliteEamDbSettings { } public void loadSettings() { - dbName = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbName"); // NON-NLS + dbName = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbName"); // NON-NLS if (dbName == null || dbName.isEmpty()) { dbName = DEFAULT_DBNAME; } - dbDirectory = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbDirectory"); // NON-NLS + dbDirectory = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbDirectory"); // NON-NLS if (dbDirectory == null || dbDirectory.isEmpty()) { dbDirectory = DEFAULT_DBDIRECTORY; } try { - String bulkThresholdString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.bulkThreshold"); // NON-NLS + String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.bulkThreshold"); // NON-NLS if (bulkThresholdString == null || bulkThresholdString.isEmpty()) { this.bulkThreshold = DEFAULT_BULK_THRESHHOLD; } else { @@ -89,7 +89,7 @@ public final class SqliteEamDbSettings { this.bulkThreshold = DEFAULT_BULK_THRESHHOLD; } - String badTagsStr = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.badTags"); // NON-NLS + String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS if (badTagsStr == null || badTagsStr.isEmpty()) { badTagsStr = DEFAULT_BAD_TAGS; } @@ -99,10 +99,10 @@ public final class SqliteEamDbSettings { public void saveSettings() { createDbDirectory(); - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbName", getDbName()); // NON-NLS - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbDirectory", getDbDirectory()); // NON-NLS - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS - ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.badTags", String.join(",", badTags)); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.dbName", getDbName()); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.dbDirectory", getDbDirectory()); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.badTags", String.join(",", badTags)); // NON-NLS } /** @@ -256,8 +256,8 @@ public final class SqliteEamDbSettings { createCasesTable.append("examiner_email text NOT NULL,"); createCasesTable.append("examiner_phone text NOT NULL,"); createCasesTable.append("notes text NOT NULL,"); - createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null,"); - createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE(case_uid)"); + createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE(case_uid) ON CONFLICT IGNORE,"); + createCasesTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL"); createCasesTable.append(")"); // NOTE: when there are few cases in the cases table, these indices may not be worthwhile @@ -274,46 +274,50 @@ public final class SqliteEamDbSettings { String dataSourceIdx1 = "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)"; - StringBuilder createGlobalReferenceSetsTable = new StringBuilder(); - createGlobalReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS global_reference_sets ("); - createGlobalReferenceSetsTable.append("id integer primary key autoincrement NOT NULL,"); - createGlobalReferenceSetsTable.append("org_id integer,"); - createGlobalReferenceSetsTable.append("set_name text NOT NULL,"); - createGlobalReferenceSetsTable.append("version text NOT NULL,"); - createGlobalReferenceSetsTable.append("import_date text NOT NULL,"); - createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null"); - createGlobalReferenceSetsTable.append(")"); + StringBuilder createReferenceSetsTable = new StringBuilder(); + createReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS reference_sets ("); + createReferenceSetsTable.append("id integer primary key autoincrement NOT NULL,"); + createReferenceSetsTable.append("org_id integer,"); + createReferenceSetsTable.append("set_name text NOT NULL,"); + createReferenceSetsTable.append("version text NOT NULL,"); + createReferenceSetsTable.append("import_date text NOT NULL,"); + createReferenceSetsTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL"); + createReferenceSetsTable.append(")"); - String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)"; + String referenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS reference_sets_org_id ON reference_sets (org_id)"; - StringBuilder createGlobalFilesTable = new StringBuilder(); - createGlobalFilesTable.append("CREATE TABLE IF NOT EXISTS global_files ("); - createGlobalFilesTable.append("id integer primary key autoincrement NOT NULL,"); - createGlobalFilesTable.append("global_reference_set_id integer,"); - createGlobalFilesTable.append("value text NOT NULL,"); - createGlobalFilesTable.append("known_status text NOT NULL,"); - createGlobalFilesTable.append("comment text NOT NULL,"); - createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE(global_reference_set_id, value)"); - createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null"); - createGlobalFilesTable.append(")"); + // Each "%s" will be replaced with the relevant reference_TYPE table name. + StringBuilder createReferenceTypesTableTemplate = new StringBuilder(); + createReferenceTypesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s ("); + createReferenceTypesTableTemplate.append("id integer primary key autoincrement NOT NULL,"); + createReferenceTypesTableTemplate.append("reference_set_id integer,"); + createReferenceTypesTableTemplate.append("value text NOT NULL,"); + createReferenceTypesTableTemplate.append("known_status text NOT NULL,"); + createReferenceTypesTableTemplate.append("comment text NOT NULL,"); + createReferenceTypesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE(reference_set_id, value) ON CONFLICT IGNORE,"); + createReferenceTypesTableTemplate.append("foreign key (reference_set_id) references reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL"); + createReferenceTypesTableTemplate.append(")"); - String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)"; - String globalFilesIdx2 = "CREATE INDEX IF NOT EXISTS global_files_value_known_status ON global_files (value, known_status)"; + // Each "%s" will be replaced with the relevant reference_TYPE table name. + String referenceTypesIdx1 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)"; + String referenceTypesIdx2 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)"; - StringBuilder createArtifactTypesTable = new StringBuilder(); - createArtifactTypesTable.append("CREATE TABLE IF NOT EXISTS artifact_types ("); - createArtifactTypesTable.append("id integer primary key autoincrement NOT NULL,"); - createArtifactTypesTable.append("name text NOT NULL,"); - createArtifactTypesTable.append("supported integer NOT NULL,"); - createArtifactTypesTable.append("enabled integer NOT NULL,"); - createArtifactTypesTable.append("CONSTRAINT artifact_type_name_unique UNIQUE (name)"); - createArtifactTypesTable.append(")"); + StringBuilder createCorrelationTypesTable = new StringBuilder(); + createCorrelationTypesTable.append("CREATE TABLE IF NOT EXISTS correlation_types ("); + createCorrelationTypesTable.append("id integer primary key autoincrement NOT NULL,"); + createCorrelationTypesTable.append("display_name text NOT NULL,"); + createCorrelationTypesTable.append("db_table_name text NOT NULL,"); + createCorrelationTypesTable.append("supported integer NOT NULL,"); + createCorrelationTypesTable.append("enabled integer NOT NULL,"); + createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)"); + createCorrelationTypesTable.append(")"); // NOTE: there are API methods that query by one of: name, supported, or enabled. // Only name is currently implemented, but, there will only be a small number // of artifact_types, so there is no benefit to having any indices. + // Each "%s" will be replaced with the relevant TYPE_instances table name. StringBuilder createArtifactInstancesTableTemplate = new StringBuilder(); - createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s_instances ("); + createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s ("); createArtifactInstancesTableTemplate.append("id integer primary key autoincrement NOT NULL,"); createArtifactInstancesTableTemplate.append("case_id integer,"); createArtifactInstancesTableTemplate.append("data_source_id integer,"); @@ -321,16 +325,16 @@ public final class SqliteEamDbSettings { createArtifactInstancesTableTemplate.append("file_path text NOT NULL,"); createArtifactInstancesTableTemplate.append("known_status text NOT NULL,"); createArtifactInstancesTableTemplate.append("comment text NOT NULL,"); - createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique UNIQUE(case_id, data_source_id, value, file_path),"); - createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,"); - createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null"); + createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE(case_id, data_source_id, value, file_path) ON CONFLICT IGNORE,"); + createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"); + createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL"); createArtifactInstancesTableTemplate.append(")"); - // TODO: do we need any more indices? - String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_instances_case_id ON %s_instances (case_id)"; - String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_instances_data_source_id ON %s_instances (data_source_id)"; - String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_instances_value ON %s_instances (value)"; - String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_instances_value_known_status ON %s_instances (value, known_status)"; + // Each "%s" will be replaced with the relevant TYPE_instances table name. + String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)"; + String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)"; + String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)"; + String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)"; StringBuilder createDbInfoTable = new StringBuilder(); createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info ("); @@ -365,28 +369,34 @@ public final class SqliteEamDbSettings { stmt.execute(createDataSourcesTable.toString()); stmt.execute(dataSourceIdx1); - stmt.execute(createGlobalReferenceSetsTable.toString()); - stmt.execute(globalReferenceSetsIdx1); + stmt.execute(createReferenceSetsTable.toString()); + stmt.execute(referenceSetsIdx1); - stmt.execute(createGlobalFilesTable.toString()); - stmt.execute(globalFilesIdx1); - stmt.execute(globalFilesIdx2); - - stmt.execute(createArtifactTypesTable.toString()); + stmt.execute(createCorrelationTypesTable.toString()); stmt.execute(createDbInfoTable.toString()); - // Create a separate table for each artifact type - List DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes(); + // Create a separate instance and reference table for each artifact type + List DEFAULT_CORRELATION_TYPES = EamArtifact.getDefaultCorrelationTypes(); - String type_name; - for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) { - type_name = type.getName(); - stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), type_name, type_name)); - stmt.execute(String.format(instancesIdx1, type_name, type_name)); - stmt.execute(String.format(instancesIdx2, type_name, type_name)); - stmt.execute(String.format(instancesIdx3, type_name, type_name)); - stmt.execute(String.format(instancesIdx4, type_name, type_name)); + String reference_type_dbname; + String instance_type_dbname; + for (EamArtifact.Type type : DEFAULT_CORRELATION_TYPES) { + reference_type_dbname = EamDbUtil.correlationTypeToReferenceTableName(type); + instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type); + + stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesIdx1, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesIdx2, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesIdx3, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesIdx4, instance_type_dbname, instance_type_dbname)); + + // FUTURE: allow more than the FILES type + if (type.getId() == EamArtifact.FILES_TYPE_ID) { + stmt.execute(String.format(createReferenceTypesTableTemplate.toString(), reference_type_dbname, reference_type_dbname)); + stmt.execute(String.format(referenceTypesIdx1, reference_type_dbname, reference_type_dbname)); + stmt.execute(String.format(referenceTypesIdx2, reference_type_dbname, reference_type_dbname)); + } } } catch (SQLException ex) { LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS @@ -403,16 +413,16 @@ public final class SqliteEamDbSettings { return false; } - boolean result = EamDbUtil.insertDefaultArtifactTypes(conn) + boolean result = EamDbUtil.insertDefaultCorrelationTypes(conn) && EamDbUtil.insertSchemaVersion(conn); EamDbUtil.closeConnection(conn); return result; } public boolean isChanged() { - String dbNameString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbName"); // NON-NLS - String dbDirectoryString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbDirectory"); // NON-NLS - String bulkThresholdString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.bulkThreshold"); // NON-NLS + String dbNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbName"); // NON-NLS + String dbDirectoryString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbDirectory"); // NON-NLS + String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.bulkThreshold"); // NON-NLS return !dbName.equals(dbNameString) || !dbDirectory.equals(dbDirectoryString) @@ -455,7 +465,7 @@ public final class SqliteEamDbSettings { if (bulkThreshold > 0) { this.bulkThreshold = bulkThreshold; } else { - throw new EamDbException("Invalid bulk threshold for database connection."); // NON-NLS + throw new EamDbException("Invalid bulk threshold."); // NON-NLS } } @@ -491,7 +501,7 @@ public final class SqliteEamDbSettings { if (dbDirectory != null && !dbDirectory.isEmpty()) { this.dbDirectory = dbDirectory; } else { - throw new EamDbException("Error invalid directory for sqlite database. Cannot be null or empty"); // NON-NLS + throw new EamDbException("Invalid directory for sqlite database. Cannot empty"); // NON-NLS } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/BadFileTagRunner.java similarity index 70% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/BadFileTagRunner.java index 1355bbef7e..c99cad4f1b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/BadFileTagRunner.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/BadFileTagRunner.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,13 +16,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.eventlisteners; +package org.sleuthkit.autopsy.centralrepository.eventlisteners; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; /** * Thread to send info to remote DB that tags a file as known bad. @@ -43,14 +43,14 @@ public class BadFileTagRunner implements Runnable { @Override public void run() { if (!EamDb.isEnabled()) { - LOGGER.log(Level.WARNING, "Enterprise artifacts manager database not configured"); // NON-NLS + LOGGER.log(Level.WARNING, "Central Repository database not configured"); // NON-NLS return; } try { dbManager.setArtifactInstanceKnownBad(this.artifact); } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error connecting to enterprise artifacts manager database.", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS } } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java similarity index 88% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 039e9a8867..bbeee8c722 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/CaseEventListener.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.eventlisteners; +package org.sleuthkit.autopsy.centralrepository.eventlisteners; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -29,13 +29,14 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactUtil; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamCase; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDataSource; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamOrganization; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDataSource; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; @@ -45,11 +46,10 @@ import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskDataException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; /** - * Listen for case events and update entries in the enterprise artifacts manager - * database accordingly + * Listen for case events and update entries in the Central Repository database + * accordingly */ @Messages({"caseeventlistener.evidencetag=Evidence"}) public class CaseEventListener implements PropertyChangeListener { @@ -75,7 +75,8 @@ public class CaseEventListener implements PropertyChangeListener { || (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) || (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK) || (af.getKnown() == TskData.FileKnown.KNOWN) - || (af.isDir() == true)) { + || (af.isDir() == true) + || (!af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC))) { break; } @@ -101,24 +102,24 @@ public class CaseEventListener implements PropertyChangeListener { EamArtifact eamArtifact; try { - EamArtifact.Type filesType = dbManager.getCorrelationArtifactTypeByName("FILES"); + EamArtifact.Type filesType = dbManager.getCorrelationTypeById(EamArtifact.FILES_TYPE_ID); eamArtifact = new EamArtifact(filesType, af.getMd5Hash()); EamArtifactInstance cei = new EamArtifactInstance( new EamCase(Case.getCurrentCase().getName(), Case.getCurrentCase().getDisplayName()), new EamDataSource(deviceId, dsName), af.getParentPath() + af.getName(), tagAdded.getComment(), - EamArtifactInstance.KnownStatus.BAD, + TskData.FileKnown.BAD, EamArtifactInstance.GlobalStatus.LOCAL ); eamArtifact.addInstance(cei); - // send update to enterprise artifacts manager db + // send update to Central Repository db Runnable r = new BadFileTagRunner(eamArtifact); // TODO: send r into a thread pool instead Thread t = new Thread(r); t.start(); } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error, unable to get FILES artifact type during CONTENT_TAG_ADDED event.", ex); + LOGGER.log(Level.SEVERE, "Error, unable to get FILES correlation type during CONTENT_TAG_ADDED event.", ex); } } } // CONTENT_TAG_ADDED @@ -141,7 +142,7 @@ public class CaseEventListener implements PropertyChangeListener { if (dbManager.getBadTags().contains(tagName.getDisplayName())) { try { - EamArtifact eamArtifact = EamArtifactUtil.fromBlackboardArtifact(bbArtifact, true, dbManager.getCorrelationArtifactTypes(), true); + EamArtifact eamArtifact = EamArtifactUtil.fromBlackboardArtifact(bbArtifact, true, dbManager.getCorrelationTypes(), true); if (null != eamArtifact) { eamArtifact.getInstances().get(0).setComment(bbTagAdded.getComment()); Runnable r = new BadFileTagRunner(eamArtifact); @@ -171,7 +172,7 @@ public class CaseEventListener implements PropertyChangeListener { dbManager.newDataSource(new EamDataSource(deviceId, newDataSource.getName())); } } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error connecting to enterprise artifacts manager database.", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS } catch (TskCoreException | TskDataException ex) { LOGGER.log(Level.SEVERE, "Error getting data source from DATA_SOURCE_ADDED event content.", ex); //NON-NLS } @@ -227,7 +228,7 @@ public class CaseEventListener implements PropertyChangeListener { dbManager.newCase(curCeCase); } } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error connecting to enterprise artifacts manager database.", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS } } } // CURRENT_CASE diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java similarity index 88% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java index 9066d960d5..6f03556d1e 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/IngestEventsListener.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.eventlisteners; +package org.sleuthkit.autopsy.centralrepository.eventlisteners; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -34,17 +34,17 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactUtil; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; /** - * Listen for ingest events and update entries in the enterprise artifacts manager database accordingly + * Listen for ingest events and update entries in the Central Repository database accordingly */ public class IngestEventsListener { @@ -91,8 +91,8 @@ public class IngestEventsListener { List eamArtifacts = new ArrayList<>(); try { for (BlackboardArtifact bbArtifact : bbArtifacts) { - // eamArtifact will be null OR a EamArtifact containing one EnterpriseArtifactsManagerArtifactInstance. - EamArtifact eamArtifact = EamArtifactUtil.fromBlackboardArtifact(bbArtifact, true, dbManager.getCorrelationArtifactTypes(), true); + // eamArtifact will be null OR a EamArtifact containing one EamArtifactInstance. + EamArtifact eamArtifact = EamArtifactUtil.fromBlackboardArtifact(bbArtifact, true, dbManager.getCorrelationTypes(), true); if (null != eamArtifact) { try { @@ -115,7 +115,7 @@ public class IngestEventsListener { } } } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error getting enterprise artifacts manager artifact types.", ex); + LOGGER.log(Level.SEVERE, "Error getting correlation types.", ex); } if (FALSE == eamArtifacts.isEmpty()) { // send update to entperirse artifact manager db @@ -147,17 +147,17 @@ public class IngestEventsListener { } } - @NbBundle.Messages({"EnterpriseArtifactsManager.prevcases.text=Previous Cases", - "EnterpriseArtifactsManager.ingestmodule.name=Enterprise Artifacts Manager"}) + @NbBundle.Messages({"IngestEventsListener.prevcases.text=Previous Cases", + "IngestEventsListener.ingestmodule.name=Correlation Engine"}) private void postCorrelatedBadArtifactToBlackboard(BlackboardArtifact bbArtifact, List caseDisplayNames) { try { AbstractFile af = bbArtifact.getSleuthkitCase().getAbstractFileById(bbArtifact.getObjectID()); - String MODULE_NAME = Bundle.EnterpriseArtifactsManager_ingestmodule_name(); + String MODULE_NAME = Bundle.IngestEventsListener_ingestmodule_name(); BlackboardArtifact tifArtifact = af.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT); BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, - Bundle.EnterpriseArtifactsManager_prevcases_text()); + Bundle.IngestEventsListener_prevcases_text()); BlackboardAttribute att2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, "Previous Case: " + caseDisplayNames.stream().distinct().collect(Collectors.joining(",", "", ""))); tifArtifact.addAttribute(att); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/Installer.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java similarity index 89% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/Installer.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index 73680f9120..a0a7878605 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/Installer.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,14 +16,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.eventlisteners; +package org.sleuthkit.autopsy.centralrepository.eventlisteners; import java.beans.PropertyChangeListener; import org.openide.modules.ModuleInstall; import org.openide.util.actions.CallableSystemAction; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.actions.EamEditCaseInfoAction; +import org.sleuthkit.autopsy.centralrepository.actions.EamEditCaseInfoAction; /** * Install event listeners during module initialization diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/NewArtifactsRunner.java similarity index 73% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/NewArtifactsRunner.java index a8eaa8fd3d..e81b012f79 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/NewArtifactsRunner.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/NewArtifactsRunner.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,15 +16,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.eventlisteners; +package org.sleuthkit.autopsy.centralrepository.eventlisteners; import java.util.ArrayList; import java.util.Collection; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; /** * Thread to insert a new artifact into remote DB. @@ -46,7 +46,7 @@ public class NewArtifactsRunner implements Runnable { @Override public void run() { if (!EamDb.isEnabled()) { - LOGGER.log(Level.WARNING, "Enterprise artifacts manager database not configured"); // NON-NLS + LOGGER.log(Level.WARNING, "Central Repository database not configured"); // NON-NLS return; } @@ -55,7 +55,7 @@ public class NewArtifactsRunner implements Runnable { dbManager.addArtifact(eamArtifact); } } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error connecting to enterprise artifacts manager database.", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS } } diff --git a/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/bad.png b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/bad.png new file mode 100644 index 0000000000..e8f8f55fc1 Binary files /dev/null and b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/bad.png differ diff --git a/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/good.png b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/good.png new file mode 100644 index 0000000000..210b1a6c3c Binary files /dev/null and b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/good.png differ diff --git a/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/import16.png b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/import16.png new file mode 100644 index 0000000000..18b35db444 Binary files /dev/null and b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/import16.png differ diff --git a/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/options-icon.png b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/options-icon.png new file mode 100644 index 0000000000..e3ca571e32 Binary files /dev/null and b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/images/options-icon.png differ diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java similarity index 87% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java index 6937f5aca1..5411a8c983 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModule.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,10 +16,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.ingestmodule; +package org.sleuthkit.autopsy.centralrepository.ingestmodule; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamCase; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import java.util.List; import java.util.logging.Level; import java.util.stream.Collectors; @@ -35,25 +35,24 @@ import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDataSource; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDataSource; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.HashUtility; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamOrganization; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; import org.sleuthkit.datamodel.TskDataException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; /** - * Ingest module for inserting entries into the enterprise artifacts manager - * database on ingest of a data source + * Ingest module for inserting entries into the Central Repository database on + * ingest of a data source */ -@Messages({"EnterpriseArtifactsManager.prevcases.text=Previous Cases", - "EnterpriseArtifactsManager.ingestmodule.name=Enterprise Artifacts Manager"}) +@Messages({"IngestModule.prevcases.text=Previous Cases"}) class IngestModule implements FileIngestModule { private final static Logger LOGGER = Logger.getLogger(IngestModule.class.getName()); @@ -84,7 +83,8 @@ class IngestModule implements FileIngestModule { || (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) || (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK) || (af.getKnown() == TskData.FileKnown.KNOWN) - || (af.isDir() == true)) { + || (af.isDir() == true) + || (!af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC))) { return ProcessResult.OK; } @@ -121,7 +121,7 @@ class IngestModule implements FileIngestModule { // Make a TSK_HASHSET_HIT blackboard artifact for global known bad files try { - if (dbManager.isArtifactGlobalKnownBad(eamArtifact)) { + if (dbManager.isArtifactlKnownBadByReference(eamArtifact)) { postCorrelatedHashHitToBlackboard(af); } } catch (EamDbException ex) { @@ -135,7 +135,7 @@ class IngestModule implements FileIngestModule { eamDataSource, af.getParentPath() + af.getName(), "", - EamArtifactInstance.KnownStatus.UNKNOWN, + TskData.FileKnown.UNKNOWN, EamArtifactInstance.GlobalStatus.LOCAL ); eamArtifact.addInstance(cefi); @@ -159,7 +159,7 @@ class IngestModule implements FileIngestModule { */ return; } - + EamDb dbManager = EamDb.getInstance(); try { dbManager.bulkInsertArtifacts(); @@ -179,8 +179,8 @@ class IngestModule implements FileIngestModule { // see ArtifactManagerTimeTester for details @Messages({ - "EnterpriseArtifactsManager.notfyBubble.title=Enterprise Artifacts Manager Not Initialized", - "EnterpriseArtifactsManager.errorMessage.isNotEnabled=Enterprise artifacts manager settings are not initialized, cannot run enteprise artifact manager ingest module." + "IngestModule.notfyBubble.title=Central Repository Not Initialized", + "IngestModule.errorMessage.isNotEnabled=Central Repository settings are not initialized, cannot run Correlation Engine ingest module." }) @Override public void startUp(IngestJobContext context) throws IngestModuleException { @@ -194,7 +194,7 @@ class IngestModule implements FileIngestModule { */ if (RuntimeProperties.runningWithGUI()) { if (1L == warningMsgRefCounter.incrementAndGet(jobId)) { - MessageNotifyUtil.Notify.warn(Bundle.EnterpriseArtifactsManager_notfyBubble_title(), Bundle.EnterpriseArtifactsManager_errorMessage_isNotEnabled()); + MessageNotifyUtil.Notify.warn(Bundle.IngestModule_notfyBubble_title(), Bundle.IngestModule_errorMessage_isNotEnabled()); } } return; @@ -213,10 +213,10 @@ class IngestModule implements FileIngestModule { EamDb dbManager = EamDb.getInstance(); try { - filesType = dbManager.getCorrelationArtifactTypeByName("FILES"); + filesType = dbManager.getCorrelationTypeById(EamArtifact.FILES_TYPE_ID); } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error getting correlation artifact type FILES in startUp.", ex); // NON-NLS - throw new IngestModuleException("Error getting correlation artifact type FILES in startUp.", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error getting correlation type FILES in startUp.", ex); // NON-NLS + throw new IngestModuleException("Error getting correlation type FILES in startUp.", ex); // NON-NLS } // TODO: once we implement a shared cache, load/init it here w/ syncronized and define reference counter @@ -264,10 +264,10 @@ class IngestModule implements FileIngestModule { private void postCorrelatedBadFileToBlackboard(AbstractFile abstractFile, List caseDisplayNames) { try { - String MODULE_NAME = Bundle.EnterpriseArtifactsManager_ingestmodule_name(); + String MODULE_NAME = IngestModuleFactory.getModuleName(); BlackboardArtifact tifArtifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, - Bundle.EnterpriseArtifactsManager_prevcases_text()); + Bundle.IngestModule_prevcases_text()); BlackboardAttribute att2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, "Previous Case: " + caseDisplayNames.stream().distinct().collect(Collectors.joining(",", "", ""))); tifArtifact.addAttribute(att); @@ -294,10 +294,10 @@ class IngestModule implements FileIngestModule { private void postCorrelatedHashHitToBlackboard(AbstractFile abstractFile) { try { - String MODULE_NAME = Bundle.EnterpriseArtifactsManager_ingestmodule_name(); + String MODULE_NAME = IngestModuleFactory.getModuleName(); BlackboardArtifact tifArtifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT); BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, - Bundle.EnterpriseArtifactsManager_prevcases_text()); + Bundle.IngestModule_prevcases_text()); tifArtifact.addAttribute(att); try { @@ -330,7 +330,7 @@ class IngestModule implements FileIngestModule { @Messages({"IngestModule.postToBB.fileName=File Name", "IngestModule.postToBB.md5Hash=MD5 Hash", "IngestModule.postToBB.hashSetSource=Source of Hash", - "IngestModule.postToBB.eamHit=Enterprise Artifacts Manager", + "IngestModule.postToBB.eamHit=Central Repository", "# {0} - Name of file that is Known Bad", "IngestModule.postToBB.knownBadMsg=Known Bad: {0}"}) public void sendBadFileInboxMessage(BlackboardArtifact artifact, String name, String md5Hash) { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModuleFactory.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModuleFactory.java similarity index 76% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModuleFactory.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModuleFactory.java index a33188ac60..ed3d4f0915 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/ingestmodule/IngestModuleFactory.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModuleFactory.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,26 +16,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.ingestmodule; +package org.sleuthkit.autopsy.centralrepository.ingestmodule; +import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel.GlobalSettingsPanel; +import org.sleuthkit.autopsy.centralrepository.optionspanel.GlobalSettingsPanel; /** - * Factory for enterprise artifacts manager ingest modules + * Factory for Central Repository ingest modules */ @ServiceProvider(service = org.sleuthkit.autopsy.ingest.IngestModuleFactory.class) +@NbBundle.Messages({"IngestModuleFactory.ingestmodule.name=Correlation Engine", + "IngestModuleFactory.ingestmodule.desc=Saves properties to the central repository for later correlation"}) public class IngestModuleFactory extends IngestModuleFactoryAdapter { private static final String VERSION_NUMBER = "0.8.0"; static String getModuleName() { - return java.util.ResourceBundle.getBundle("org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/Bundle") - .getString("OpenIDE-Module-Name"); + return Bundle.IngestModuleFactory_ingestmodule_name(); } @Override @@ -45,8 +47,7 @@ public class IngestModuleFactory extends IngestModuleFactoryAdapter { @Override public String getModuleDescription() { - return java.util.ResourceBundle.getBundle("org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/Bundle") - .getString("OpenIDE-Module-Long-Description"); + return Bundle.IngestModuleFactory_ingestmodule_desc(); } @Override diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/license-enterpriseartifactmanager.txt b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/license-centralrepository.txt similarity index 95% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/license-enterpriseartifactmanager.txt rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/license-centralrepository.txt index 4a3e9c3c1c..ebd777cdad 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/license-enterpriseartifactmanager.txt +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/license-centralrepository.txt @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/AddNewOrganizationDialog.form b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/AddNewOrganizationDialog.form similarity index 80% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/AddNewOrganizationDialog.form rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/AddNewOrganizationDialog.form index c8108d26f8..1a4c8e4966 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/AddNewOrganizationDialog.form +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/AddNewOrganizationDialog.form @@ -104,7 +104,7 @@ - + @@ -114,7 +114,7 @@ - + @@ -124,42 +124,42 @@ - + - + - + - + - + - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/AddNewOrganizationDialog.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/AddNewOrganizationDialog.java similarity index 96% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/AddNewOrganizationDialog.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/AddNewOrganizationDialog.java index a996da8f1e..0721c92ca7 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/AddNewOrganizationDialog.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/AddNewOrganizationDialog.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel; +package org.sleuthkit.autopsy.centralrepository.optionspanel; import java.awt.Dimension; import java.awt.Toolkit; @@ -31,12 +31,12 @@ import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamOrganization; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; /** - * Dialog to add a new organization to the enterprise artifacts manager database + * Dialog to add a new organization to the Central Repository database */ public class AddNewOrganizationDialog extends javax.swing.JDialog { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties similarity index 76% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties index 8811aa8c49..22a0ed7a5c 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties @@ -1,14 +1,7 @@ -OptionsCategory_Name_Enterprise_Artifacts_Manager_Options=Enterprise Artifacts Manager -OptionsCategory_Keywords_Enterprise_Artifacts_Manager_Options=Enterprise Artifacts Manager Settings +OptionsCategory_Name_Central_Repository_Options=Central Repository +OptionsCategory_Keywords_Central_Repository_Options=Central Repository Settings ImportHashDatabaseDialog.known.text=Known ImportHashDatabaseDialog.knownBad.text=Known Bad -ImportHashDatabaseDialog.importHashDbMsg=Import Hash Database -ImportHashDatabaseDialog.fileNameExtFilter.text=Hash Database File -ImportHashDatabaseDialog.failedToGetDbPathMsg=Failed to get the path of the selected database. -ImportHashDatabaseDialog.importHashDbErr=Import Hash Database Error -ImportHashDatabaseDialog.mustSelectHashDbFilePathMsg=A hash database file path must be selected. -ImportHashDatabaseDialog.hashDbDoesNotExistMsg=The selected hash database does not exist. -ImportHashDatabaseDialog.errorMessage.failedToOpenHashDbMsg=Failed to open hash database at {0}. EamPostgresSettingsDialog.lbUserPassword.text=User Password : EamPostgresSettingsDialog.lbUserName.text=User Name : EamPostgresSettingsDialog.bnCancel.text=Cancel @@ -28,21 +21,18 @@ ImportHashDatabaseDialog.tfDatabaseName.tooltip=Name for this database ImportHashDatabaseDialog.tfDatabaseVersion.tooltip.text=Database Version Number ImportHashDatabaseDialog.knownRadioButton.text=Known (NSRL or other) ImportHashDatabaseDialog.openButton.text=Open... -ImportHashDatabaseDialog.databasePathTextField.text= ImportHashDatabaseDialog.cancelButton.text=Cancel ImportHashDatabaseDialog.lbDatabaseVersion.text=Database Version: ImportHashDatabaseDialog.okButton.text=OK ImportHashDatabaseDialog.lbDatabaseName.text=Database Name: ImportHashDatabaseDialog.lbSourceOrganization.text=Source Organization: ImportHashDatabaseDialog.lbDatabaseAttribution.text=Database Attribution: -ImportHashDatabaseDialog.lbDatabasePath.text=Database Path: ImportHashDatabaseDialog.lbDatabaseType.text=Type of database: ImportHashDatabaseDialog.knownBadRadioButton.text=Known Bad ImportHashDatabaseDialog.bnNewOrganization.text=Add New Organization ImportHashDatabaseDialog.tfDatabaseName.tooltip=Name for this database ImportHashDatabaseDialog.tfDatabaseVersion.tooltip.text=Database Version Number GlobalSettingsPanel.bnImportDatabase.actionCommand= -GlobalSettingsPanel.bnManageTypes.text=Manage Artifact Types GlobalSettingsPanel.bnManageTags.actionCommand= GlobalSettingsPanel.bnManageTags.toolTipText= GlobalSettingsPanel.bnManageTags.text=Manage Tags @@ -59,10 +49,7 @@ AddNewOrganizationDialog.bnOK.text=OK AddNewOrganizationDialog.tfName.tooltip=POC Name ManageTagsDialog.okButton.text=OK ManageTagsDialog.cancelButton.text=Cancel -ManageArtifactTypesDialog.cancelButton.text=Cancel -ManageArtifactTypesDialog.okButton.text=OK -ManageArtifactTypesDialog.lbWarningMsg.text=Warning Message -ManageArtifactTypesDialog.taInstructionsMsg.text=Select one or more artifact types to store in the database and use for correlation during Ingest. +ManageArtifactTypesDialog.taInstructionsMsg.text=Enable one or more correlation properties to use for correlation during ingest. Note, these properties are global and impact all users of the central repository. EamSqliteSettingsDialog.bnOk.text=OK EamPostgresSettingsDialog.bnSave.text=Save EamDbSettingsDialog.pnDatabaseConnectionSettings.border.title=Database Settings @@ -88,3 +75,10 @@ GlobalSettingsPanel.lbDbPlatformTypeLabel.text=Type: GlobalSettingsPanel.lbDbNameLabel.text=Name: GlobalSettingsPanel.bnDbConfigure.text=Configure GlobalSettingsPanel.lbDbLocationLabel.text=Location: +ManageCorrelationPropertiesDialog.lbWarningMsg.text=Warning Message +ManageCorrelationPropertiesDialog.cancelButton.text=Cancel +ManageCorrelationPropertiesDialog.okButton.text=OK +GlobalSettingsPanel.bnManageProperties.text=Manage Correlation Properties +ImportHashDatabaseDialog.lbInstructions.text=Choose an .idx file to import into the central repository. +ImportHashDatabaseDialog.lbFilePath.text=File Path: +ImportHashDatabaseDialog.tfFilePath.text= diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.form b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.form similarity index 86% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.form rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.form index 3a43033eca..93bfa8f3fd 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.form +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.form @@ -60,7 +60,7 @@ - + @@ -151,17 +151,17 @@ - + - + - + @@ -171,7 +171,7 @@ - + @@ -250,35 +250,35 @@ - + - + - + - + - + @@ -297,7 +297,7 @@ - + @@ -307,7 +307,7 @@ - + @@ -317,7 +317,7 @@ - + @@ -374,7 +374,7 @@ - + @@ -384,7 +384,7 @@ - + @@ -394,7 +394,7 @@ - + @@ -404,7 +404,7 @@ - + @@ -422,7 +422,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java similarity index 94% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index 4f95216843..89f2f230a2 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamDbSettingsDialog.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel; +package org.sleuthkit.autopsy.centralrepository.optionspanel; import java.awt.Color; import java.awt.Cursor; @@ -20,19 +20,20 @@ import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JTextField; +import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.corecomponents.TextPrompt; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbPlatformEnum; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.PostgresEamDbSettings; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.SqliteEamDbSettings; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbPlatformEnum; +import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresEamDbSettings; +import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteEamDbSettings; /** * @@ -53,7 +54,7 @@ public class EamDbSettingsDialog extends JDialog { /** * Creates new form EamDbSettingsDialog */ - @Messages({"EamDbSettingsDialog.title.text=Enterprise Artifacts Manager Settings"}) + @Messages({"EamDbSettingsDialog.title.text=Central Repository Database Configuration"}) public EamDbSettingsDialog() { super((JFrame) WindowManager.getDefault().getMainWindow(), Bundle.EamDbSettingsDialog_title_text(), @@ -546,22 +547,58 @@ public class EamDbSettingsDialog extends JDialog { } }//GEN-LAST:event_bnCreateDbActionPerformed + @Messages({"EamDbSettingsDialog.okButton.errorTitle.text=Restart Required.", + "EamDbSettingsDialog.okButton.errorMsg.text=Please restart Autopsy to begin using the new database platform."}) private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed + /** + * We have to shutdown the previous platform's connection pool first; + * assuming it wasn't DISABLED. This will close any existing idle + * connections. + * + * The next use of an EamDb API method will start a new connection pool + * using those new settings. + */ + try { + EamDb previousDbManager = EamDb.getInstance(); + if (null != previousDbManager) { + // NOTE: do not set/save the seleted platform before calling this. + EamDb.getInstance().shutdownConnections(); + } + } catch (EamDbException ex) { + LOGGER.log(Level.SEVERE, "Failed to close database connections in previously selected platform.", ex); // NON-NLS + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + Bundle.EamDbSettingsDialog_okButton_errorMsg_text(), + Bundle.EamDbSettingsDialog_okButton_errorTitle_text(), + JOptionPane.WARNING_MESSAGE); + }); + } + + // Even if we fail to close the existing connections, make sure that we + // save the new connection settings, so an Autopsy restart will correctly + // start with the new settings. EamDbPlatformEnum.setSelectedPlatform(selectedPlatform.name()); EamDbPlatformEnum.saveSelectedPlatform(); + switch (selectedPlatform) { case POSTGRESQL: + // save the new PostgreSQL settings dbSettingsPostgres.saveSettings(); + // Load those newly saved settings into the postgres db manager instance + // in case we are still using the same instance. EamDb.getInstance().updateSettings(); break; case SQLITE: + // save the new SQLite settings dbSettingsSqlite.saveSettings(); + // Load those newly saved settings into the sqlite db manager instance + // in case we are still using the same instance. EamDb.getInstance().updateSettings(); break; case DISABLED: break; } - + dispose(); }//GEN-LAST:event_bnOkActionPerformed @@ -847,7 +884,7 @@ public class EamDbSettingsDialog extends JDialog { * * @return true */ - @Messages({"EamDbSettingsDialog.validation.finished=Click OK to save your database settings and return to the Options. Or select a differnt database type."}) + @Messages({"EamDbSettingsDialog.validation.finished=Click OK to save your database settings and return to the Options. Or select a different database type."}) private boolean enableOkButton() { if (testingStatus == DatabaseTestResult.TESTEDOK || selectedPlatform == EamDbPlatformEnum.DISABLED) { bnOk.setEnabled(true); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamOptionsPanelController.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamOptionsPanelController.java similarity index 80% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamOptionsPanelController.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamOptionsPanelController.java index 3c0fec984d..dab04c255f 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/EamOptionsPanelController.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamOptionsPanelController.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel; +package org.sleuthkit.autopsy.centralrepository.optionspanel; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -33,11 +33,11 @@ import org.sleuthkit.autopsy.coreutils.Logger; /** * Controller for the main settings panel */ -@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_Enterprise_Artifacts_Manager_Options", - iconBase = "org/sleuthkit/autopsy/experimental/images/options-icon.png", +@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_Central_Repository_Options", + iconBase = "org/sleuthkit/autopsy/centralrepository/images/options-icon.png", position = 14, - keywords = "#OptionsCategory_Keywords_Enterprise_Artifacts_Manager_Options", - keywordsCategory = "EnterpriseArtifactsManager") + keywords = "#OptionsCategory_Keywords_Central_Repository_Options", + keywordsCategory = "CentralRepository") public final class EamOptionsPanelController extends OptionsPanelController { private GlobalSettingsPanel panel; @@ -111,8 +111,8 @@ public final class EamOptionsPanelController extends OptionsPanelController { return panel; } - @Messages({"EnterpriseArtifactsManagerOptionsController.moduleErr=Error processing value changes.", - "EnterpriseArtifactsManagerOptionsController.moduleErr.msg=Value change processing failed."}) + @Messages({"EamOptionsController.moduleErr=Error processing value changes.", + "EamOptionsController.moduleErr.msg=Value change processing failed."}) void changed() { if (!changed) { changed = true; @@ -122,8 +122,8 @@ public final class EamOptionsPanelController extends OptionsPanelController { } catch (Exception ex) { LOGGER.log(Level.SEVERE, "Error processing property change", ex); //NON-NLS MessageNotifyUtil.Notify.show( - Bundle.EnterpriseArtifactsManagerOptionsController_moduleErr(), - Bundle.EnterpriseArtifactsManagerOptionsController_moduleErr_msg(), + Bundle.EamOptionsController_moduleErr(), + Bundle.EamOptionsController_moduleErr_msg(), MessageNotifyUtil.MessageType.ERROR); } } @@ -133,8 +133,8 @@ public final class EamOptionsPanelController extends OptionsPanelController { } catch (Exception e) { LOGGER.log(Level.SEVERE, "Error processing property change validation.", e); //NON-NLS MessageNotifyUtil.Notify.show( - Bundle.EnterpriseArtifactsManagerOptionsController_moduleErr(), - Bundle.EnterpriseArtifactsManagerOptionsController_moduleErr_msg(), + Bundle.EamOptionsController_moduleErr(), + Bundle.EamOptionsController_moduleErr_msg(), MessageNotifyUtil.MessageType.ERROR); } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.form b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form similarity index 78% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.form rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form index 02edd5748e..ec0056d904 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.form +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form @@ -50,7 +50,7 @@ - + @@ -113,28 +113,28 @@ - + - + - + - + @@ -183,13 +183,13 @@ - + - + - + @@ -199,13 +199,13 @@ - + - + - + @@ -215,7 +215,7 @@ - + @@ -233,7 +233,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java similarity index 95% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java index ca37fc5f03..d6e5873319 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/GlobalSettingsPanel.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel; +package org.sleuthkit.autopsy.centralrepository.optionspanel; import org.sleuthkit.autopsy.coreutils.Logger; import java.beans.PropertyChangeEvent; @@ -25,16 +25,15 @@ import javax.swing.SwingUtilities; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbPlatformEnum; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.PostgresEamDbSettings; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.SqliteEamDbSettings; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbPlatformEnum; +import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresEamDbSettings; +import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteEamDbSettings; /** - * Main settings panel for the enterprise artifacts manager + * Main settings panel for the Central Repository */ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel { @@ -44,7 +43,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i private final IngestJobEventPropertyChangeListener ingestJobEventListener; /** - * Creates new form EnterpriseArtifactsManagerOptionsPanel + * Creates new form EamOptionsPanel */ public GlobalSettingsPanel() { ingestJobEventListener = new IngestJobEventPropertyChangeListener(); @@ -54,7 +53,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i addIngestJobEventsListener(); } - @Messages({"GlobalSettingsPanel.title=Global Enterprise Artifacts Manager Settings"}) + @Messages({"GlobalSettingsPanel.title=Central Repository Settings"}) private void customizeComponents() { setName(Bundle.GlobalSettingsPanel_title()); } @@ -145,7 +144,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i .addContainerGap()) ); - bnImportDatabase.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/experimental/images/import16.png"))); // NOI18N + bnImportDatabase.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/centralrepository/images/import16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnImportDatabase, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnImportDatabase.label")); // NOI18N bnImportDatabase.setActionCommand(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnImportDatabase.actionCommand")); // NOI18N bnImportDatabase.addActionListener(new java.awt.event.ActionListener() { @@ -163,7 +162,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } }); - org.openide.awt.Mnemonics.setLocalizedText(bnManageTypes, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTypes.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(bnManageTypes, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageProperties.text")); // NOI18N bnManageTypes.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnManageTypesActionPerformed(evt); @@ -235,7 +234,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i }//GEN-LAST:event_bnManageTagsActionPerformed private void bnManageTypesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnManageTypesActionPerformed - ManageArtifactTypesDialog dialog = new ManageArtifactTypesDialog(); + ManageCorrelationPropertiesDialog dialog = new ManageCorrelationPropertiesDialog(); firePropertyChange(OptionsPanelController.PROP_VALID, null, null); }//GEN-LAST:event_bnManageTypesActionPerformed diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.form b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ImportHashDatabaseDialog.form similarity index 63% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.form rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ImportHashDatabaseDialog.form index d79c67566d..0865173651 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.form +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ImportHashDatabaseDialog.form @@ -30,33 +30,19 @@ + - - + - - - - - - - - - - - - - - - + @@ -86,6 +72,21 @@ + + + + + + + + + + + + + + + @@ -94,48 +95,56 @@ + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -144,7 +153,7 @@ - + @@ -154,24 +163,24 @@ - + - + - + - + @@ -184,7 +193,7 @@ - + @@ -195,49 +204,49 @@ - + - + - + - + - + - + - + @@ -262,21 +271,21 @@ - + - + - + @@ -293,5 +302,15 @@ + + + + + + + + + + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ImportHashDatabaseDialog.java similarity index 71% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ImportHashDatabaseDialog.java index 8e40524923..3d76d09e6a 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ImportHashDatabaseDialog.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ImportHashDatabaseDialog.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel; +package org.sleuthkit.autopsy.centralrepository.optionspanel; import java.awt.Dimension; import java.awt.Toolkit; @@ -29,30 +29,38 @@ import java.nio.file.Files; import java.time.LocalDate; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JTextField; +import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.filechooser.FileNameExtensionFilter; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamGlobalFileInstance; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamGlobalSet; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamOrganization; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalFileInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.datamodel.TskData; /** * Instances of this class allow a user to select an existing hash database and @@ -63,7 +71,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { private static final Logger LOGGER = Logger.getLogger(ImportHashDatabaseDialog.class.getName()); private final JFileChooser fileChooser = new JFileChooser(); - private final static String LAST_FILE_PATH_KEY = "EnterpriseArtifactsManagerImport_Path"; // NON-NLS + private final static String LAST_FILE_PATH_KEY = "CentralRepositoryImport_Path"; // NON-NLS private EamOrganization selectedOrg = null; private List orgs = null; private final Collection textBoxes; @@ -75,9 +83,10 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { * and add it to the set of hash databases used to classify files as * unknown, known, or known bad. */ + @Messages({"ImportHashDatabaseDialog.importHashDbMsg=Import Hash Database"}) ImportHashDatabaseDialog() { super((JFrame) WindowManager.getDefault().getMainWindow(), - NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.importHashDbMsg"), + Bundle.ImportHashDatabaseDialog_importHashDbMsg(), true); // NON-NLS textBoxes = new ArrayList<>(); textBoxChangedListener = new TextBoxChangedListener(); @@ -87,12 +96,14 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { display(); } + @Messages({"ImportHashDatabaseDialog.fileNameExtFilter.text=Hash Database File",}) private void initFileChooser() { fileChooser.setDragEnabled(false); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); String[] EXTENSION = new String[]{"idx"}; //NON-NLS FileNameExtensionFilter filter = new FileNameExtensionFilter( - NbBundle.getMessage(this.getClass(), "ImportHashDatabaseDialog.fileNameExtFilter.text"), EXTENSION); // NON-NLS + Bundle.ImportHashDatabaseDialog_fileNameExtFilter_text(), + EXTENSION); // NON-NLS fileChooser.setFileFilter(filter); fileChooser.setMultiSelectionEnabled(false); } @@ -107,6 +118,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { * Register for notifications when the text boxes get updated. */ private void setTextBoxListeners() { + textBoxes.add(tfFilePath); textBoxes.add(tfDatabaseName); textBoxes.add(tfDatabaseVersion); addDocumentListeners(textBoxes, textBoxChangedListener); @@ -150,7 +162,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { private boolean textFieldsArePopulated() { return !tfDatabaseName.getText().trim().isEmpty() && !tfDatabaseVersion.getText().trim().isEmpty() - && !databasePathTextField.getText().trim().isEmpty(); + && !tfFilePath.getText().trim().isEmpty(); } /** @@ -177,7 +189,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { * * @return true if it's okay, false otherwise. */ - @Messages({"ImportHashDatabaseDialog.validation.notEnabled=Database not initialized. Restart Autopsy."}) + @Messages({"ImportHashDatabaseDialog.validation.notEnabled=Database not initialized."}) public boolean valid() { lbWarningMsg.setText(""); EamDb dbManager = EamDb.getInstance(); @@ -244,7 +256,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { buttonGroup1 = new javax.swing.ButtonGroup(); okButton = new javax.swing.JButton(); cancelButton = new javax.swing.JButton(); - databasePathTextField = new javax.swing.JTextField(); + tfFilePath = new javax.swing.JTextField(); openButton = new javax.swing.JButton(); knownRadioButton = new javax.swing.JRadioButton(); knownBadRadioButton = new javax.swing.JRadioButton(); @@ -259,6 +271,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { tfDatabaseVersion = new javax.swing.JTextField(); bnNewOrganization = new javax.swing.JButton(); lbWarningMsg = new javax.swing.JLabel(); + lbInstructions = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -276,7 +289,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { } }); - databasePathTextField.setText(org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.databasePathTextField.text")); // NOI18N + tfFilePath.setText(org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.tfFilePath.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(openButton, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.openButton.text")); // NOI18N openButton.addActionListener(new java.awt.event.ActionListener() { @@ -294,7 +307,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { org.openide.awt.Mnemonics.setLocalizedText(lbDatabaseType, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.lbDatabaseType.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(lbDatabasePath, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.lbDatabasePath.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(lbDatabasePath, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.lbFilePath.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(lbDatabaseAttribution, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.lbDatabaseAttribution.text")); // NOI18N @@ -325,6 +338,9 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { lbWarningMsg.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N lbWarningMsg.setForeground(new java.awt.Color(255, 0, 0)); + lbInstructions.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(lbInstructions, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.lbInstructions.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -332,28 +348,18 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lbInstructions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() - .addComponent(lbWarningMsg, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(18, 18, 18) + .addGap(0, 0, Short.MAX_VALUE) .addComponent(okButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton)) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lbDatabaseType) - .addGroup(layout.createSequentialGroup() - .addGap(19, 19, 19) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(knownRadioButton) - .addComponent(knownBadRadioButton))) - .addComponent(lbDatabaseAttribution)) - .addGap(0, 0, Short.MAX_VALUE)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addComponent(lbDatabasePath) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(databasePathTextField)) + .addComponent(tfFilePath)) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addGap(23, 23, 23) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -373,7 +379,18 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { .addComponent(comboboxSourceOrganization, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(tfDatabaseName)))))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(openButton))) + .addComponent(openButton)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lbDatabaseType) + .addGroup(layout.createSequentialGroup() + .addGap(19, 19, 19) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(knownRadioButton) + .addComponent(knownBadRadioButton))) + .addComponent(lbDatabaseAttribution)) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(lbWarningMsg, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); @@ -383,59 +400,64 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() + .addComponent(lbInstructions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(openButton) - .addComponent(databasePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(tfFilePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbDatabasePath)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lbDatabaseType) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(knownRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(knownBadRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lbDatabaseAttribution) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(bnNewOrganization) - .addGroup(layout.createSequentialGroup() - .addGap(3, 3, 3) - .addComponent(lbSourceOrganization, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(comboboxSourceOrganization, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(18, 18, 18) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(tfDatabaseName) - .addComponent(lbDatabaseName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbDatabaseVersion, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(tfDatabaseVersion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lbWarningMsg, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(okButton) - .addComponent(cancelButton))) - .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lbDatabaseType) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(knownRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(knownBadRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lbDatabaseAttribution) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(bnNewOrganization) + .addGroup(layout.createSequentialGroup() + .addGap(3, 3, 3) + .addComponent(lbSourceOrganization, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(comboboxSourceOrganization, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(tfDatabaseName) + .addComponent(lbDatabaseName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lbDatabaseVersion, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(tfDatabaseVersion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lbWarningMsg, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(44, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(okButton) + .addComponent(cancelButton)) + .addContainerGap()))) ); pack(); }// //GEN-END:initComponents + @Messages({"ImportHashDatabaseDialog.failedToGetDbPathMsg=Failed to get the path of the selected database.",}) private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { File databaseFile = fileChooser.getSelectedFile(); try { - databasePathTextField.setText(databaseFile.getCanonicalPath()); + tfFilePath.setText(databaseFile.getCanonicalPath()); if (databaseFile.getName().toLowerCase().contains("nsrl")) { //NON-NLS knownRadioButton.setSelected(true); } ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY, databaseFile.getParent()); } catch (IOException ex) { Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.SEVERE, "Failed to get path of selected database", ex); // NON-NLS - JOptionPane.showMessageDialog(this, - NbBundle.getMessage(this.getClass(), - "ImportHashDatabaseDialog.failedToGetDbPathMsg")); // NON-NLS + lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_failedToGetDbPathMsg()); } } valid(); @@ -458,73 +480,61 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { tfDatabaseName.getText().trim(), tfDatabaseVersion.getText().trim(), LocalDate.now()); - return dbManager.newGlobalSet(eamGlobalSet); + return dbManager.newReferencelSet(eamGlobalSet); } @Messages({"ImportHashDatabaseDialog.createGlobalSet.failedMsg.text=Failed to store attribution details.", - "ImportHashDatabaseDialog.createGlobalSet.failedTitle.text=Import hashdb error."}) + "ImportHashDatabaseDialog.mustSelectHashDbFilePathMsg=Missing hash database file path.", + "ImportHashDatabaseDialog.hashDbDoesNotExistMsg=The selected hash database does not exist.", + "# {0} - selected file path", + "ImportHashDatabaseDialog.errorMessage.failedToOpenHashDbMsg=Failed to open hash database at {0}.", +}) private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed // Note that the error handlers in this method call return without disposing of the // dialog to allow the user to try again, if desired. - String selectedFilePath = databasePathTextField.getText(); + String selectedFilePath = tfFilePath.getText(); // have valid file path if (selectedFilePath.isEmpty()) { - JOptionPane.showMessageDialog(this, - NbBundle.getMessage(this.getClass(), - "ImportHashDatabaseDialog.mustSelectHashDbFilePathMsg"), - NbBundle.getMessage(this.getClass(), - "ImportHashDatabaseDialog.importHashDbErr"), - JOptionPane.ERROR_MESSAGE); // NON-NLS + lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_mustSelectHashDbFilePathMsg()); return; } File file = new File(selectedFilePath); if (!file.exists()) { - JOptionPane.showMessageDialog(this, - NbBundle.getMessage(this.getClass(), - "ImportHashDatabaseDialog.hashDbDoesNotExistMsg"), - NbBundle.getMessage(this.getClass(), - "ImportHashDatabaseDialog.importHashDbErr"), - JOptionPane.ERROR_MESSAGE); // NON-NLS + lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_hashDbDoesNotExistMsg()); return; } // create global set - int globalSetID = -1; + int globalSetID; try { globalSetID = createGlobalSet(); } catch (EamDbException ex) { - JOptionPane.showMessageDialog(this, - Bundle.ImportHashDatabaseDialog_createGlobalSet_failedMsg_text(), - Bundle.ImportHashDatabaseDialog_createGlobalSet_failedTitle_text(), - JOptionPane.ERROR_MESSAGE); + LOGGER.log(Level.SEVERE, "Failed to create global set.", ex); + lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_createGlobalSet_failedMsg_text()); return; } // insert hashes - EamArtifactInstance.KnownStatus knownStatus = EamArtifactInstance.KnownStatus.UNKNOWN; + TskData.FileKnown knownStatus = TskData.FileKnown.UNKNOWN; if (knownRadioButton.isSelected()) { - knownStatus = EamArtifactInstance.KnownStatus.KNOWN; + knownStatus = TskData.FileKnown.KNOWN; } else if (knownBadRadioButton.isSelected()) { - knownStatus = EamArtifactInstance.KnownStatus.BAD; + knownStatus = TskData.FileKnown.BAD; } - String errorMessage = NbBundle.getMessage(this.getClass(), - "ImportHashDatabaseDialog.errorMessage.failedToOpenHashDbMsg", - selectedFilePath); // NON-NLS + String errorMessage = Bundle.ImportHashDatabaseDialog_errorMessage_failedToOpenHashDbMsg(selectedFilePath); + // Future, make UI handle more than the "FILES" type. + EamArtifact.Type contentType = EamArtifact.getDefaultCorrelationTypes().get(0); // get "FILES" type try { - new ImportHashDatabaseWorker(selectedFilePath, knownStatus, globalSetID).execute(); - } catch (Throwable ex) { - Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex); - JOptionPane.showMessageDialog(this, - ex.getMessage(), - NbBundle.getMessage(this.getClass(), - "ImportHashDatabaseDialog.importHashDbErr"), - JOptionPane.ERROR_MESSAGE); - return; + // run in the background and close dialog + SwingUtilities.invokeLater(new ImportHashDatabaseWorker(selectedFilePath, knownStatus, globalSetID, contentType)::execute); + dispose(); + } catch (EamDbException | UnknownHostException ex) { + Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.SEVERE, errorMessage, ex); + lbWarningMsg.setText(ex.getMessage()); } - dispose(); }//GEN-LAST:event_okButtonActionPerformed @SuppressWarnings({"unchecked"}) @@ -552,38 +562,57 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { }//GEN-LAST:event_comboboxSourceOrganizationActionPerformed @NbBundle.Messages({"ImportHashDatabaseDialog.ImportHashDatabaseWorker.displayName=Importing Hash Database"}) - private class ImportHashDatabaseWorker extends SwingWorker { + private class ImportHashDatabaseWorker extends SwingWorker { - private final EamDb dbManager; private final File file; - private final EamArtifactInstance.KnownStatus knownStatus; + private final TskData.FileKnown knownStatus; private final int globalSetID; + private final ProgressHandle progress; + private final EamArtifact.Type contentType; - public ImportHashDatabaseWorker(String filename, EamArtifactInstance.KnownStatus knownStatus, int globalSetID) throws EamDbException, UnknownHostException { - this.dbManager = EamDb.getInstance(); + public ImportHashDatabaseWorker(String filename, TskData.FileKnown knownStatus, int globalSetID, EamArtifact.Type contentType) throws EamDbException, UnknownHostException { this.file = new File(filename); this.knownStatus = knownStatus; this.globalSetID = globalSetID; + this.contentType = contentType; + this.progress = ProgressHandle.createHandle(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_displayName()); if (!EamDb.isEnabled()) { - throw new EamDbException("Enterprise artifacts manager database settings were not properly initialized"); // NON-NLS + throw new EamDbException("Central Repository database is not enabled."); // NON-NLS } } @Override - protected Object doInBackground() throws Exception { - ProgressHandle progress = ProgressHandle.createHandle(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_displayName()); - importHashDatabase(progress); + protected Void doInBackground() throws Exception { + importHashDatabase(); return null; } + @Override + @Messages({"ImportHashDatabaseDialog.ImportHashDatabaseWorker.error=Failed to import hash database."}) + protected void done() { + progress.finish(); + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.SEVERE, Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_error(), ex); + MessageNotifyUtil.Notify.show(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_error(), + ex.getMessage(), + MessageNotifyUtil.MessageType.ERROR); + } + } + private long numberOfLinesInFile(File f) throws IOException { return Files.lines(f.toPath()).count(); } - private void importHashDatabase(ProgressHandle progress) throws EamDbException, IOException { + @Messages({"# {0} - value content", + "ImportHashDatabaseDialog.ImportHashDatabaseWorker.duplicate=Duplicate value {0} found in import file."}) + private void importHashDatabase() throws EamDbException, IOException { BufferedReader reader = new BufferedReader(new FileReader(file)); String line; + EamDb dbManager = EamDb.getInstance(); + Set globalInstances = new HashSet<>(); long totalLines = numberOfLinesInFile(file); if (totalLines <= Integer.MAX_VALUE) { @@ -609,11 +638,12 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { knownStatus, ""); - dbManager.prepareGlobalFileInstance(eamGlobalFileInstance); + if (!globalInstances.add(eamGlobalFileInstance)) { + throw new EamDbException(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_duplicate(parts[0])); // NON-NLS + } } - dbManager.bulkInsertGlobalFileInstances(); - progress.finish(); + dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); } } @@ -622,7 +652,6 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { private javax.swing.ButtonGroup buttonGroup1; private javax.swing.JButton cancelButton; private javax.swing.JComboBox comboboxSourceOrganization; - private javax.swing.JTextField databasePathTextField; private javax.swing.JRadioButton knownBadRadioButton; private javax.swing.JRadioButton knownRadioButton; private javax.swing.JLabel lbDatabaseAttribution; @@ -630,11 +659,13 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog { private javax.swing.JLabel lbDatabasePath; private javax.swing.JLabel lbDatabaseType; private javax.swing.JLabel lbDatabaseVersion; + private javax.swing.JLabel lbInstructions; private javax.swing.JLabel lbSourceOrganization; private javax.swing.JLabel lbWarningMsg; private javax.swing.JButton okButton; private javax.swing.JButton openButton; private javax.swing.JTextField tfDatabaseName; private javax.swing.JTextField tfDatabaseVersion; + private javax.swing.JTextField tfFilePath; // End of variables declaration//GEN-END:variables } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageArtifactTypesDialog.form b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageCorrelationPropertiesDialog.form similarity index 86% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageArtifactTypesDialog.form rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageCorrelationPropertiesDialog.form index 7ab23c86d5..5124d1d85d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageArtifactTypesDialog.form +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageCorrelationPropertiesDialog.form @@ -67,7 +67,7 @@ - + @@ -77,7 +77,7 @@ - + @@ -100,7 +100,7 @@ - +
@@ -123,7 +123,7 @@
- +
@@ -140,7 +140,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageArtifactTypesDialog.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageCorrelationPropertiesDialog.java similarity index 79% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageArtifactTypesDialog.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageCorrelationPropertiesDialog.java index 543e093f0d..b0fb9eb718 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageArtifactTypesDialog.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageCorrelationPropertiesDialog.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel; +package org.sleuthkit.autopsy.centralrepository.optionspanel; import java.awt.Dimension; import java.awt.Toolkit; @@ -32,30 +32,30 @@ import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; /** - * Dialog to handle management of artifact types handled by the enterprise - * artifacts manager + * Dialog to handle management of artifact types handled by the Central + * Repository */ -final class ManageArtifactTypesDialog extends javax.swing.JDialog { +final class ManageCorrelationPropertiesDialog extends javax.swing.JDialog { - private static final Logger LOGGER = Logger.getLogger(ManageArtifactTypesDialog.class.getName()); + private static final Logger LOGGER = Logger.getLogger(ManageCorrelationPropertiesDialog.class.getName()); - private final List eamArtifactTypes; + private final List correlationTypes; /** * Displays a dialog that allows a user to select which Type(s) should be * used for Correlation during ingest. */ - @Messages({"ManageArtifactTypesDialog.title=Manage Artifact Types"}) - ManageArtifactTypesDialog() { + @Messages({"ManageCorrelationPropertiesDialog.title=Manage Correlation Properties"}) + ManageCorrelationPropertiesDialog() { super((JFrame) WindowManager.getDefault().getMainWindow(), - Bundle.ManageArtifactTypesDialog_title(), + Bundle.ManageCorrelationPropertiesDialog_title(), true); // NON-NLS - this.eamArtifactTypes = new ArrayList<>(); + this.correlationTypes = new ArrayList<>(); initComponents(); customizeComponents(); display(); @@ -72,24 +72,24 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog { DefaultTableModel model = (DefaultTableModel) tbCorrelatableTypes.getModel(); try { EamDb dbManager = EamDb.getInstance(); - eamArtifactTypes.clear(); - eamArtifactTypes.addAll(dbManager.getCorrelationArtifactTypes()); + correlationTypes.clear(); + correlationTypes.addAll(dbManager.getCorrelationTypes()); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); } - eamArtifactTypes.forEach((aType) -> { - model.addRow(new Object[]{aType.getName(), aType.isEnabled()}); + correlationTypes.forEach((aType) -> { + model.addRow(new Object[]{aType.getDisplayName(), aType.isEnabled()}); }); model.addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent evt) { int row = evt.getFirstRow(); TableModel model = (TableModel) evt.getSource(); - Object typeName = model.getValueAt(row, 0); + Object displayName = model.getValueAt(row, 0); Boolean enabled = (Boolean) model.getValueAt(row, 1); - eamArtifactTypes.stream().filter((aType) -> (aType.getName().equals(typeName))).forEachOrdered((aType) -> { + correlationTypes.stream().filter((aType) -> (aType.getDisplayName().equals(displayName))).forEachOrdered((aType) -> { aType.setEnabled(enabled); }); valid(); @@ -103,15 +103,15 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog { setVisible(true); } - @Messages({"ManageArtifactTypesDialog.noneSelected=There are no artifact types enabled."}) + @Messages({"ManageCorrelationPropertiesDialog.noneSelected=There are no correlation properties enabled."}) private boolean valid() { lbWarningMsg.setText(""); int countEnabled = 0; - countEnabled = eamArtifactTypes.stream().filter((aType) -> (aType.isEnabled())).map((_item) -> 1).reduce(countEnabled, Integer::sum); + countEnabled = correlationTypes.stream().filter((aType) -> (aType.isEnabled())).map((_item) -> 1).reduce(countEnabled, Integer::sum); if (0 == countEnabled) { - lbWarningMsg.setText(Bundle.ManageArtifactTypesDialog_noneSelected()); + lbWarningMsg.setText(Bundle.ManageCorrelationPropertiesDialog_noneSelected()); } return true; } @@ -135,14 +135,14 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog { setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(ManageArtifactTypesDialog.class, "ManageArtifactTypesDialog.okButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(ManageCorrelationPropertiesDialog.class, "ManageCorrelationPropertiesDialog.okButton.text")); // NOI18N okButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { okButtonActionPerformed(evt); } }); - org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(ManageArtifactTypesDialog.class, "ManageArtifactTypesDialog.cancelButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(ManageCorrelationPropertiesDialog.class, "ManageCorrelationPropertiesDialog.cancelButton.text")); // NOI18N cancelButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cancelButtonActionPerformed(evt); @@ -156,7 +156,7 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog { }, new String [] { - "Artifact Type", "Enable" + "Correlation Properties", "Enable" } ) { Class[] types = new Class [] { @@ -180,7 +180,7 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog { lbWarningMsg.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N lbWarningMsg.setForeground(new java.awt.Color(255, 0, 0)); - org.openide.awt.Mnemonics.setLocalizedText(lbWarningMsg, org.openide.util.NbBundle.getMessage(ManageArtifactTypesDialog.class, "ManageArtifactTypesDialog.lbWarningMsg.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(lbWarningMsg, org.openide.util.NbBundle.getMessage(ManageCorrelationPropertiesDialog.class, "ManageCorrelationPropertiesDialog.lbWarningMsg.text")); // NOI18N taInstructions.setEditable(false); taInstructions.setBackground(new java.awt.Color(240, 240, 240)); @@ -188,7 +188,7 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog { taInstructions.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N taInstructions.setLineWrap(true); taInstructions.setRows(5); - taInstructions.setText(org.openide.util.NbBundle.getMessage(ManageArtifactTypesDialog.class, "ManageArtifactTypesDialog.taInstructionsMsg.text")); // NOI18N + taInstructions.setText(org.openide.util.NbBundle.getMessage(ManageCorrelationPropertiesDialog.class, "ManageArtifactTypesDialog.taInstructionsMsg.text")); // NOI18N taInstructions.setWrapStyleWord(true); taInstructions.setAutoscrolls(false); taInstructions.setBorder(null); @@ -239,20 +239,20 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog { dispose(); }//GEN-LAST:event_cancelButtonActionPerformed - @Messages({"ManageArtifactTypesDialog.okbutton.failure=Error saving updated selections."}) + @Messages({"ManageCorrelationPropertiesDialog.okbutton.failure=Error saving updated selections."}) private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed - if (0 == eamArtifactTypes.size()) { + if (0 == correlationTypes.size()) { dispose(); } else { EamDb dbManager = EamDb.getInstance(); - eamArtifactTypes.forEach((aType) -> { + correlationTypes.forEach((aType) -> { try { - dbManager.updateCorrelationArtifactType(aType); + dbManager.updateCorrelationType(aType); dispose(); } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Failed to updated Enterprise Artifacts Manager artifact types with selections from dialog.", ex); // NON-NLS - lbWarningMsg.setText(Bundle.ManageArtifactTypesDialog_okbutton_failure()); + LOGGER.log(Level.SEVERE, "Failed to update correlation properties with selections from dialog.", ex); // NON-NLS + lbWarningMsg.setText(Bundle.ManageCorrelationPropertiesDialog_okbutton_failure()); } }); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageTagsDialog.form b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form similarity index 89% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageTagsDialog.form rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form index 60a7cd7c1d..209313f26f 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageTagsDialog.form +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form @@ -59,7 +59,7 @@ - + @@ -69,7 +69,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageTagsDialog.java b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java similarity index 97% rename from Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageTagsDialog.java rename to CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java index df4b70ecc2..876a3546d7 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/ManageTagsDialog.java +++ b/CentralRepository/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java @@ -1,5 +1,5 @@ /* - * Enterprise Artifacts Manager + * Central Repository * * Copyright 2015-2017 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel; +package org.sleuthkit.autopsy.centralrepository.optionspanel; import java.awt.Dimension; import java.awt.Toolkit; @@ -29,11 +29,10 @@ import javax.swing.JFrame; import javax.swing.table.DefaultTableModel; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.TagsManager; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb; /** * Instances of this class allow a user to select an existing hash database and diff --git a/Core/manifest.mf b/Core/manifest.mf index c38806aaa0..ff950c1b37 100644 --- a/Core/manifest.mf +++ b/Core/manifest.mf @@ -2,7 +2,7 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.core/10 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml -OpenIDE-Module-Implementation-Version: 19 +OpenIDE-Module-Implementation-Version: 20 OpenIDE-Module-Requires: org.openide.windows.WindowManager AutoUpdate-Show-In-Client: true AutoUpdate-Essential-Module: true diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index ddb1df5848..30ce57d6f0 100644 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -28,5 +28,5 @@ nbm.module.author=Brian Carrier nbm.needs.restart=true source.reference.metadata-extractor-2.8.1.jar=release/modules/ext/metadata-extractor-2.8.1-src.zip!/Source/ source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar -spec.version.base=10.7 +spec.version.base=10.8 diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index 8ad63473d4..2c9fa00b0d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -32,8 +32,14 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JMenuItem; import javax.swing.SwingWorker; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.TableColumnModelEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; +import javax.swing.event.TableColumnModelListener; +import javax.swing.text.JTextComponent; +import javax.swing.text.View; import org.apache.commons.lang.StringUtils; import org.openide.nodes.Node; import org.openide.util.Lookup; @@ -52,8 +58,8 @@ import org.netbeans.swing.etable.ETable; /** * Instances of this class display the BlackboardArtifacts associated with the - * Content represented by a Node. Each BlackboardArtifact is rendered displayed in a JTable - * representation of its BlackboardAttributes. + * Content represented by a Node. Each BlackboardArtifact is rendered displayed + * in a JTable representation of its BlackboardAttributes. */ @ServiceProvider(service = DataContentViewer.class, position = 3) public class DataContentViewerArtifact extends javax.swing.JPanel implements DataContentViewer { @@ -78,6 +84,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat Bundle.DataContentViewerArtifact_attrsTableHeader_value(), Bundle.DataContentViewerArtifact_attrsTableHeader_sources()}; private static final int[] COLUMN_WIDTHS = {100, 800, 100}; + private static final int CELL_BOTTOM_MARGIN = 5; public DataContentViewerArtifact() { initResultsTable(); @@ -85,6 +92,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat resultsTableScrollPane.setViewportView(resultsTable); customizeComponents(); resetComponents(); + resultsTable.setDefaultRenderer(Object.class, new MultiLineTableCellRenderer()); } private void initResultsTable() { @@ -100,11 +108,71 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat resultsTable.getTableHeader().setReorderingAllowed(false); resultsTable.setColumnHidingAllowed(false); resultsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION); - updateColumnSizes(); + resultsTable.getColumnModel().addColumnModelListener(new TableColumnModelListener() { + + @Override + public void columnAdded(TableColumnModelEvent e) { + } + + @Override + public void columnRemoved(TableColumnModelEvent e) { + } + + @Override + public void columnMoved(TableColumnModelEvent e) { + + } + + @Override + public void columnMarginChanged(ChangeEvent e) { + updateRowHeights(); //When the user changes column width we may need to resize row height + } + + @Override + public void columnSelectionChanged(ListSelectionEvent e) { + } + }); + resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN); + } + /** + * Sets the row heights to the heights of the content in their Value column. + */ + private void updateRowHeights() { + int valueColIndex = -1; + for (int col = 0; col < resultsTable.getColumnCount(); col++) { + if (resultsTable.getColumnName(col).equals(COLUMN_HEADERS[1])) { + valueColIndex = col; + } + } + if (valueColIndex != -1) { + for (int row = 0; row < resultsTable.getRowCount(); row++) { + Component comp = resultsTable.prepareRenderer( + resultsTable.getCellRenderer(row, valueColIndex), row, valueColIndex); + final int rowHeight; + if (comp instanceof JTextComponent) { + final JTextComponent tc = (JTextComponent) comp; + final View rootView = tc.getUI().getRootView(tc); + java.awt.Insets i = tc.getInsets(null); + rootView.setSize(resultsTable.getColumnModel().getColumn(valueColIndex) + .getPreferredWidth() - i.left - i.right, + Integer.MAX_VALUE); + rowHeight = (int) rootView.getPreferredSpan(View.Y_AXIS); + } else { + rowHeight = comp.getPreferredSize().height; + } + if (rowHeight > 0) { + resultsTable.setRowHeight(row, rowHeight + CELL_BOTTOM_MARGIN); + } + } + } + } + + /** + * Update the column widths so that the Value column has most of the space. + */ private void updateColumnSizes() { - resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN); Enumeration columns = resultsTable.getColumnModel().getColumns(); while (columns.hasMoreElements()) { TableColumn col = columns.nextElement(); @@ -551,6 +619,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel()); tModel.setDataVector(viewUpdate.tableContents.getRows(), COLUMN_HEADERS); updateColumnSizes(); + updateRowHeights(); resultsTable.clearSelection(); this.setCursor(null); @@ -568,6 +637,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel()); tModel.setDataVector(waitRow, COLUMN_HEADERS); updateColumnSizes(); + updateRowHeights(); resultsTable.clearSelection(); // The output of the previous task is no longer relevant. if (currentTask != null) { @@ -758,4 +828,27 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat } } } + + /** + * TableCellRenderer for displaying multiline text. + */ + private class MultiLineTableCellRenderer implements javax.swing.table.TableCellRenderer { + + @Override + public Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + javax.swing.JTextArea jtex = new javax.swing.JTextArea(); + if (value instanceof String) { + jtex.setText((String) value); + jtex.setLineWrap(true); + jtex.setWrapStyleWord(true); + } + //cell backgroud color when selected + if (isSelected) { + jtex.setBackground(javax.swing.UIManager.getColor("Table.selectionBackground")); + } else { + jtex.setBackground(javax.swing.UIManager.getColor("Table.background")); + } + return jtex; + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNode.java index 33dc37e66f..c723d99b55 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNode.java @@ -94,12 +94,15 @@ public abstract class DisplayableItemNode extends AbstractNode { } /** - * Accepts a DisplayableItemNodeVisitor. + * Accepts a visitor DisplayableItemNodeVisitor that will perform an + * operation on this artifact type and return some object as the result of + * the operation. * - * @param The type parameter of the visitor. - * @param visitor The visitor. + * @param visitor The visitor, where the type parameter of the visitor is + * the type of the object that will be returned as the result + * of the visit operation. * - * @return + * @return An object of type T. */ public abstract T accept(DisplayableItemNodeVisitor visitor); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java index 5cfddc7f7a..8f0802007e 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java @@ -51,7 +51,9 @@ import org.sleuthkit.datamodel.TskData; /** * Filters database results by file extension. */ - public final class FileTypesByExtension implements AutopsyVisitableItem { +public final class FileTypesByExtension implements AutopsyVisitableItem { + + private static final Logger LOGGER = Logger.getLogger(FileTypesByExtension.class.getName()); private final SleuthkitCase skCase; @@ -72,13 +74,63 @@ import org.sleuthkit.datamodel.TskData; * Listens for case and ingest invest. Updates observers when events are * fired. FileType and FileTypes nodes are all listening to this. */ - private static class FileTypesByExtObservable extends Observable { + static private class FileTypesByExtObservable extends Observable { - private FileTypesByExtObservable() { + private boolean showCounts = true; + private final PropertyChangeListener pcl; + + private FileTypesByExtObservable(SleuthkitCase skCase) { super(); + this.pcl = (PropertyChangeEvent evt) -> { + String eventType = evt.getPropertyName(); + if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString()) || eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { + /** + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. + */ + try { + Case.getCurrentCase(); + shouldShowCounts(skCase); + update(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + // case was closed. Remove listeners so that we don't get called with a stale case handle + if (evt.getNewValue() == null) { + removeListeners(); + } + } + }; + IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); Case.addPropertyChangeListener(pcl); + + } + + /** + * Should the nodes show counts? + * + * + * @return True, unless the DB has more than 200k rows. + */ + private boolean shouldShowCounts(SleuthkitCase skCase) { + if (showCounts) { + try { + if (skCase.countFilesWhere("1=1") > 200000) { + showCounts = false; + } + } catch (TskCoreException tskCoreException) { + showCounts = false; + LOGGER.log(Level.SEVERE, "Error counting files.", tskCoreException); + } + } + return showCounts; } private void removeListeners() { @@ -88,31 +140,6 @@ import org.sleuthkit.datamodel.TskData; Case.removePropertyChangeListener(pcl); } - private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { - String eventType = evt.getPropertyName(); - if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString()) || eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { - /** - * Checking for a current case is a stop gap measure until a - * different way of handling the closing of cases is worked out. - * Currently, remote events may be received for a case that is - * already closed. - */ - try { - Case.getCurrentCase(); - update(); - } catch (IllegalStateException notUsed) { - /** - * Case is closed, do nothing. - */ - } - } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { - // case was closed. Remove listeners so that we don't get called with a stale case handle - if (evt.getNewValue() == null) { - removeListeners(); - } - } - }; - private void update() { setChanged(); notifyObservers(); @@ -146,7 +173,7 @@ import org.sleuthkit.datamodel.TskData; * @param o Observable that was created by a higher-level node that * provides updates on events */ - private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, Observable o) { + private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) { super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); this.filter = filter; init(); @@ -206,7 +233,7 @@ import org.sleuthkit.datamodel.TskData; private final SleuthkitCase skCase; private final FileTypesByExtension.RootFilter filter; - private final Observable notifier; + private final FileTypesByExtObservable notifier; /** * @@ -215,12 +242,12 @@ import org.sleuthkit.datamodel.TskData; * @param o Observable that provides updates based on events * being fired (or null if one needs to be created) */ - private FileTypesByExtNodeChildren(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, Observable o) { + private FileTypesByExtNodeChildren(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) { super(); this.skCase = skCase; this.filter = filter; if (o == null) { - this.notifier = new FileTypesByExtObservable(); + this.notifier = new FileTypesByExtObservable(skCase); } else { this.notifier = o; } @@ -263,6 +290,7 @@ import org.sleuthkit.datamodel.TskData; FileTypesByExtension.SearchFilterInterface filter; SleuthkitCase skCase; + private final FileTypesByExtObservable notifier; /** * @@ -271,10 +299,11 @@ import org.sleuthkit.datamodel.TskData; * @param o Observable that sends updates when the child factories * should refresh */ - FileExtensionNode(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) { + FileExtensionNode(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, FileTypesByExtObservable o) { super(Children.create(new FileExtensionNodeChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName())); this.filter = filter; this.skCase = skCase; + this.notifier = o; init(); o.addObserver(new ByExtNodeObserver()); } @@ -295,8 +324,10 @@ import org.sleuthkit.datamodel.TskData; } private void updateDisplayName() { - final long count = FileExtensionNodeChildren.calculateItems(skCase, filter); - super.setDisplayName(filter.getDisplayName() + " (" + count + ")"); + final String count = notifier.shouldShowCounts(skCase) + ? " (" + Long.toString(FileExtensionNodeChildren.calculateItems(skCase, filter)) + ")" + : ""; + super.setDisplayName(filter.getDisplayName() + count); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 1549d6bdc1..2ccc1dc1e8 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -71,41 +71,18 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi private final HashMap> existingMimeTypes = new HashMap<>(); private static final Logger LOGGER = Logger.getLogger(FileTypesByMimeType.class.getName()); + private boolean showCounts = true; + private void removeListeners() { deleteObservers(); IngestManager.getInstance().removeIngestJobEventListener(pcl); Case.removePropertyChangeListener(pcl); } - /* * The pcl is in the class because it has the easiest mechanisms to add and * remove itself during its life cycles. */ - private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { - String eventType = evt.getPropertyName(); - if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - - /** - * Checking for a current case is a stop gap measure until a - * different way of handling the closing of cases is worked out. - * Currently, remote events may be received for a case that is - * already closed. - */ - try { - Case.getCurrentCase(); - populateHashMap(); - } catch (IllegalStateException notUsed) { - /** - * Case is closed, do nothing. - */ - } - } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { - if (evt.getNewValue() == null) { - removeListeners(); - } - } - }; + private final PropertyChangeListener pcl; /** * Retrieve the media types by retrieving the keyset from the hashmap. @@ -140,7 +117,6 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi existingMimeTypes.clear(); if (skCase == null) { - return; } try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(allDistinctMimeTypesQuery.toString())) { @@ -170,12 +146,59 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi } FileTypesByMimeType(SleuthkitCase skCase) { + this.pcl = (PropertyChangeEvent evt) -> { + String eventType = evt.getPropertyName(); + if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { + + /** + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked out. + * Currently, remote events may be received for a case that is + * already closed. + */ + try { + Case.getCurrentCase(); + shouldShowCounts(skCase); + + populateHashMap(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + if (evt.getNewValue() == null) { + removeListeners(); + } + } + }; IngestManager.getInstance().addIngestJobEventListener(pcl); Case.addPropertyChangeListener(pcl); this.skCase = skCase; populateHashMap(); } + /** + * Should the nodes show counts? + * + * + * @return True, unless the DB has more than 200k rows. + */ + private boolean shouldShowCounts(final SleuthkitCase skCase) { + if (showCounts) { + try { + if (skCase.countFilesWhere("1=1") > 200000) { + showCounts = false; + } + } catch (TskCoreException tskCoreException) { + showCounts = false; + LOGGER.log(Level.SEVERE, "Error counting files.", tskCoreException); + } + } + return showCounts; + } + @Override public T accept(AutopsyItemVisitor v) { return v.visit(this); @@ -358,10 +381,12 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi * results */ private void updateDisplayName(String mimeType) { - final long count = new MediaSubTypeNodeChildren(mimeType).calculateItems(skCase, mimeType); + final String count = shouldShowCounts(skCase) + ? " (" + Long.toString(new MediaSubTypeNodeChildren(mimeType).calculateItems(skCase, mimeType)) + ")" + : ""; String[] mimeTypeParts = mimeType.split("/"); //joins up all remaining parts of the mimeType into one sub-type string - super.setDisplayName(StringUtils.join(ArrayUtils.subarray(mimeTypeParts, 1, mimeTypeParts.length), "/") + " (" + count + ")"); + super.setDisplayName(StringUtils.join(ArrayUtils.subarray(mimeTypeParts, 1, mimeTypeParts.length), "/") + count); } /** diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java index f488e741e3..f237243dd0 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java @@ -55,7 +55,7 @@ import org.sleuthkit.datamodel.VolumeSystem; * selecting the parent in the tree view, then selecting the content in the * results view. */ -public final class ViewContextAction extends AbstractAction { +public class ViewContextAction extends AbstractAction { private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(ViewContextAction.class.getName()); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactory.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactory.java index 59b5b64d9c..5b522d552a 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactory.java @@ -49,7 +49,7 @@ package org.sleuthkit.autopsy.ingest; * implementations must be marked with the following NetBeans Service provider * annotation: * - *
@ServiceProvider(service=IngestModuleFactory.class)
+ *
\@ServiceProvider(service=IngestModuleFactory.class)
*

* IMPORTANT TIP: If an implementation of IngestModuleFactory does not need to * provide implementations of all of the IngestModuleFactory methods, it can diff --git a/Experimental/build.xml b/Experimental/build.xml index 07de3bd2f4..b3923a5c30 100644 --- a/Experimental/build.xml +++ b/Experimental/build.xml @@ -13,17 +13,13 @@ - + - - - - diff --git a/Experimental/ivy.xml b/Experimental/ivy.xml index 4b336cfd9e..e50fab6472 100644 --- a/Experimental/ivy.xml +++ b/Experimental/ivy.xml @@ -3,8 +3,6 @@ - - @@ -13,13 +11,5 @@ - - - - - - - - diff --git a/Experimental/manifest.mf b/Experimental/manifest.mf index eb45e376b8..cafb630948 100644 --- a/Experimental/manifest.mf +++ b/Experimental/manifest.mf @@ -4,4 +4,3 @@ OpenIDE-Module: org.sleuthkit.autopsy.experimental OpenIDE-Module-Layer: org/sleuthkit/autopsy/experimental/autoingest/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties OpenIDE-Module-Specification-Version: 1.0 -OpenIDE-Module-Install: org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/Installer.class \ No newline at end of file diff --git a/Experimental/nbproject/project.xml b/Experimental/nbproject/project.xml index c990077688..280fbc431b 100644 --- a/Experimental/nbproject/project.xml +++ b/Experimental/nbproject/project.xml @@ -110,7 +110,7 @@ 10 - 10.7 + 10.8 @@ -156,26 +156,6 @@ ext/c3p0-0.9.5.jar release/modules/ext/c3p0-0.9.5.jar - - ext/commons-dbcp2-2.1.1.jar - release/modules/ext/commons-dbcp2-2.1.1.jar - - - ext/commons-logging-1.2.jar - release/modules/ext/commons-logging-1.2.jar - - - ext/commons-pool2-2.4.2.jar - release/modules/ext/commons-pool2-2.4.2.jar - - - ext/postgresql-42.0.0.jar - release/modules/ext/postgresql-42.0.0.jar - - - ext/sqlite-jdbc-3.16.1.jar - release/modules/ext/sqlite-jdbc-3.16.1.jar - diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 4c1cea69b8..afae397553 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -774,8 +774,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang } } - - /** * Removes a set of auto ingest jobs from a collection of jobs. * @@ -915,8 +913,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang AutoIngestManager.this.completedJobs = newCompletedJobsList; } catch (Exception ex) { - /* NOTE: Need to catch all exceptions here. Otherwise uncaught exceptions will - propagate up to the calling thread and may stop it from running.*/ + /* + * NOTE: Need to catch all exceptions here. Otherwise + * uncaught exceptions will propagate up to the calling + * thread and may stop it from running. + */ SYS_LOGGER.log(Level.SEVERE, String.format("Error scanning the input directory %s", rootInputDirectory), ex); } } @@ -2274,6 +2275,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang * is shutting down. */ ingestLock.wait(); + SYS_LOGGER.log(Level.INFO, "Finished ingest modules analysis for {0} ", manifestPath); IngestJob.ProgressSnapshot jobSnapshot = ingestJob.getSnapshot(); for (IngestJob.ProgressSnapshot.DataSourceProcessingSnapshot snapshot : jobSnapshot.getDataSourceSnapshots()) { if (!snapshot.isCancelled()) { @@ -2505,9 +2507,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang String eventType = event.getPropertyName(); if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { synchronized (ingestLock) { - if (!IngestManager.getInstance().isIngestRunning()) { - ingestLock.notify(); - } + ingestLock.notify(); } } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java index 0811a52c2b..e7b633a133 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/SharedConfiguration.java @@ -79,7 +79,7 @@ public class SharedConfiguration { private static final String HASHDB_CONFIG_FILE_NAME = "hashLookup.settings"; //NON-NLS private static final String HASHDB_CONFIG_FILE_NAME_LEGACY = "hashsets.xml"; //NON-NLS public static final String FILE_EXPORTER_SETTINGS_FILE = "fileexporter.settings"; //NON-NLS - private static final String ENTERPRISE_ARTIFACTS_MANAGER_PROPERTIES_FILE = "EnterpriseArtifactsManager.properties"; //NON-NLS + private static final String CENTRAL_REPOSITORY_PROPERTIES_FILE = "CentralRepository.properties"; //NON-NLS private static final String SHARED_CONFIG_VERSIONS = "SharedConfigVersions.txt"; //NON-NLS // Folders @@ -206,7 +206,7 @@ public class SharedConfiguration { uploadMultiUserAndGeneralSettings(remoteFolder); uploadHashDbSettings(remoteFolder); uploadFileExporterSettings(remoteFolder); - uploadEnterpriseArtifactsManagerSettings(remoteFolder); + uploadCentralRepositorySettings(remoteFolder); try { Files.deleteIfExists(uploadInProgress.toPath()); @@ -271,7 +271,7 @@ public class SharedConfiguration { downloadFileExtMismatchSettings(remoteFolder); downloadAndroidTriageSettings(remoteFolder); downloadFileExporterSettings(remoteFolder); - downloadEnterpriseArtifactsManagerSettings(remoteFolder); + downloadCentralRepositorySettings(remoteFolder); // Download general settings, then restore the current // values for the unshared fields @@ -778,27 +778,27 @@ public class SharedConfiguration { } /** - * Upload Enterprise Artifacts Manager settings. + * Upload Central Repository settings. * * @param remoteFolder Shared settings folder * * @throws SharedConfigurationException */ - private void uploadEnterpriseArtifactsManagerSettings(File remoteFolder) throws SharedConfigurationException { - publishTask("Uploading Enterprise Artifacts Manager configuration"); - copyToRemoteFolder(ENTERPRISE_ARTIFACTS_MANAGER_PROPERTIES_FILE, moduleDirPath, remoteFolder, true); + private void uploadCentralRepositorySettings(File remoteFolder) throws SharedConfigurationException { + publishTask("Uploading Central Repository configuration"); + copyToRemoteFolder(CENTRAL_REPOSITORY_PROPERTIES_FILE, moduleDirPath, remoteFolder, true); } /** - * Download Enterprise Artifacts Manager settings. + * Download Central Repository settings. * * @param remoteFolder Shared settings folder * * @throws SharedConfigurationException */ - private void downloadEnterpriseArtifactsManagerSettings(File remoteFolder) throws SharedConfigurationException { - publishTask("Downloading Enterprise Artifacts Manager configuration"); - copyToLocalFolder(ENTERPRISE_ARTIFACTS_MANAGER_PROPERTIES_FILE, moduleDirPath, remoteFolder, true); + private void downloadCentralRepositorySettings(File remoteFolder) throws SharedConfigurationException { + publishTask("Downloading Central Repository configuration"); + copyToLocalFolder(CENTRAL_REPOSITORY_PROPERTIES_FILE, moduleDirPath, remoteFolder, true); } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/Bundle.properties deleted file mode 100644 index ad927009be..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/Bundle.properties +++ /dev/null @@ -1,7 +0,0 @@ -OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Name=Enterprise Artifacts Manager -OpenIDE-Module-Short-Description=Enterprise Artifacts Manager Ingest Module -OpenIDE-Module-Long-Description=\ - Enterprise Artifacts Manager ingest module. \n\n\ - This ingest module stores artifacts of selected types into a central database.\n\ - Stored artifacts are used by future cases to compare and analyzes file and artifacts during ingest. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifact.java b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifact.java deleted file mode 100644 index dd33b5e0e9..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/datamodel/EamArtifact.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Enterprise Artifacts Manager - * - * Copyright 2015-2017 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * - * Used to store info about a specific artifact. - */ -public class EamArtifact implements Serializable { - - private static final long serialVersionUID = 1L; - - private String ID; - private String artifactValue; - private Type artifactType; - private final List artifactInstances; - - /** - * Load the default correlation artifact types - */ - public static List getDefaultArtifactTypes() { - List DEFAULT_ARTIFACT_TYPES = new ArrayList<>(); - DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("FILES", true, true)); // NON-NLS - DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("DOMAIN", true, false)); // NON-NLS - DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("EMAIL", true, false)); // NON-NLS - DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("PHONE", true, false)); // NON-NLS - DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("USBID", true, false)); // NON-NLS - return DEFAULT_ARTIFACT_TYPES; - } - - public EamArtifact(Type artifactType, String artifactValue) { - this.ID = ""; - this.artifactType = artifactType; - this.artifactValue = artifactValue; - this.artifactInstances = new ArrayList<>(); - } - - public Boolean equals(EamArtifact otherArtifact) { - return ((this.getID().equals(otherArtifact.getID())) - && (this.getArtifactType().equals(otherArtifact.getArtifactType())) - && (this.getArtifactValue().equals(otherArtifact.getArtifactValue())) - && (this.getInstances().equals(otherArtifact.getInstances()))); - } - - @Override - public String toString() { - String result = this.getID() - + this.getArtifactType().toString() - + this.getArtifactValue(); - result = this.getInstances().stream().map((inst) -> inst.toString()).reduce(result, String::concat); - return result; - } - - /** - * @return the ID - */ - public String getID() { - return ID; - } - - /** - * @param ID the ID to set - */ - public void setID(String ID) { - this.ID = ID; - } - - /** - * @return the artifactValue - */ - public String getArtifactValue() { - return artifactValue; - } - - /** - * @param artifactValue the artifactValue to set - */ - public void setArtifactValue(String artifactValue) { - this.artifactValue = artifactValue; - } - - /** - * @return the artifact Type - */ - public Type getArtifactType() { - return artifactType; - } - - /** - * @param artifactType the artifact Type to set - */ - public void setArtifactType(Type artifactType) { - this.artifactType = artifactType; - } - - /** - * @return the List of artifactInstances; empty list of none have been - * added. - */ - public List getInstances() { - return new ArrayList<>(artifactInstances); - } - - /** - * @param artifactInstances the List of artifactInstances to set. - */ - public void setInstances(List artifactInstances) { - this.artifactInstances.clear(); - if (null != artifactInstances) { - this.artifactInstances.addAll(artifactInstances); - } - } - - /** - * @param instance the instance to add - */ - public void addInstance(EamArtifactInstance artifactInstance) { - this.artifactInstances.add(artifactInstance); - } - - public static class Type implements Serializable { - - private int id; - private String name; - private Boolean supported; - private Boolean enabled; - - public Type(int id, String name, Boolean supported, Boolean enabled) { - this.id = id; - this.name = name; - this.supported = supported; - this.enabled = enabled; - } - - public Type(String name, Boolean supported, Boolean enabled) { - this(-1, name, supported, enabled); - } - - /** - * Determine if 2 Type objects are equal based on having the same - * Type.name. - * - * @param otherType Type object for comparison. - * - * @return true or false - */ - @Override - public boolean equals(Object that) { - if (this == that) { - return true; - } else if (!(that instanceof EamArtifact.Type)) { - return false; - } else { - return ((EamArtifact.Type) that).sameType(this); - } - } - - /** - * Determines if the content of this artifact type object is equivalent - * to the content of another artifact type object. - * - * @param that the other type - * - * @return true if it is the same type - */ - private boolean sameType(EamArtifact.Type that) { - return this.id == that.getId() - && this.name.equals(that.getName()) - && Objects.equals(this.supported, that.isSupported()) - && Objects.equals(this.enabled, that.isEnabled()); - } - - @Override - public int hashCode() { - int hash = 7; - hash = 67 * hash + Objects.hashCode(this.id); - hash = 67 * hash + Objects.hashCode(this.name); - hash = 67 * hash + Objects.hashCode(this.supported); - hash = 67 * hash + Objects.hashCode(this.enabled); - return hash; - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder(); - str.append("(id=").append(id); - str.append(", name=").append(name); - str.append(", supported=").append(supported.toString()); - str.append(", enabled=").append(enabled.toString()); - str.append(")"); - return str.toString(); - } - - /** - * @return the id - */ - public int getId() { - return id; - } - - /** - * @param id the id to set - */ - public void setId(int id) { - this.id = id; - } - - /** - * Get the name of this Artifact Type. - * - * @return the name - */ - public String getName() { - return name; - } - - /** - * Set the name of this Artifact Type - * - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } - - /** - * Check if this Artifact Type is supported. - * - * @return true or false - */ - public Boolean isSupported() { - return supported; - } - - /** - * Set this Artifact Type as supported or not supported. - * - * @param supported the supported to set - */ - public void setSupported(Boolean supported) { - this.supported = supported; - } - - /** - * Check if this Artifact Type is enabled. - * - * @return true or false - */ - public Boolean isEnabled() { - return enabled; - } - - /** - * Set this Artifact Type as enabled or not enabled. - * - * @param enabled the enabled to set - */ - public void setEnabled(Boolean enabled) { - this.enabled = enabled; - } - } -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/docs/CONFIG.md b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/docs/CONFIG.md deleted file mode 100644 index d3bd10561e..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/docs/CONFIG.md +++ /dev/null @@ -1,140 +0,0 @@ -# Configuration - -## Database Setup - -There are 2 choices for database platforms: SQLite and PostgreSQL. -1. SQLite is a database in a file stored locally on the same host that is running Autopsy. -There is nothing to do to setup this database. It will be created by Autopsy on your -behalf, if it doesn't already exist. -2. PostgreSQL is a database server that can be run either on the same host that is -running Autopsy or on a remote server. To use PostgreSQL with the EnterpriseArtifactManager module, -you will need the server to be running, have an existing database named "enterpriseartifactmanagerdb" -and have an existing user/pass with ownership of the enterpriseartifactmanagerdb database. -The tables and indices will be automatically created by Autopsy. -See the [Autopsy multi-user settings documentation[(http://sleuthkit.org/autopsy/docs/user-docs/4.3/install_postgresql.html) for help setting up your PostgreSQL server. - -## Enable Module and Configure Database Settings - -In the menu go to: Tools -> Options -> EnterpriseArtifactManager - -1. Check the box to Enable Enterprise Artifact Manager. This will enable the Database Platform dropdown and Configure button. -2. In the dropdown, select the database platform that you want to use. -3. Click the Configure button to configure the settings for the chosen database platform. -4. Click the Apply button to save your database configuration settings. - -### Configure SQLite Database Settings - -There is only one step here, to specify the path and filename for the database. -You can accept the default value or use the Open button to choose another path. -The database file name can be called anything you want, but it is convenient to -give it a ".db" suffix. - -Once you have selected the path, click the Test Connection button. -If you see a green check next to the button, everything is ready to go. -If you see a red check next to the button, there is a problem with the path -you selected and you'll have to resolve that problem. - -Once the test passes, click the Save button to save your selection and close the window. - -### Configure PostgreSQL Database Settings - -For PostgreSQL all values are required, but some defaults are provided for convenience. - -1. Host Name/IP is the hostname or IP of your PostgreSQL server. -2. Port is the port that the PostgreSQL server is listening on; default is 5432. -3. Database name is the name of the database you are using for this module; default is enterpriseartifactmanagerdb. -4. User Name is the PostgreSQL user that owns and has full permissions to the database specified in step 3. -5. User Password is the password for the user. - -Once all values have been entered, click the Test Connection button. -If you see a green check next to the button, everything is ready to go. -If you see a red check next to the button, there is a problem with the values -you entered and you'll have to resolve that problem. - -Once the test passes, click the Save button to save your selection and close the window. - -## Import Globally Known Artifacts - -The purpose of this feature is to store any Known or Known Bad Artifacts in -the database. Think of this feature like a dynamic Hash List. -These artifacts are used during Ingest to flag files as Interesting. -They are also displayed in the Content Viewer when a file or artifact is selected that is -associated with one of the globally known artifacts. - -When importing a hash database, all fields are required. - -1. Select the Database Path using the Open button. This is the file containing -the hash values that you want to import. You can import multiple files, but only -one at a time. The format of these files must be the same format as used by -the hash database module. -2. Select the database type. The type of content in the database being imported. -3. Define the attribution for this database. - a. Select the Source Organization in the dropdown list. -This is the organization that provided the hash database to you. - b. If you do not see the Organization in the list, use the [Add New Organization](FEATURES.md#adding-a-new-organization) button to add it. -Once you add it, you can then select it in the dropdown list. - c. Enter a name for the dataset. This can be anything you want, but is often something like "child porn", "drugs", "malware", "corp hashlist", etc. - d. Enter a version number for that dataset. This can be anything you want, but is often something like "1.0", "1.1a", 20170505", etc. -4. Click the OK button to start the import. - -## Manage Correlatable Tags - -In Autopsy, you are allowed to define your own Tag names, tag files and artifacts, - and add comments when you tag a file or artifact. - -The purpose of this feature is to associate one or more of those tags with this module -to be used for Correlation. -By default there is a tag called "Evidence" as the only tag associated with this module. - -To associate one or more tag(s) with this module, check the Correlate box next to the tag -name(s) and click OK. - -### What does it mean for a tag to be associated with this module? - -Any file or artifact that a user tags with one of the associated tags will be -added to the database as a file or artifact of interest. -Any future data source ingest, where this module is enabled, will use those -files or artifacts as if they were part of the Known Bad list, causing matching files -from that ingest to be added to the Interesting Artifacts list in that currently open case. - -The term Correlate means that files processed during a future ingest will be correlated -with files existing in the database. - -As an example, I have a case open and I tag an image called "evilphoto.png" with the -default "Evidence" tag. That image will be stored in the database as a file of interest. -In the next data source that I ingest for the same case or a future case, -if an image with the same MD5 hash as "evilphoto.png" -is found, it will be automatically added to the Interesting Files tree and assumed -to be evidence. -This makes it easy to find and flag things in future cases that you know are -Interesting. - -## Manage Correlation Types - -This feature allows the user to control how much data is being stored in the database -to use for correlation and analysis. -By default, only FILES is enabled. -Select the types that you want to enable and click OK. - -The meaning of each type is as follows: - -* FILES - file path and MD5 hash -* DOMAIN - domain name -* EMAIL - email address -* PHONE - phone number -* USBID - device ID of connected USB devices. - -### What does Correlation mean? - -Artifacts stored in the database are available for this module to use for analysis. -That analysis comes in many forms. -When a file or artifact is extracted during ingest, this module will use the database -to find other files or artifacts that match it, to determine if that new file should be -flagged as an Interesting File. - -If that file or artifact does not exist in the database, and that Correlation Type -is enabled, then it will be added to the database. - -Having more data in the database will obviously allow this module to be more thorough, -but for some, database size is a concern, so we allow them to select a subset of data -to collect and use for analysis. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/docs/DEVELOP.md b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/docs/DEVELOP.md deleted file mode 100644 index 5b61ce70c4..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/docs/DEVELOP.md +++ /dev/null @@ -1,61 +0,0 @@ -# Instructions for doing development of Autopsy Modules - -## On Windows, Setup your development environment with Autopsy sources and javadocs - -* Install x64 PostgreSQL and setup: - * http://sleuthkit.org/autopsy/docs/user-docs/4.3/install_postgresql.html - -* Install Oracle Java SE JDK 8 - Windows x64 from Oracle: - * http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html - -* Install NetBeans (choose the 'All' version): - * https://netbeans.org/downloads/ - -* Install Git for Windows x64: - * https://git-scm.com/downloads - -* Install doxygen and make sure it is added to your PATH - * http://www.stack.nl/~dimitri/doxygen/download.html - -* Sleuthkit and the DataModel java bindings - * Clone sleuthkit repo and set TSK_HOME environment variable. - * For the java bindings, there are two ways to get these - 1. [build Sleuthkit and then the java bindings](https://github.com/sleuthkit/sleuthkit/blob/develop/win32/BUILDING.txt), requiring Visual Studio and several - dependant libraries. - 2. download the [Autopsy dev platform zip](https://github.com/sleuthkit/autopsy/releases/download/autopsy-4.4.0/autopsy-4.4.0-devplatform.zip) and copy autopsy-4.4.0-devplatform/autopsy/modules/ext/Tsk_DataModel_PostgreSQL.jar to TSK_HOME/bindings/java/dist/ - * Set up environment variables, sample values: - - JAVA_HOME=C:\Program Files\Java\jdk1.8.0_121 - - JDK_HOME=C:\Program Files\Java\jdk1.8.0_121 - - JRE_HOME_64=C:\Program Files\Java\jre1.8.0_121 - - LIBEWF_HOME=C:\libewf_64bit (only needed if you chose option #1 above) - - LIBVHDI_HOME=C:\libvhdi_64bit (only needed if you chose option #1 above) - - POSTGRESQL_HOME_64=c:\Program Files\PostgreSQL\9.6 (only needed if you chose option #1 above) - - TSK_HOME=c:\sleuthkit - - PATH=...;C:\Program Files\Java\jdk1.8.0_121\bin;C:\Program Files\NetBeans 8.2\extide\ant\bin;C:\Program Files\doxygen\bin - -* Build Autopsy platform: - * Reference: https://github.com/sleuthkit/autopsy/blob/develop/BUILDING.txt - * Clone Autopsy project - * git clone git@github.com:sleuthkit/autopsy.git - * git checkout develop - * Add Autopsy project to NetBeans - * File -> Open Project - * Build the top level Autopsy project - * Generate javadoc and add doc folder in the documentation tab - -If the project builds correctly, everything is installed correctly. - -## How to build disk images for development/testing - -Refer to MS technet instructions for creating/using a VHD: https://technet.microsoft.com/en-us/library/gg318052(v=ws.10).aspx - -But here is the general idea: -* On Windows, use Disk Management tool to create a Virtual Hard Disk (.vhd) using the "dynamically expanding" disk format. Choose a small-ish disk size if you want the testing to be quick. -* Initialize the disk (Initialize Disk). -* Format the disk (New Simple Volume). -* Mount that disk (Attach VHD) -* Copy some files onto the disk. -* Umount that disk (Detach VHD). Do NOT delete the disk when detaching! - -Repeat the above steps to create additional disk images. - diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/docs/FEATURES.md b/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/docs/FEATURES.md deleted file mode 100644 index de96fee0a0..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/docs/FEATURES.md +++ /dev/null @@ -1,116 +0,0 @@ -# Features - -Once you have configured everything, created a case, and have run the ingest of at least one data source, -you can make use of some other exciting features that are described below. - -## Content Viewer - -This module adds a new tab to the [Content Viewer](http://sleuthkit.org/autopsy/docs/user-docs/4.3/content_viewer_page.html). -The tab for this module is called "Other Cases". -It can display data that is found in other cases, other data sources for the same case, or imported global artifacts. - -If at least one other case or data source has been ingested with this module enabled, -there is a potential that data will be displayed in the Other Cases content viewer. -If the selected file or artifact is associated by one of the supported Correlation Types, -to one or more file(s) or artifact(s) in the database, the associated files/artifacts will be displayed. -Note: the Content Viewer will display ALL associated files and artifacts available in the database. -It ignores the user's [enabled/disabled Correlation Types](CONFIG.md#manage-correlation-types). - -If the user right-clicks on a row, a menu will be displayed. -This menu has several options. -1. [Show Commonality Details](FEATURES.md#show-commonality-details) -2. [Save to CSV](FEATURES.md#save-to-csv) -3. [Show Case Details](FEATURES.md#show-case-details) -4. [Select All](FEATURES.md#select-all) - -Click option for more details. - -### Rows in the table - -By default, the rows in the content viewer will have background colors to indicate if they -are known to be of interest. -Files/artifacts that are Known Bad will have a Red background, Unknown will have Yellow background, -and Known will have a White background. - -The user can click on any column heading to sort by the values in that column. - -### Show Commonality Details - -The concept of Commonality simply means, how common is the selected file. -The value is the percentage of case/data source tuples that have the selected file or artifact. - -### Save to CSV - -This option will save ALL SELECTED rows in the Content Viewer table to a CSV file. -By default, the CSV file is saved into the Export directory inside the currently open Autopsy case, -but the user is free to select a different location. - -Note: if you want to copy/paste rows, it is usually possible to use CTRL+C to copy the -selected rows and then CTRL+V to paste them into a file, but it will not be CSV formatted. - -### Show Case Details - -This option will open a dialog that displays all of the relevant details for the selected case. -The details will include: -1. Case UUID -2. Case Name -3. Case Creation Date -4. Case Examiner contact information -5. Case Examiner's notes - -These details would have been entered by the examiner of the selected case, by visiting -the Case -> Enterprise Artifact Manager Case Details menu, when that case was open. - -### Select All - -This option will select all rows in the Content Viewer table. - -## Interesting Items tree - -In the Results tree of an open case is an entry called Interesting Items. -When this module is enabled, all of the enabled Correlatable Types will cause -matching files to be added to this Interesting Items tree during ingest. - -As an example, if the FILES Correlatable Type is enabled, and the ingest is -currently processing a file, for example "badfile.exe", and the MD5 hash for that -file already exists in the database as a KNOWN BAD file, then an entry in the Interesting Items tree -will be added for the current instance of "badfile.exe" in the data source currently being ingested. - -The same type of thing will happen for each [enabled Correlatable Type](CONFIG.md#manage-correlation-types). - -In the case of the PHONE correlatable type, the Interesting Items tree will start -a sub-tree for each phone number. The sub-tree will then contain each instance of that -Known Bad phone number. - -## Edit Enterprise Artifact Manager Case Details - -By default, Autopsy lets you edit Case Details in the Case menu. -When this module is enabled, there is an additional option in the Case menu, -called "Enterprise Artifact Manager Case Details". - -This is where the examiner can store a number of details about the case. -1. The organization of the case examiner. -2. The contact information of the case examiner. -3. The case examiner's case notes. - -To define the organization of the case examiner, simply select the organization name -from the dropdown box. -If the organization is not listed, you can click [Add New Organization](FEATURES.md#adding-a-new-organization) button. -Once the new organization is added, it should be available in the dropdown box. - -## Adding a New Organization - -An Organization can have two purposes in this module. - -1. It defines the Organization that the forensic examiner belongs to. -This organization is selected or added when Editing Correlation Case Details. -2. It defines the Organization that is the source of a Globally Known Artifact List. -This organization is selected or added during Import of a Globally Known Artifact hash list. - -When adding a new organization, only the Organization Name is required. -It is recommended to also include a Point of Contact for that organization. -This will be someone that is a manager or team lead at that Organization that -could be contacted for any questions about a case or a shared Globally Known Artifact -hash list. - -Click OK to save the new Organization. diff --git a/ImageGallery/nbproject/project.xml b/ImageGallery/nbproject/project.xml index b9e8b60120..14e60b0a5a 100644 --- a/ImageGallery/nbproject/project.xml +++ b/ImageGallery/nbproject/project.xml @@ -127,7 +127,7 @@ 10 - 10.7 + 10.8 diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index 45abae006a..d375e76868 100644 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -119,7 +119,7 @@ 10 - 10.7 + 10.8 diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties index 1a14ddf308..99d88938ce 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties @@ -236,10 +236,10 @@ KeywordSearchGlobalLanguageSettingsPanel.ingestSettingsLabel.text=Ingest setting KeywordSearchGlobalLanguageSettingsPanel.enableUTF16Checkbox.text=Enable UTF16LE and UTF16BE string extraction KeywordSearchGlobalLanguageSettingsPanel.languagesLabel.text=Enabled scripts (languages): KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.toolTipText=20 mins. (fastest ingest time) -KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20 minutes +KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20 minutes (slowest feedback, fastest ingest) KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.toolTipText=10 minutes (faster overall ingest time than default) -KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text=10 minutes -KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text=Results update frequency during ingest (we have not seen significant performance differences between 5, 10, or 20 minute intervals): +KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text=10 minutes (slower feedback, faster ingest) +KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text=Results update frequency during ingest: KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.toolTipText=Requires Hash DB service to had run previously, or be selected for next ingest. KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.text=Do not add files in NSRL (known files) to keyword index during ingest KeywordSearchGlobalSearchSettingsPanel.informationLabel.text=Information @@ -249,7 +249,7 @@ KeywordSearchGlobalSearchSettingsPanel.filesIndexedLabel.text=Files in keyword i KeywordSearchGlobalSearchSettingsPanel.showSnippetsCB.text=Show Keyword Preview in Keyword Search Results (will result in longer search times) KeywordSearchGlobalSearchSettingsPanel.chunksValLabel.text=0 KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.toolTipText=1 minute (overall ingest time will be longest) -KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1=1 minute +KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1=1 minute (faster feedback, longest ingest) KeywordSearchGlobalSearchSettingsPanel.chunksLabel.text=Chunks in keyword index: KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.toolTipText=5 minutes (overall ingest time will be longer) KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.text=5 minutes (default) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java index 08a6b38165..830c93325a 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java @@ -161,10 +161,10 @@ public final class KeywordSearchIngestModule implements FileIngestModule { try { Index indexInfo = server.getIndexInfo(); if (!IndexFinder.getCurrentSolrVersion().equals(indexInfo.getSolrVersion())) { - throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSolrVersionNotSupported(indexInfo.getSolrVersion())); + throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSolrVersionNotSupported(indexInfo.getSolrVersion())); } if (!IndexFinder.getCurrentSchemaVersion().equals(indexInfo.getSchemaVersion())) { - throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSchemaNotSupported(indexInfo.getSchemaVersion())); + throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSchemaNotSupported(indexInfo.getSchemaVersion())); } } catch (NoOpenCoreException ex) { throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupMessage_failedToGetIndexSchema(), ex); @@ -249,7 +249,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule { public ProcessResult process(AbstractFile abstractFile) { if (initialized == false) //error initializing indexing/Solr { - logger.log(Level.WARNING, "Skipping processing, module not initialized, file: {0}", abstractFile.getName()); //NON-NLS + logger.log(Level.SEVERE, "Skipping processing, module not initialized, file: {0}", abstractFile.getName()); //NON-NLS putIngestStatus(jobId, abstractFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING); return ProcessResult.OK; } @@ -293,14 +293,16 @@ public final class KeywordSearchIngestModule implements FileIngestModule { */ @Override public void shutDown() { - logger.log(Level.INFO, "Instance {0}", instanceNum); //NON-NLS + logger.log(Level.INFO, "Keyword search ingest module instance {0} shutting down", instanceNum); //NON-NLS if ((initialized == false) || (context == null)) { return; } if (context.fileIngestIsCancelled()) { - stop(); + logger.log(Level.INFO, "Keyword search ingest module instance {0} stopping search job due to ingest cancellation", instanceNum); //NON-NLS + SearchRunner.getInstance().stopJob(jobId); + cleanup(); return; } @@ -309,34 +311,20 @@ public final class KeywordSearchIngestModule implements FileIngestModule { // We only need to post the summary msg from the last module per job if (refCounter.decrementAndGet(jobId) == 0) { + try { + final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles(); + logger.log(Level.INFO, "Indexed files count: {0}", numIndexedFiles); //NON-NLS + final int numIndexedChunks = KeywordSearch.getServer().queryNumIndexedChunks(); + logger.log(Level.INFO, "Indexed file chunks count: {0}", numIndexedChunks); //NON-NLS + } catch (NoOpenCoreException | KeywordSearchModuleException ex) { + logger.log(Level.SEVERE, "Error executing Solr queries to check number of indexed files and file chunks", ex); //NON-NLS + } postIndexSummary(); synchronized (ingestStatus) { ingestStatus.remove(jobId); } } - //log number of files / chunks in index - //signal a potential change in number of text_ingested files - try { - final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles(); - final int numIndexedChunks = KeywordSearch.getServer().queryNumIndexedChunks(); - logger.log(Level.INFO, "Indexed files count: {0}", numIndexedFiles); //NON-NLS - logger.log(Level.INFO, "Indexed file chunks count: {0}", numIndexedChunks); //NON-NLS - } catch (NoOpenCoreException | KeywordSearchModuleException ex) { - logger.log(Level.WARNING, "Error executing Solr query to check number of indexed files/chunks: ", ex); //NON-NLS - } - - cleanup(); - } - - /** - * Handle stop event (ingest interrupted) Cleanup resources, threads, timers - */ - private void stop() { - logger.log(Level.INFO, "stop()"); //NON-NLS - - SearchRunner.getInstance().stopJob(jobId); - cleanup(); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java index 6f5407e4a4..1a2ffd1200 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java @@ -131,6 +131,7 @@ public final class SearchRunner { } if (readyForFinalSearch) { + logger.log(Level.INFO, "Commiting search index before final search for search job {0}", job.getJobId()); //NON-NLS commit(); doFinalSearch(job); //this will block until it's done } @@ -189,7 +190,7 @@ public final class SearchRunner { final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles(); KeywordSearch.fireNumIndexedFilesChange(null, numIndexedFiles); } catch (NoOpenCoreException | KeywordSearchModuleException ex) { - logger.log(Level.WARNING, "Error executing Solr query to check number of indexed files: ", ex); //NON-NLS + logger.log(Level.SEVERE, "Error executing Solr query to check number of indexed files", ex); //NON-NLS } } @@ -201,21 +202,25 @@ public final class SearchRunner { */ private void doFinalSearch(SearchJobInfo job) { // Run one last search as there are probably some new files committed - logger.log(Level.INFO, "Running final search for jobid {0}", job.getJobId()); //NON-NLS + logger.log(Level.INFO, "Starting final search for search job {0}", job.getJobId()); //NON-NLS if (!job.getKeywordListNames().isEmpty()) { try { // In case this job still has a worker running, wait for it to finish + logger.log(Level.INFO, "Checking for previous search for search job {0} before executing final search", job.getJobId()); //NON-NLS job.waitForCurrentWorker(); SearchRunner.Searcher finalSearcher = new SearchRunner.Searcher(job, true); job.setCurrentSearcher(finalSearcher); //save the ref + logger.log(Level.INFO, "Kicking off final search for search job {0}", job.getJobId()); //NON-NLS finalSearcher.execute(); //start thread // block until the search is complete + logger.log(Level.INFO, "Waiting for final search for search job {0}", job.getJobId()); //NON-NLS finalSearcher.get(); + logger.log(Level.INFO, "Final search for search job {0} completed", job.getJobId()); //NON-NLS } catch (InterruptedException | CancellationException ex) { - logger.log(Level.INFO, "Final search for search job {1} interrupted or cancelled", job.getJobId()); //NON-NLS + logger.log(Level.INFO, "Final search for search job {0} interrupted or cancelled", job.getJobId()); //NON-NLS } catch (ExecutionException ex) { logger.log(Level.SEVERE, String.format("Final search for search job %d failed", job.getJobId()), ex); //NON-NLS } @@ -246,6 +251,7 @@ public final class SearchRunner { SearchJobInfo job = j.getValue(); // If no lists or the worker is already running then skip it if (!job.getKeywordListNames().isEmpty() && !job.isWorkerRunning()) { + logger.log(Level.INFO, "Executing periodic search for search job {0}", job.getJobId()); Searcher searcher = new Searcher(job); job.setCurrentSearcher(searcher); //save the ref searcher.execute(); //start thread @@ -341,7 +347,9 @@ public final class SearchRunner { private void waitForCurrentWorker() throws InterruptedException { synchronized (finalSearchLock) { while (workerRunning) { + logger.log(Level.INFO, "Waiting for previous worker to finish"); //NON-NLS finalSearchLock.wait(); //wait() releases the lock + logger.log(Level.INFO, "Notified previous worker finished"); //NON-NLS } } } @@ -351,6 +359,7 @@ public final class SearchRunner { */ private void searchNotify() { synchronized (finalSearchLock) { + logger.log(Level.INFO, "Notifying after finishing search"); //NON-NLS workerRunning = false; finalSearchLock.notify(); } @@ -505,8 +514,7 @@ public final class SearchRunner { try { finalizeSearcher(); stopWatch.stop(); - - logger.log(Level.INFO, "Searcher took to run: {0} secs.", stopWatch.getElapsedTimeSecs()); //NON-NLS + logger.log(Level.INFO, "Searcher took {0} secs to run (final = {1})", new Object[]{stopWatch.getElapsedTimeSecs(), this.finalRun}); //NON-NLS } finally { // In case a thread is waiting on this worker to be done job.searchNotify(); @@ -520,7 +528,9 @@ public final class SearchRunner { protected void done() { // call get to see if there were any errors try { + logger.log(Level.INFO, "Searcher calling get() on itself in done()"); //NON-NLS get(); + logger.log(Level.INFO, "Searcher finished calling get() on itself in done()"); //NON-NLS } catch (InterruptedException | ExecutionException e) { logger.log(Level.SEVERE, "Error performing keyword search: " + e.getMessage()); //NON-NLS services.postMessage(IngestMessage.createErrorMessage(KeywordSearchModuleFactory.getModuleName(), @@ -566,17 +576,18 @@ public final class SearchRunner { } /** - * This method filters out all of the hits found in earlier - * periodic searches and returns only the results found by the most - * recent search. + * This method filters out all of the hits found in earlier periodic + * searches and returns only the results found by the most recent + * search. * * This method will only return hits for objects for which we haven't * previously seen a hit for the keyword. - * + * * @param queryResult The results returned by a keyword search. - * @return A unique set of hits found by the most recent search for objects - * that have not previously had a hit. The hits will be for the lowest - * numbered chunk associated with the object. + * + * @return A unique set of hits found by the most recent search for + * objects that have not previously had a hit. The hits will be + * for the lowest numbered chunk associated with the object. * */ private QueryResults filterResults(QueryResults queryResult) { diff --git a/NEWS.txt b/NEWS.txt index a07761dfdd..351a8f2d9f 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -7,13 +7,13 @@ and can be applied to either the table viewer or the thumbnail viewer. correctly. - The View Source File in Directory context menu item now works correctly. - Tagged image files in the HTML report are now displayed full-size. -- A new enterprise artifact manager feature has been added to the optional -Experimental plug-in (NetBeans module; this optional feature includes a database -(SQLite or PostgreSQL) and logic for correlating artifacts across cases; results -are displayed using an Interesting Artifacts branch of the Interesting Items -tree and a content viewer. +- A new central repository feature has been added to the optional +CentralRepository plug-in (NetBeans module; this optional feature includes a +database (SQLite or PostgreSQL) and logic for correlating artifacts across +cases; results are displayed using an Interesting Artifacts branch of the +Interesting Items tree and an Other Data Sources content viewer. - Some potential deadlocks during ingest have been eliminated. -- Assorted small enhancements and bug fixes. +- Assorted small enhancements and bug fixes are included. ---------------- VERSION 4.4.0 -------------- Improvements: diff --git a/RecentActivity/nbproject/project.xml b/RecentActivity/nbproject/project.xml index e3559b4155..198dc619db 100644 --- a/RecentActivity/nbproject/project.xml +++ b/RecentActivity/nbproject/project.xml @@ -60,7 +60,7 @@ 10 - 10.7 + 10.8 diff --git a/Testing/nbproject/project.xml b/Testing/nbproject/project.xml index cfaf244b7b..7d8e0b6fc5 100644 --- a/Testing/nbproject/project.xml +++ b/Testing/nbproject/project.xml @@ -47,7 +47,7 @@ 10 - 10.7 + 10.8 diff --git a/build.xml b/build.xml index 43534a7495..b0d244b119 100755 --- a/build.xml +++ b/build.xml @@ -265,6 +265,7 @@ + diff --git a/docs/doxygen-user/installSolr.dox b/docs/doxygen-user/installSolr.dox index 0547e6e65f..d47904df08 100755 --- a/docs/doxygen-user/installSolr.dox +++ b/docs/doxygen-user/installSolr.dox @@ -1,7 +1,5 @@ -/*! \page install_solr Install and Configure Solr and Zookeeper -A central Solr server is needed to store keyword indexes. Zookeeper is used to manage Solr configuration and as a coordination service for Autopsy. It is installed as part of Bitnami Solr package, but has to be configured separately. To install Solr, perform the following steps: - - +/*! \page install_solr Install and Configure Solr +A central Solr server is needed to store keyword indexes, and its embedded Zookeeper is used as a coordination service for Autopsy. To install Solr, perform the following steps: \section install_solr_prereq Prerequisites @@ -81,22 +79,13 @@ The following steps will configure Solr to run using an account that will have a

5. From an Autopsy installation, copy the folder "C:\Program Files\Autopsy-XXX(current version)\autopsy\solr\solr\configsets" to "C:\Bitnami\solr-4.10.3-0\apache-solr\solr". 6. From an Autopsy installation, copy the folder "C:\Program Files\Autopsy-XXX(current version)\autopsy\solr\solr\lib" to "C:\Bitnami\solr-4.10.3-0\apache-solr\solr". -\subsection configure_Zookeeper Zookeeper Configuration - - The following steps will configure Zookeeper. - 1. Stop the solrJetty service by pressing Start, typing services.msc, pressing Enter, and locating the solrJetty Windows service. Select the service and press Stop the service. If the service is already stopped and there is no Stop the service available, this is okay. - 2. Start a Windows command prompt as administrator by pressing Start, typing command, right clicking on Command Prompt, and clicking on Run as administrator. Then run the following command to uninstall the solrJetty service: +7. Stop the solrJetty service by pressing Start, typing services.msc, pressing Enter, and locating the solrJetty Windows service. Select the service and press Stop the service. If the service is already stopped and there is no Stop the service available, this is okay. +8. Start a Windows command prompt as administrator by pressing Start, typing command, right clicking on Command Prompt, and clicking on Run as administrator. Then run the following command to uninstall the solrJetty service: cmd /c C:\Bitnami\solr-4.10.3-0\apache-solr\scripts\serviceinstall.bat UNINSTALL You will very likely see a result that says "The solrJetty service is not started." This is okay. - - 3. Create a folder "C:\Bitnami\zookeeper" if it does not exist. - 4. Edit "C:\Bitnami\solr-4.10.3-0\apache-solr\solr\zoo.cfg" to include the text dataDir=C:/Bitnami/zookeeper as shown in the screenshot below -

- \image html zooDir.PNG -
- 5. Start a Windows command prompt as administrator by pressing Start, typing command, right clicking on Command Prompt, and clicking on Run as administrator. Then run the following command to install the solrJetty service: +9. Start a Windows command prompt as administrator by pressing Start, typing command, right clicking on Command Prompt, and clicking on Run as administrator. Then run the following command to install the solrJetty service: cmd /c C:\Bitnami\solr-4.10.3-0\apache-solr\scripts\serviceinstall.bat INSTALL
Note the argument "INSTALL" is case sensitive. Your command prompt should look like the screenshot below. Very likely your command prompt will say "The solrJetty service could not be started." This is okay. diff --git a/nbproject/project.properties b/nbproject/project.properties index f970ea2eb7..8cceb63bc8 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -10,6 +10,7 @@ build.type=RELEASE #build.type=DEVELOPMENT project.org.netbeans.progress=org-netbeans-api-progress +project.org.sleuthkit.autopsy.centralrepository=CentralRepository project.org.sleuthkit.autopsy.experimental=Experimental project.org.sleuthkit.autopsy.imagegallery=ImageGallery update_versions=false @@ -31,7 +32,8 @@ modules=\ ${project.org.sleuthkit.autopsy.core}:\ ${project.org.sleuthkit.autopsy.corelibs}:\ ${project.org.sleuthkit.autopsy.imagegallery}:\ - ${project.org.sleuthkit.autopsy.experimental} + ${project.org.sleuthkit.autopsy.experimental}:\ + ${project.org.sleuthkit.autopsy.centralrepository} project.org.sleuthkit.autopsy.core=Core project.org.sleuthkit.autopsy.corelibs=CoreLibs project.org.sleuthkit.autopsy.keywordsearch=KeywordSearch diff --git a/thirdparty/apache-mime4j/apache-mime4j-core-0.8.0-SNAPSHOT.jar b/thirdparty/apache-mime4j/apache-mime4j-core-0.8.0-SNAPSHOT.jar new file mode 100644 index 0000000000..0aff45bb7d Binary files /dev/null and b/thirdparty/apache-mime4j/apache-mime4j-core-0.8.0-SNAPSHOT.jar differ diff --git a/thirdparty/apache-mime4j/apache-mime4j-dom-0.8.0-SNAPSHOT.jar b/thirdparty/apache-mime4j/apache-mime4j-dom-0.8.0-SNAPSHOT.jar new file mode 100644 index 0000000000..773ab544ca Binary files /dev/null and b/thirdparty/apache-mime4j/apache-mime4j-dom-0.8.0-SNAPSHOT.jar differ diff --git a/thirdparty/apache-mime4j/apache-mime4j-mbox-iterator-0.8.0-SNAPSHOT.jar b/thirdparty/apache-mime4j/apache-mime4j-mbox-iterator-0.8.0-SNAPSHOT.jar new file mode 100644 index 0000000000..bb7d15da61 Binary files /dev/null and b/thirdparty/apache-mime4j/apache-mime4j-mbox-iterator-0.8.0-SNAPSHOT.jar differ diff --git a/thirdparty/rr-full/plugins/appcompatcache.pl b/thirdparty/rr-full/plugins/appcompatcache.pl index 332a31838a..2e43785121 100644 --- a/thirdparty/rr-full/plugins/appcompatcache.pl +++ b/thirdparty/rr-full/plugins/appcompatcache.pl @@ -296,6 +296,7 @@ sub appWin8 { while($ofs < $len) { my $tag = unpack("V",substr($data,$ofs,4)); + last unless (defined $tag); # 32-bit if ($tag == 0x73746f72) { $jmp = unpack("V",substr($data,$ofs + 8,4)); @@ -340,6 +341,7 @@ sub appWin10 { while ($ofs < $len) { $tag = substr($data,$ofs,4); + last unless (defined $tag); if ($tag eq "10ts") { $sz = unpack("V",substr($data,$ofs + 0x08,4)); diff --git a/thirdparty/rr-full/plugins/appcompatcache_tln.pl b/thirdparty/rr-full/plugins/appcompatcache_tln.pl index e349d09320..fd767b51e0 100644 --- a/thirdparty/rr-full/plugins/appcompatcache_tln.pl +++ b/thirdparty/rr-full/plugins/appcompatcache_tln.pl @@ -291,6 +291,7 @@ sub appWin8 { while($ofs < $len) { my $tag = unpack("V",substr($data,$ofs,4)); + last unless (defined $tag); # 32-bit if ($tag == 0x73746f72) { $jmp = unpack("V",substr($data,$ofs + 8,4)); @@ -335,6 +336,7 @@ sub appWin10 { while ($ofs < $len) { $tag = substr($data,$ofs,4); + last unless (defined $tag); if ($tag eq "10ts") { $sz = unpack("V",substr($data,$ofs + 0x08,4)); diff --git a/thirdparty/rr-full/plugins/arpcache.pl b/thirdparty/rr-full/plugins/arpcache.pl index b4b8a2a1f2..3a0b733ca2 100644 --- a/thirdparty/rr-full/plugins/arpcache.pl +++ b/thirdparty/rr-full/plugins/arpcache.pl @@ -122,6 +122,7 @@ sub parsePath { while($tag) { $ofs += 2; my $i = substr($data,$ofs,2); + last unless (defined $i); if (unpack("v",$i) == 0) { $tag = 0; } diff --git a/thirdparty/rr-full/plugins/comdlg32.pl b/thirdparty/rr-full/plugins/comdlg32.pl index 7eecfaaabf..1f41837ff2 100644 --- a/thirdparty/rr-full/plugins/comdlg32.pl +++ b/thirdparty/rr-full/plugins/comdlg32.pl @@ -386,6 +386,7 @@ sub parseShellItem { while ($tag) { my %item = (); my $sz = unpack("v",substr($data,$cnt,2)); + return %str unless (defined $sz); $tag = 0 if (($sz == 0) || ($cnt + $sz > $len)); my $dat = substr($data,$cnt,$sz); @@ -544,6 +545,7 @@ sub parseFolderEntry { my $str = ""; while($tag) { my $s = substr($data,$ofs_shortname + $cnt,1); + return %item unless (defined $s); if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) { $tag = 0; } @@ -559,10 +561,12 @@ sub parseFolderEntry { $tag = 1; $cnt = 0; while ($tag) { - if (unpack("v",substr($data,$ofs + $cnt,2)) == 0xbeef) { + my $s = substr($data,$ofs + $cnt,2); + return %item unless (defined $s); + if (unpack("v",$s) == 0xbeef) { $tag = 0; } - else { + else { $cnt++; } } diff --git a/thirdparty/rr-full/plugins/itempos.pl b/thirdparty/rr-full/plugins/itempos.pl index a1e309196a..8f5d4562b8 100644 --- a/thirdparty/rr-full/plugins/itempos.pl +++ b/thirdparty/rr-full/plugins/itempos.pl @@ -228,6 +228,7 @@ sub parseFolderItem { my $str = ""; while($tag) { my $s = substr($data,$ofs_shortname + $cnt,1); + return %item unless (defined $s); if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) { $tag = 0; } @@ -243,7 +244,9 @@ sub parseFolderItem { $tag = 1; $cnt = 0; while ($tag) { - if (unpack("v",substr($data,$ofs + $cnt,2)) == 0xbeef) { + my $s = substr($data,$ofs + $cnt,2); + return %item unless (defined $s); + if (unpack("v",$s) == 0xbeef) { $tag = 0; } else { diff --git a/thirdparty/rr-full/plugins/shellbags.pl b/thirdparty/rr-full/plugins/shellbags.pl index 7625f0b83f..5b8587af38 100644 --- a/thirdparty/rr-full/plugins/shellbags.pl +++ b/thirdparty/rr-full/plugins/shellbags.pl @@ -378,6 +378,7 @@ sub parseVariableEntry { my $cnt = 0x10; while($tag) { my $sz = unpack("V",substr($stuff,$cnt,4)); + return %item unless (defined $sz); my $id = unpack("V",substr($stuff,$cnt + 4,4)); #-------------------------------------------------------------- # sub-segment types @@ -421,6 +422,7 @@ sub parseVariableEntry { my $t = 1; while ($t) { my $i = substr($data,$o,1); + return %item unless (defined $i); if ($i =~ m/\x00/) { $t = 0; } @@ -732,6 +734,7 @@ sub parseFolderEntry { my $str = ""; while($tag) { my $s = substr($data,$ofs_shortname + $cnt,1); + return %item unless (defined $s); if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) { $tag = 0; } @@ -747,7 +750,9 @@ sub parseFolderEntry { $tag = 1; $cnt = 0; while ($tag) { - if (unpack("v",substr($data,$ofs + $cnt,2)) == 0xbeef) { + my $s = substr($data,$ofs + $cnt,2); + return %item unless (defined $s); + if (unpack("v",$s) == 0xbeef) { $tag = 0; } else { @@ -850,7 +855,9 @@ sub parseFolderEntry2 { my $tag = 1; while ($tag) { - if (unpack("v",substr($data,$ofs,2)) == 0xbeef) { + my $s = substr($data,$ofs,2); + return %item unless (defined $s); + if (unpack("v",$s) == 0xbeef) { $tag = 0; } else { @@ -951,6 +958,7 @@ sub shellItem0x52 { while ($tag) { $d = substr($data,0x32 + $cnt,2); + return %item unless (defined $d); if (unpack("v",$d) == 0) { $tag = 0; } diff --git a/thirdparty/rr-full/plugins/shellbags_test.pl b/thirdparty/rr-full/plugins/shellbags_test.pl index 800592a8c2..2c4e7bda3d 100644 --- a/thirdparty/rr-full/plugins/shellbags_test.pl +++ b/thirdparty/rr-full/plugins/shellbags_test.pl @@ -358,6 +358,7 @@ sub parseFolderItem { my $str = ""; while($tag) { my $s = substr($data,$ofs_shortname + $cnt,1); + return %item unless (defined $s); if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) { $tag = 0; } @@ -373,7 +374,9 @@ sub parseFolderItem { $tag = 1; $cnt = 0; while ($tag) { - if (unpack("v",substr($data,$ofs + $cnt,2)) == 0xbeef) { + my $s = substr($data,$ofs + $cnt,2); + return %item unless (defined $s); + if (unpack("v",$s) == 0xbeef) { $tag = 0; } else { diff --git a/thirdparty/rr-full/plugins/shellbags_tln.pl b/thirdparty/rr-full/plugins/shellbags_tln.pl index c8f5bd0b22..bbbd3fe309 100644 --- a/thirdparty/rr-full/plugins/shellbags_tln.pl +++ b/thirdparty/rr-full/plugins/shellbags_tln.pl @@ -356,6 +356,7 @@ sub parseVariableEntry { while($tag) { my $sz = unpack("V",substr($stuff,$cnt,4)); my $id = unpack("V",substr($stuff,$cnt + 4,4)); + return %item unless (defined $sz); #-------------------------------------------------------------- # sub-segment types # 0x0a - file name @@ -386,6 +387,7 @@ sub parseVariableEntry { # my $sz = unpack("V",substr($stuff,$cnt,4)); # my $id = unpack("V",substr($stuff,$cnt + 4,4)); # +# return %item unless (defined $sz); # if ($sz == 0x00) { # $tag = 0; # next; @@ -652,6 +654,7 @@ sub parseFolderEntry { my $str = ""; while($tag) { my $s = substr($data,$ofs_shortname + $cnt,1); + return %item unless (defined $s); if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) { $tag = 0; } @@ -667,7 +670,9 @@ sub parseFolderEntry { $tag = 1; $cnt = 0; while ($tag) { - if (unpack("v",substr($data,$ofs + $cnt,2)) == 0xbeef) { + my $s = substr($data,$ofs + $cnt,2); + return %item unless (defined $s); + if (unpack("v",$s) == 0xbeef) { $tag = 0; } else { diff --git a/thirdparty/rr-full/plugins/shellbags_xp.pl b/thirdparty/rr-full/plugins/shellbags_xp.pl index 2c427d6638..b4f8ee2b00 100644 --- a/thirdparty/rr-full/plugins/shellbags_xp.pl +++ b/thirdparty/rr-full/plugins/shellbags_xp.pl @@ -397,7 +397,8 @@ sub parseVariableEntry { # 0x0e, 0x0f, 0x10 - mod date, create date, access date(?) # 0x0c - size #-------------------------------------------------------------- - if ($sz == 0x00) { + return %item unless (defined $sz); + if ($sz == 0x00) { $tag = 0; next; } @@ -419,7 +420,7 @@ sub parseVariableEntry { # while($tag) { # my $sz = unpack("V",substr($stuff,$cnt,4)); # my $id = unpack("V",substr($stuff,$cnt + 4,4)); -# +# return %item unless (defined $sz); # if ($sz == 0x00) { # $tag = 0; # next; @@ -725,6 +726,7 @@ sub parseFolderEntry { my $str = ""; while($tag) { my $s = substr($data,$ofs_shortname + $cnt,1); + return %item unless (defined $s); if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) { $tag = 0; } @@ -740,7 +742,9 @@ sub parseFolderEntry { $tag = 1; $cnt = 0; while ($tag) { - if (unpack("v",substr($data,$ofs + $cnt,2)) == 0xbeef) { + my $s = substr($data,$ofs + $cnt,2); + return %item unless (defined $s); + if (unpack("v",$s) == 0xbeef) { $tag = 0; } else { @@ -829,7 +833,9 @@ sub parseFolderEntry2 { my $tag = 1; while ($tag) { - if (unpack("v",substr($data,$ofs,2)) == 0xbeef) { + my $s = substr($data,$ofs,2); + return %item unless (defined $s); + if (unpack("v",$s) == 0xbeef) { $tag = 0; } else { diff --git a/thirdparty/rr-full/plugins/shimcache.pl b/thirdparty/rr-full/plugins/shimcache.pl index 527eb4dcc6..125143fbda 100755 --- a/thirdparty/rr-full/plugins/shimcache.pl +++ b/thirdparty/rr-full/plugins/shimcache.pl @@ -283,6 +283,7 @@ sub appWin8 { while($ofs < $len) { my $tag = unpack("V",substr($data,$ofs,4)); + last unless (defined $tag); # 32-bit if ($tag == 0x73746f72) { $jmp = unpack("V",substr($data,$ofs + 8,4)); @@ -327,6 +328,7 @@ sub appWin10 { while ($ofs < $len) { $tag = substr($data,$ofs,4); + last unless (defined $tag); if ($tag eq "10ts") { $sz = unpack("V",substr($data,$ofs + 0x08,4)); diff --git a/thirdparty/rr-full/plugins/shimcache_tln.pl b/thirdparty/rr-full/plugins/shimcache_tln.pl index 1e03d645ce..b0fa1588b6 100755 --- a/thirdparty/rr-full/plugins/shimcache_tln.pl +++ b/thirdparty/rr-full/plugins/shimcache_tln.pl @@ -277,6 +277,7 @@ sub appWin8 { while($ofs < $len) { my $tag = unpack("V",substr($data,$ofs,4)); + last unless (defined $tag); # 32-bit if ($tag == 0x73746f72) { $jmp = unpack("V",substr($data,$ofs + 8,4)); @@ -321,6 +322,7 @@ sub appWin10 { while ($ofs < $len) { $tag = substr($data,$ofs,4); + last unless (defined $tag); if ($tag eq "10ts") { $sz = unpack("V",substr($data,$ofs + 0x08,4)); diff --git a/thunderbirdparser/build.xml b/thunderbirdparser/build.xml index 80c452ef31..0b0a4fe2dd 100644 --- a/thunderbirdparser/build.xml +++ b/thunderbirdparser/build.xml @@ -20,6 +20,9 @@ + + + diff --git a/thunderbirdparser/nbproject/project.properties b/thunderbirdparser/nbproject/project.properties index e21eb352f8..ceee1f4265 100644 --- a/thunderbirdparser/nbproject/project.properties +++ b/thunderbirdparser/nbproject/project.properties @@ -1,6 +1,6 @@ -file.reference.apache-mime4j-core-0.8.0.jar=release/modules/ext/apache-mime4j-core-0.8.0.jar -file.reference.apache-mime4j-dom-0.8.0.jar=release/modules/ext/apache-mime4j-dom-0.8.0.jar -file.reference.apache-mime4j-mbox-iterator-0.8.0.jar=release/modules/ext/apache-mime4j-mbox-iterator-0.8.0.jar +file.reference.apache-mime4j-core-0.8.0.jar=release/modules/ext/apache-mime4j-core-0.8.0-SNAPSHOT.jar +file.reference.apache-mime4j-dom-0.8.0.jar=release/modules/ext/apache-mime4j-dom-0.8.0-SNAPSHOT.jar +file.reference.apache-mime4j-mbox-iterator-0.8.0.jar=release/modules/ext/apache-mime4j-mbox-iterator-0.8.0-SNAPSHOT.jar file.reference.java-libpst-1.0-SNAPSHOT.jar=release/modules/ext/java-libpst-1.0-SNAPSHOT.jar javac.source=1.8 javac.compilerargs=-Xlint -Xlint:-serial diff --git a/thunderbirdparser/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml index 060c91a323..e0aea0045c 100644 --- a/thunderbirdparser/nbproject/project.xml +++ b/thunderbirdparser/nbproject/project.xml @@ -36,7 +36,7 @@ 10 - 10.7 + 10.8
@@ -51,20 +51,20 @@ - ext/apache-mime4j-core-0.8.0.jar - release/modules/ext/apache-mime4j-core-0.8.0.jar + ext/apache-mime4j-core-0.8.0-SNAPSHOT.jar + release/modules/ext/apache-mime4j-core-0.8.0-SNAPSHOT.jar - ext/apache-mime4j-dom-0.8.0.jar - release/modules/ext/apache-mime4j-dom-0.8.0.jar + ext/apache-mime4j-dom-0.8.0-SNAPSHOT.jar + release/modules/ext/apache-mime4j-dom-0.8.0-SNAPSHOT.jar ext/java-libpst-1.0-SNAPSHOT.jar release/modules/ext/java-libpst-1.0-SNAPSHOT.jar - ext/apache-mime4j-mbox-iterator-0.8.0.jar - release/modules/ext/apache-mime4j-mbox-iterator-0.8.0.jar + ext/apache-mime4j-mbox-iterator-0.8.0-SNAPSHOT.jar + release/modules/ext/apache-mime4j-mbox-iterator-0.8.0-SNAPSHOT.jar