From f003254ad547bbc7acb4679b2d018dcc8dfa85f6 Mon Sep 17 00:00:00 2001 From: Raman Date: Thu, 4 Jan 2018 15:31:54 -0500 Subject: [PATCH 01/52] 3414: Create generic Application Content Viewer --- .../ApplicationContentViewer.form | 41 +++ .../ApplicationContentViewer.java | 251 ++++++++++++++++++ .../autopsy/contentviewers/Bundle.properties | 2 + .../autopsy/contentviewers/ContentViewer.java | 50 ++++ .../contentviewers/JPEGViewerDummy.form | 58 ++++ .../contentviewers/JPEGViewerDummy.java | 89 +++++++ .../modules/filetypeid/FileTypeDetector.java | 34 ++- 7 files changed, 522 insertions(+), 3 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.form create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/ContentViewer.java create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.form create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.form new file mode 100644 index 0000000000..d07831cafe --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.form @@ -0,0 +1,41 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java new file mode 100644 index 0000000000..30141c3f4c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java @@ -0,0 +1,251 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 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.contentviewers; + +import com.google.common.base.Strings; +import java.awt.Component; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Generic Application content viewer + */ +@ServiceProvider(service = DataContentViewer.class, position = 5) +public class ApplicationContentViewer extends javax.swing.JPanel implements DataContentViewer { + + private static final int CONFIDENCE_LEVEL = 7; + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(ApplicationContentViewer.class.getName()); + + private final Map mimeTypeToViewerMap = new HashMap<>(); + + // TBD: This hardcoded list of viewers should be replaced with a dynamic lookup + private static final ContentViewer[] KNOWN_VIEWERS = new ContentViewer[]{ + new JPEGViewerDummy() // this if for testing only + }; + + private ContentViewer lastViewer; + + /** + * Creates new form ApplicationContentViewer + */ + public ApplicationContentViewer() { + + // init the mimetype to viewer map + for (ContentViewer cv : KNOWN_VIEWERS) { + cv.getSupportedMIMETypes().forEach((mimeType) -> { + if (mimeTypeToViewerMap.containsKey(mimeType) == false) { + mimeTypeToViewerMap.put(mimeType, cv); + } else { + LOGGER.log(Level.WARNING, "Duplicate viewer for mimtype: {0}", mimeType); //NON-NLS + } + }); + } + + initComponents(); + + LOGGER.log(Level.INFO, "Created ApplicationContentViewer instance: {0}", this); //NON-NLS + } + + /** + * Get the ContentViewer for a given mimetype + * + * @param mimeType + * + * @return ContentViewer, null if no known content viewer supports the + * mimetype + */ + private ContentViewer getSupportingViewer(String mimeType) { + return mimeTypeToViewerMap.containsKey(mimeType) ? mimeTypeToViewerMap.get(mimeType) : null; + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + setLayout(new javax.swing.OverlayLayout(this)); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + + @Override + public void setNode(Node selectedNode) { + if (selectedNode == null) { + return; + } + + AbstractFile file = selectedNode.getLookup().lookup(AbstractFile.class); + if (file == null) { + return; + } + + String mimeType = file.getMIMEType(); + if (Strings.isNullOrEmpty(mimeType)) { + LOGGER.log(Level.INFO, "Mimetype not known for file: {0}", file.getName()); //NON-NLS + try { + FileTypeDetector fileTypeDetector = new FileTypeDetector(); + mimeType = fileTypeDetector.detectFileType(file); + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + LOGGER.log(Level.SEVERE, "Failed to initialize FileTypeDetector.", ex); //NON-NLS + return; + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, String.format("Could not detect format using fileTypeDetector for file: %s", file), ex); //NON-NLS + return; + } + } + + if (mimeType.equalsIgnoreCase("application/octet-stream")) { + return; + } + else { + ContentViewer viewer = getSupportingViewer(mimeType); + if (viewer != null) { + lastViewer = viewer; + + viewer.setFile(file); + this.removeAll(); + this.add(viewer.getComponent()); + this.repaint(); + } + } + + } + + @Override + @NbBundle.Messages("ApplicationContentViewer.title=Application Content Viewer") + public String getTitle() { + return Bundle.ApplicationContentViewer_title(); + } + + @Override + @NbBundle.Messages("ApplicationContentViewer.toolTip=Displays file contents.") + public String getToolTip() { + return Bundle.ApplicationContentViewer_toolTip(); + } + + @Override + public DataContentViewer createInstance() { + return new ApplicationContentViewer(); + } + + @Override + public Component getComponent() { + return this; + } + + @Override + public void resetComponent() { + + if (lastViewer != null) { + lastViewer.resetComponent(); + } + this.removeAll(); + lastViewer = null; + } + + @Override + public boolean isSupported(Node node) { + + if (node == null) { + return false; + } + + AbstractFile aFile = node.getLookup().lookup(AbstractFile.class); + if (aFile == null) { + return false; + } + + String mimeType = aFile.getMIMEType(); + if (Strings.isNullOrEmpty(mimeType)) { + LOGGER.log(Level.INFO, "Mimetype not known for file: {0}", aFile.getName()); //NON-NLS + try { + FileTypeDetector fileTypeDetector = new FileTypeDetector(); + mimeType = fileTypeDetector.detectFileType(aFile); + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + LOGGER.log(Level.SEVERE, "Failed to initialize FileTypeDetector.", ex); //NON-NLS + return false; + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, String.format("Could not detect format using fileTypeDetector for file: %s", aFile), ex); //NON-NLS + return false; + } + } + + if (mimeType.equalsIgnoreCase("application/octet-stream")) { + return false; + } else { + return (getSupportingViewer(mimeType) != null); + } + + } + + @Override + public int isPreferred(Node node) { + if (node == null) { + return 0; + } + + AbstractFile file = node.getLookup().lookup(AbstractFile.class); + if (file == null) { + return 0; + } + + String mimeType = file.getMIMEType(); + if (Strings.isNullOrEmpty(mimeType)) { + LOGGER.log(Level.INFO, "Mimetype not known for file: {0}", file.getName()); //NON-NLS + try { + FileTypeDetector fileTypeDetector = new FileTypeDetector(); + mimeType = fileTypeDetector.detectFileType(file); + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + LOGGER.log(Level.SEVERE, "Failed to initialize FileTypeDetector.", ex); //NON-NLS + return 0; + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, String.format("Could not detect format using fileTypeDetector for file: %s", file), ex); //NON-NLS + return 0; + } + } + + if (mimeType.equalsIgnoreCase("application/octet-stream")) { + return 0; + } else { + if (null != getSupportingViewer(mimeType)) { + return CONFIDENCE_LEVEL; + } + } + + return 0; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties index 45916b87b3..cf082b2bab 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties @@ -33,3 +33,5 @@ MessageContentViewer.directionText.text=direction MessageContentViewer.ccLabel.text=CC: MessageContentViewer.attachmentsPanel.TabConstraints.tabTitle=Attachments MessageContentViewer.viewInNewWindowButton.text=View in New Window +JPEGViewerDummy.jLabel1.text=You are looking at a JPEG file: +JPEGViewerDummy.jTextField1.text=jTextField1 diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContentViewer.java new file mode 100644 index 0000000000..98dbbd0b08 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContentViewer.java @@ -0,0 +1,50 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 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.contentviewers; + +import java.awt.Component; +import java.util.List; +import org.sleuthkit.datamodel.AbstractFile; + +/** + * Defines an interface for application specific content viewer + * + */ +interface ContentViewer { + + /** + * Returns list of MIME types supported by this viewer + */ + List getSupportedMIMETypes(); + + /** + * Display the given file's content in the view panel + */ + void setFile(AbstractFile file); + + /** + * Returns panel + */ + Component getComponent(); + + /** + * Clears the data in the panel + */ + void resetComponent(); +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.form b/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.form new file mode 100644 index 0000000000..587dd3c9a0 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.form @@ -0,0 +1,58 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java b/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java new file mode 100644 index 0000000000..cae2db12a0 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java @@ -0,0 +1,89 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.contentviewers; + +import java.awt.Component; +import java.util.Arrays; +import java.util.List; +import org.sleuthkit.datamodel.AbstractFile; + +public class JPEGViewerDummy extends javax.swing.JPanel implements ContentViewer { + + public static final String[] SUPPORTED_MIMETYPES = new String[]{"image/jpeg"}; + + /** + * Creates new form JPEGViewer + */ + public JPEGViewerDummy() { + initComponents(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(JPEGViewerDummy.class, "JPEGViewerDummy.jLabel1.text")); // NOI18N + + jTextField1.setEditable(false); + jTextField1.setText(org.openide.util.NbBundle.getMessage(JPEGViewerDummy.class, "JPEGViewerDummy.jTextField1.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(43, 43, 43) + .addComponent(jLabel1) + .addGap(35, 35, 35) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(120, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(269, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + @Override + public List getSupportedMIMETypes() { + return Arrays.asList(SUPPORTED_MIMETYPES); + } + + @Override + public Component getComponent() { + return this; + } + + @Override + public void resetComponent() { + this.jTextField1.setText(""); + } + + @Override + public void setFile(AbstractFile file) { + this.jTextField1.setText(file.getName()); + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JTextField jTextField1; + // End of variables declaration//GEN-END:variables + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index 5851b9887c..baa6a1135b 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.filetypeid; +import com.google.common.base.Strings; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -205,9 +206,18 @@ public class FileTypeDetector { * * @throws TskCoreException If there is a problem writing the result to the * case database. + * + */ - public String detect(AbstractFile file) throws TskCoreException { - return detect(file, false); + public String detectFileType(AbstractFile file) throws TskCoreException { + String mimeType = file.getMIMEType(); + if (Strings.isNullOrEmpty(mimeType) == false) { + return mimeType; + } + else { + return detect(file, false); + } + } /** @@ -477,4 +487,22 @@ public class FileTypeDetector { return getFileType(file); } + /** + * Detects the MIME type of a file. The result is not added to the case + * database. + * + * @param file The file to test. + * + * @return A MIME type name. If file type could not be detected or results + * were uncertain, octet-stream is returned. + * + * @throws TskCoreException If there is a problem writing the result to the + * case database. + * + * @deprecated - use detectFileType to detect + */ + @Deprecated + public String detect(AbstractFile file) throws TskCoreException { + return detect(file, true); + } } From 7ff02fa62a1af599cd11b1a1435abb986d9f7f74 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 8 Jan 2018 13:47:24 -0500 Subject: [PATCH 02/52] Added menu item to create live triage drive --- .../autopsy/livetriage/Bundle.properties | 11 + .../CreateLiveTriageDriveAction.java | 265 +++++++++++ .../autopsy/livetriage/SelectDriveDialog.form | 180 ++++++++ .../autopsy/livetriage/SelectDriveDialog.java | 423 ++++++++++++++++++ 4 files changed, 879 insertions(+) create mode 100644 Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties create mode 100644 Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java create mode 100644 Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form create mode 100644 Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties b/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties new file mode 100644 index 0000000000..49fdf032cb --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties @@ -0,0 +1,11 @@ +SelectDriveDialog.bnOk.text=Ok +SelectDriveDialog.bnRefresh.text=Refresh +SelectDriveDialog.lbSelectDrive.text=Select the drive to copy the application and script to: +SelectDriveDialog.jLabel1.text=Select drive to use for live triage (may take time to load): +SelectDriveDialog.errorLabel.text=jLabel2 +SelectDriveDialog.jLabel2.text=This feature copies the application and a batch file to a removable drive, +SelectDriveDialog.jLabel3.text=allowing systems to be analyzed without installing the software or imaging +SelectDriveDialog.jLabel4.text=the drives. +SelectDriveDialog.jLabel5.text=To analyze a system, insert the drive and run "RunFromUSB.bat" as +SelectDriveDialog.jLabel6.text=administrator. +SelectDriveDialog.bnCancel.text=Cancel diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java new file mode 100644 index 0000000000..531e978618 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java @@ -0,0 +1,265 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 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.livetriage; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.InvalidPathException; +import java.util.logging.Level; +import javax.swing.JOptionPane; +import java.awt.Frame; +import javax.swing.SwingWorker; +import org.apache.commons.io.FileUtils; +import org.netbeans.api.progress.ProgressHandle; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CallableSystemAction; +import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; + +@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.livetriage.CreateLiveTriageDriveAction") +@ActionReference(path = "Menu/Tools", position = 1401) +@ActionRegistration(displayName = "#CTL_CreateLiveTriageDriveAction", lazy = false) +@NbBundle.Messages({"CTL_CreateLiveTriageDriveAction=Make Live Triage Drive"}) +public final class CreateLiveTriageDriveAction extends CallableSystemAction { + + private static final String DISPLAY_NAME = Bundle.CTL_CreateLiveTriageDriveAction(); + + @Override + public boolean isEnabled() { + return true; + } + + @NbBundle.Messages({"CreateLiveTriageDriveAction.error.title=Error creating live triage disk", + "CreateLiveTriageDriveAction.exenotfound.message=Executable could not be found", + "CreateLiveTriageDriveAction.batchFileError.message=Error creating batch file", + "CreateLiveTriageDriveAction.appPathError.message=Could not location application directory", + "CreateLiveTriageDriveAction.copyError.message=Could not copy application", + "CreateLiveTriageDriveAction.success.title=Success", + "CreateLiveTriageDriveAction.success.message=Live triage drive created. Use RunFromUSB.bat to run the application" + }) + @Override + @SuppressWarnings("fallthrough") + public void performAction() { + + Frame mainWindow = WindowManager.getDefault().getMainWindow(); + + // If this is an installed version, there should be an 64.exe file in the bin folder + String appName = UserPreferences.getAppName(); + String exeName = appName + "64.exe"; + String installPath = PlatformUtil.getInstallPath(); + + Path exePath = Paths.get(installPath, "bin", exeName); + System.out.println("Exe expected at " + exePath); + + // TEMP for testing - allows this to run from Netbeans + exePath = Paths.get("C:\\Program Files\\Autopsy-4.5.0", "bin", exeName); + + if(! exePath.toFile().exists()) { + JOptionPane.showMessageDialog(mainWindow, + Bundle.CreateLiveTriageDriveAction_exenotfound_message(), + Bundle.CreateLiveTriageDriveAction_error_title(), + JOptionPane.ERROR_MESSAGE); + return; + } + + Path applicationBasePath; + try { + applicationBasePath = exePath.getParent().getParent(); + } catch (InvalidPathException ex){ + JOptionPane.showMessageDialog(mainWindow, + Bundle.CreateLiveTriageDriveAction_appPathError_message(), + Bundle.CreateLiveTriageDriveAction_error_title(), + JOptionPane.ERROR_MESSAGE); + return; + } + + SelectDriveDialog driveDialog = new SelectDriveDialog(mainWindow, true); + driveDialog.display(); + + if(! driveDialog.getSelectedDrive().isEmpty()) { + String drivePath = driveDialog.getSelectedDrive(); + if(drivePath.startsWith("\\\\.\\")){ + drivePath = drivePath.substring(4); + } + System.out.println("Destination path: " + drivePath); + + CopyFilesWorker worker = new CopyFilesWorker(applicationBasePath, drivePath, appName); + worker.execute(); + } + + } + + private class CopyFilesWorker extends SwingWorker { + + private final Path sourceFolder; + private final String drivePath; + private final String appName; + private ProgressHandle progressHandle = null; + + CopyFilesWorker(Path sourceFolder, String drivePath, String appName){ + this.sourceFolder = sourceFolder; + this.drivePath = drivePath; + this.appName = appName; + } + + @NbBundle.Messages({"# {0} - drivePath", + "CopyFilesWorker.progressBar.text=Live Triage: Copying files to {0}"}) + @Override + protected Void doInBackground() throws Exception { + // Setup progress bar. + String displayName = NbBundle.getMessage(this.getClass(), + "CopyFilesWorker.progressBar.text", + drivePath); + + // There's no way to stop FileUtils.copyDirectory, so don't include cancellation + progressHandle = ProgressHandle.createHandle(displayName); + progressHandle.start(); + progressHandle.switchToIndeterminate(); + + copyBatchFile(drivePath, appName); + copyApplication(sourceFolder, drivePath, appName); + + return null; + } + + @NbBundle.Messages({"CopyFilesWorker.title=Create Live Triage Drive", + "CopyFilesWorker.error.text=Error copying live triage files", + "CopyFilesWorker.done.text=Finished creating live triage disk"}) + @Override + protected void done() { + try { + super.get(); + + MessageNotifyUtil.Notify.info(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.title"), + NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.done.text")); + + } catch (Exception ex) { + Logger.getLogger(CreateLiveTriageDriveAction.class.getName()).log(Level.SEVERE, "Fatal error during live triage drive creation", ex); //NON-NLS + MessageNotifyUtil.Notify.info(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.title"), + NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.error.text")); + } finally { + if(progressHandle != null){ + progressHandle.finish(); + } + } + } + } + + private void copyApplication(Path sourceFolder, String destBaseFolder, String appName) throws IOException { + + // Create an appName folder in the destination + Path destAppFolder = Paths.get(destBaseFolder, appName); + if(! destAppFolder.toFile().exists()) { + if(! destAppFolder.toFile().mkdirs()){ + throw new IOException("Failed to create directory " + destAppFolder.toString()); + } + } + + // Now copy the files + FileUtils.copyDirectory(sourceFolder.toFile(), destAppFolder.toFile()); + } + + private void copyBatchFile(String destPath, String appName) throws IOException, InvalidPathException { + Path batchFilePath = Paths.get(destPath, "RunFromUSB.bat"); + FileUtils.writeStringToFile(batchFilePath.toFile(), getBatchFileContents(appName), "UTF-8"); + + } + + private String getBatchFileContents(String appName){ + + String batchFile = + "@echo off\n" + + "SET appName=\"" + appName + "\"\n" + + "\n" + + "REM Create the configData directory. Exit if it does not exist after attempting to create it\n" + + "if not exist configData mkdir configData\n" + + "if not exist configData (\n" + + " echo Error creating directory configData\n" + + " goto end\n" + + ")\n" + + "\n" + + "REM Create the userdir sub directory. Exit if it does not exist after attempting to create it\n" + + "if not exist configData\\userdir mkdir configData\\userdir\n" + + "if not exist configData\\userdir (\n" + + " echo Error creating directory configData\\userdir\n" + + " goto end\n" + + ")\n" + + "\n" + + "REM Create the cachedir sub directory. Exit if it does not exist after attempting to create it\n" + + "REM If it exists to start with, delete it to clear out old data\n" + + "if exist configData\\cachedir rd /s /q configData\\cachedir\n" + + "mkdir configData\\cachedir\n" + + "if not exist configData\\cachedir (\n" + + " echo Error creating directory configData\\cachedir\n" + + " goto end\n" + + ")\n" + + "\n" + + "REM Create the temp sub directory. Exit if it does not exist after attempting to create it\n" + + "REM If it exists to start with, delete it to clear out old data\n" + + "if exist configData\\temp rd /s /q configData\\temp\n" + + "mkdir configData\\temp\n" + + "if not exist configData\\temp (\n" + + " echo Error creating directory configData\\temp\n" + + " goto end\n" + + ")\n" + + "\n" + + "REM Create the cases directory. It's ok if this fails.\n" + + "if not exist cases mkdir cases\n" + + "\n" + + "if exist %appName% (\n" + + " if not exist %appName%\\bin\\%appName%64.exe (\n" + + " echo %appName%\\bin\\%appName%64.exe does not exist\n" + + " goto end\n" + + " )\n" + + " %appName%\\bin\\%appName%64.exe --userdir ..\\configData\\userdir --cachedir ..\\configData\\cachedir -J-Djava.io.tmpdir=..\\configData\\temp\n" + + ") else (\n" + + " echo Could not find %appName% directory\n" + + " goto end\n" + + ")\n" + + "\n" + + ":end\n" + + "\n" + + "REM Keep the cmd window open in case there was an error\n" + + "@pause\n"; + return batchFile; + } + + @Override + public String getName() { + return DISPLAY_NAME; + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public boolean asynchronous() { + return false; // run on edt + } +} diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form new file mode 100644 index 0000000000..87592836f0 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form @@ -0,0 +1,180 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java new file mode 100644 index 0000000000..d50d7aee2c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java @@ -0,0 +1,423 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.livetriage; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CancellationException; +import java.util.logging.Level; +import java.awt.Dimension; +import java.awt.Point; +import javax.swing.SwingWorker; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TableModelListener; +import javax.swing.table.TableModel; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.LocalDisk; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; + +/** + * + */ +class SelectDriveDialog extends javax.swing.JDialog { + + private List disks = new ArrayList<>(); + private final LocalDiskModel model = new LocalDiskModel(); + private final java.awt.Frame parent; + private String drivePath = ""; + + /** + * Creates new form SelectDriveDialog + */ + @NbBundle.Messages({"SelectDriveDialog.title=Create Live Triage Drive"}) + SelectDriveDialog(java.awt.Frame parent, boolean modal) { + super(parent, modal); + initComponents(); + this.parent = parent; + + model.loadDisks(); + bnOk.setEnabled(false); + diskTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + if (diskTable.getSelectedRow() >= 0 && diskTable.getSelectedRow() < disks.size()) { + bnOk.setEnabled(true); + } else { //The selection changed to nothing valid being selected, such as with ctrl+click + bnOk.setEnabled(false); + } + } + }); + } + + void display(){ + this.setTitle(Bundle.SelectDriveDialog_title()); + + final Dimension parentSize = parent.getSize(); + final Point parentLocationOnScreen = parent.getLocationOnScreen(); + final Dimension childSize = this.getSize(); + int x; + int y; + x = (parentSize.width - childSize.width) / 2; + y = (parentSize.height - childSize.height) / 2; + x += parentLocationOnScreen.x; + y += parentLocationOnScreen.y; + + setLocation(x, y); + setVisible(true); + } + + String getSelectedDrive(){ + return this.drivePath; + } + + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + diskTable = new javax.swing.JTable(); + jLabel1 = new javax.swing.JLabel(); + bnRefresh = new javax.swing.JButton(); + bnOk = new javax.swing.JButton(); + errorLabel = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + jSeparator1 = new javax.swing.JSeparator(); + jLabel5 = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); + bnCancel = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + diskTable.setModel(model); + jScrollPane1.setViewportView(diskTable); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.bnRefresh.text")); // NOI18N + bnRefresh.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bnRefreshActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(bnOk, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.bnOk.text")); // NOI18N + bnOk.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bnOkActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.errorLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel2.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel3.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel4.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel5.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel6.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(bnCancel, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.bnCancel.text")); // NOI18N + bnCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bnCancelActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jLabel6) + .addGroup(layout.createSequentialGroup() + .addComponent(bnRefresh, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(bnOk, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(bnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(jLabel4) + .addComponent(jSeparator1) + .addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, 368, Short.MAX_VALUE) + .addComponent(errorLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel2) + .addGap(1, 1, 1) + .addComponent(jLabel3) + .addGap(1, 1, 1) + .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jLabel5) + .addGap(1, 1, 1) + .addComponent(jLabel6) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(bnRefresh) + .addComponent(bnCancel) + .addComponent(bnOk)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(errorLabel) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + pack(); + }// //GEN-END:initComponents + + private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnRefreshActionPerformed + model.loadDisks(); + }//GEN-LAST:event_bnRefreshActionPerformed + + private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed + if (diskTable.getSelectedRow() >= 0 && diskTable.getSelectedRow() < disks.size()) { + LocalDisk selectedDisk = disks.get(diskTable.getSelectedRow()); + drivePath = selectedDisk.getPath(); + } else { + drivePath = ""; + } + dispose(); + }//GEN-LAST:event_bnOkActionPerformed + + private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed + dispose(); + }//GEN-LAST:event_bnCancelActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton bnCancel; + private javax.swing.JButton bnOk; + private javax.swing.JButton bnRefresh; + private javax.swing.JTable diskTable; + private javax.swing.JLabel errorLabel; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JSeparator jSeparator1; + // End of variables declaration//GEN-END:variables + + + /** + * Table model for displaying information from LocalDisk Objects in a table. + */ + @NbBundle.Messages({"SelectDriveDialog.localDiskModel.loading.msg=", + "SelectDriveDialog.localDiskModel.nodrives.msg=Executable could not be found", + "SelectDriveDialog.diskTable.column1.title=Disk Name", + "SelectDriveDialog.diskTable.column2.title=Disk Size", + "SelectDriveDialog.errLabel.disksNotDetected.text=Disks were not detected. On some systems it requires admin privileges", + "SelectDriveDialog.errLabel.disksNotDetected.toolTipText=Disks were not detected. On some systems it requires admin privileges", + "SelectDriveDialog.errLabel.drivesNotDetected.text=Local drives were not detected. Auto-detection not supported on this OS or admin privileges required", + "SelectDriveDialog.errLabel.drivesNotDetected.toolTipText=Local drives were not detected. Auto-detection not supported on this OS or admin privileges required", + "SelectDriveDialog.errLabel.someDisksNotDetected.text=Some disks were not detected. On some systems it requires admin privileges", + "SelectDriveDialog.errLabel.someDisksNotDetected.toolTipText=Some disks were not detected. On some systems it requires admin privileges" + + }) + private class LocalDiskModel implements TableModel { + + private LocalDiskThread worker = null; + private boolean ready = false; + private volatile boolean loadingDisks = false; + + //private String SELECT = "Select a local disk:"; + private final String LOADING = NbBundle.getMessage(this.getClass(), "SelectDriveDialog.localDiskModel.loading.msg"); + private final String NO_DRIVES = NbBundle.getMessage(this.getClass(), "SelectDriveDialog.localDiskModel.nodrives.msg"); + + private void loadDisks() { + + // if there is a worker already building the lists, then cancel it first. + if (loadingDisks && worker != null) { + worker.cancel(false); + } + + // Clear the lists + errorLabel.setText(""); + diskTable.setEnabled(false); + ready = false; + loadingDisks = true; + worker = new LocalDiskThread(); + worker.execute(); + } + + @Override + public int getRowCount() { + if (disks.isEmpty()) { + return 0; + } + return disks.size(); + } + + @Override + public int getColumnCount() { + return 2; + + } + + @Override + public String getColumnName(int columnIndex) { + switch (columnIndex) { + case 0: + return NbBundle.getMessage(this.getClass(), "SelectDriveDialog.diskTable.column1.title"); + case 1: + return NbBundle.getMessage(this.getClass(), "SelectDriveDialog.diskTable.column2.title"); + default: + return "Unnamed"; //NON-NLS + } + } + + @Override + public Class getColumnClass(int columnIndex) { + return String.class; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + if (ready) { + if (disks.isEmpty()) { + return NO_DRIVES; + } + switch (columnIndex) { + case 0: + return disks.get(rowIndex).getName(); + case 1: + return disks.get(rowIndex).getReadableSize(); + default: + return disks.get(rowIndex).getPath(); + } + } else { + return LOADING; + } + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + //setter does nothing they should not be able to modify table + } + + @Override + public void addTableModelListener(TableModelListener l) { + + } + + @Override + public void removeTableModelListener(TableModelListener l) { + + } + + /** + * Gets the lists of physical drives and partitions and combines them + * into a list of disks. + */ + class LocalDiskThread extends SwingWorker { + + private final Logger logger = Logger.getLogger(LocalDiskThread.class.getName()); + private List physicalDrives = new ArrayList<>(); + private List partitions = new ArrayList<>(); + + @Override + protected Object doInBackground() throws Exception { + // Populate the lists + //physicalDrives = new ArrayList<>(); + partitions = new ArrayList<>(); + //physicalDrives = PlatformUtil.getPhysicalDrives(); + partitions = PlatformUtil.getPartitions(); + return null; + } + + /** + * Display any error messages that might of occurred when getting + * the lists of physical drives or partitions. + */ + private void displayErrors() { + if (physicalDrives.isEmpty() && partitions.isEmpty()) { + if (PlatformUtil.isWindowsOS()) { + errorLabel.setText( + NbBundle.getMessage(this.getClass(), "SelectDriveDialog.errLabel.disksNotDetected.text")); + errorLabel.setToolTipText(NbBundle.getMessage(this.getClass(), + "SelectDriveDialog.errLabel.disksNotDetected.toolTipText")); + } else { + errorLabel.setText( + NbBundle.getMessage(this.getClass(), "SelectDriveDialog.errLabel.drivesNotDetected.text")); + errorLabel.setToolTipText(NbBundle.getMessage(this.getClass(), + "SelectDriveDialog.errLabel.drivesNotDetected.toolTipText")); + } + errorLabel.setVisible(true); + diskTable.setEnabled(false); + }/* else if (physicalDrives.isEmpty()) { + errorLabel.setText( + NbBundle.getMessage(this.getClass(), "SelectDriveDialog.errLabel.someDisksNotDetected.text")); + errorLabel.setToolTipText(NbBundle.getMessage(this.getClass(), + "SelectDriveDialog.errLabel.someDisksNotDetected.toolTipText")); + errorLabel.setVisible(true); + }*/ + } + + @Override + protected void done() { + try { + super.get(); //block and get all exceptions thrown while doInBackground() + } catch (CancellationException ex) { + logger.log(Level.INFO, "Loading local disks was canceled."); //NON-NLS + } catch (InterruptedException ex) { + logger.log(Level.INFO, "Loading local disks was interrupted."); //NON-NLS + } catch (Exception ex) { + logger.log(Level.SEVERE, "Fatal error when loading local disks", ex); //NON-NLS + } finally { + if (!this.isCancelled()) { + displayErrors(); + worker = null; + loadingDisks = false; + disks = new ArrayList<>(); + //disks.addAll(physicalDrives); + disks.addAll(partitions); + if (disks.size() > 0) { + diskTable.setEnabled(true); + diskTable.clearSelection(); + } + ready = true; + } + } + diskTable.revalidate(); + } + } + } +} From a055757c64dd0d2eb59474b068fdd658daf806d2 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 8 Jan 2018 13:48:35 -0500 Subject: [PATCH 03/52] Formatting --- .../CreateLiveTriageDriveAction.java | 218 +++++++++--------- .../autopsy/livetriage/SelectDriveDialog.java | 18 +- 2 files changed, 117 insertions(+), 119 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java index 531e978618..a90993bb73 100644 --- a/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java +++ b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java @@ -45,14 +45,14 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil; @ActionRegistration(displayName = "#CTL_CreateLiveTriageDriveAction", lazy = false) @NbBundle.Messages({"CTL_CreateLiveTriageDriveAction=Make Live Triage Drive"}) public final class CreateLiveTriageDriveAction extends CallableSystemAction { - + private static final String DISPLAY_NAME = Bundle.CTL_CreateLiveTriageDriveAction(); - + @Override public boolean isEnabled() { return true; } - + @NbBundle.Messages({"CreateLiveTriageDriveAction.error.title=Error creating live triage disk", "CreateLiveTriageDriveAction.exenotfound.message=Executable could not be found", "CreateLiveTriageDriveAction.batchFileError.message=Error creating batch file", @@ -64,45 +64,45 @@ public final class CreateLiveTriageDriveAction extends CallableSystemAction { @Override @SuppressWarnings("fallthrough") public void performAction() { - + Frame mainWindow = WindowManager.getDefault().getMainWindow(); - + // If this is an installed version, there should be an 64.exe file in the bin folder String appName = UserPreferences.getAppName(); String exeName = appName + "64.exe"; String installPath = PlatformUtil.getInstallPath(); - + Path exePath = Paths.get(installPath, "bin", exeName); System.out.println("Exe expected at " + exePath); - + // TEMP for testing - allows this to run from Netbeans exePath = Paths.get("C:\\Program Files\\Autopsy-4.5.0", "bin", exeName); - - if(! exePath.toFile().exists()) { + + if (!exePath.toFile().exists()) { JOptionPane.showMessageDialog(mainWindow, - Bundle.CreateLiveTriageDriveAction_exenotfound_message(), - Bundle.CreateLiveTriageDriveAction_error_title(), - JOptionPane.ERROR_MESSAGE); + Bundle.CreateLiveTriageDriveAction_exenotfound_message(), + Bundle.CreateLiveTriageDriveAction_error_title(), + JOptionPane.ERROR_MESSAGE); return; - } - + } + Path applicationBasePath; try { applicationBasePath = exePath.getParent().getParent(); - } catch (InvalidPathException ex){ + } catch (InvalidPathException ex) { JOptionPane.showMessageDialog(mainWindow, - Bundle.CreateLiveTriageDriveAction_appPathError_message(), - Bundle.CreateLiveTriageDriveAction_error_title(), - JOptionPane.ERROR_MESSAGE); + Bundle.CreateLiveTriageDriveAction_appPathError_message(), + Bundle.CreateLiveTriageDriveAction_error_title(), + JOptionPane.ERROR_MESSAGE); return; } - + SelectDriveDialog driveDialog = new SelectDriveDialog(mainWindow, true); driveDialog.display(); - - if(! driveDialog.getSelectedDrive().isEmpty()) { + + if (!driveDialog.getSelectedDrive().isEmpty()) { String drivePath = driveDialog.getSelectedDrive(); - if(drivePath.startsWith("\\\\.\\")){ + if (drivePath.startsWith("\\\\.\\")) { drivePath = drivePath.substring(4); } System.out.println("Destination path: " + drivePath); @@ -110,154 +110,154 @@ public final class CreateLiveTriageDriveAction extends CallableSystemAction { CopyFilesWorker worker = new CopyFilesWorker(applicationBasePath, drivePath, appName); worker.execute(); } - + } - + private class CopyFilesWorker extends SwingWorker { private final Path sourceFolder; private final String drivePath; private final String appName; private ProgressHandle progressHandle = null; - - CopyFilesWorker(Path sourceFolder, String drivePath, String appName){ + + CopyFilesWorker(Path sourceFolder, String drivePath, String appName) { this.sourceFolder = sourceFolder; this.drivePath = drivePath; this.appName = appName; } - + @NbBundle.Messages({"# {0} - drivePath", "CopyFilesWorker.progressBar.text=Live Triage: Copying files to {0}"}) @Override protected Void doInBackground() throws Exception { // Setup progress bar. String displayName = NbBundle.getMessage(this.getClass(), - "CopyFilesWorker.progressBar.text", - drivePath); - + "CopyFilesWorker.progressBar.text", + drivePath); + // There's no way to stop FileUtils.copyDirectory, so don't include cancellation progressHandle = ProgressHandle.createHandle(displayName); progressHandle.start(); progressHandle.switchToIndeterminate(); - + copyBatchFile(drivePath, appName); copyApplication(sourceFolder, drivePath, appName); - + return null; } - + @NbBundle.Messages({"CopyFilesWorker.title=Create Live Triage Drive", - "CopyFilesWorker.error.text=Error copying live triage files", - "CopyFilesWorker.done.text=Finished creating live triage disk"}) + "CopyFilesWorker.error.text=Error copying live triage files", + "CopyFilesWorker.done.text=Finished creating live triage disk"}) @Override protected void done() { try { super.get(); - + MessageNotifyUtil.Notify.info(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.title"), - NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.done.text")); - + NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.done.text")); + } catch (Exception ex) { Logger.getLogger(CreateLiveTriageDriveAction.class.getName()).log(Level.SEVERE, "Fatal error during live triage drive creation", ex); //NON-NLS MessageNotifyUtil.Notify.info(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.title"), - NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.error.text")); + NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.error.text")); } finally { - if(progressHandle != null){ + if (progressHandle != null) { progressHandle.finish(); } - } + } } } - + private void copyApplication(Path sourceFolder, String destBaseFolder, String appName) throws IOException { - + // Create an appName folder in the destination Path destAppFolder = Paths.get(destBaseFolder, appName); - if(! destAppFolder.toFile().exists()) { - if(! destAppFolder.toFile().mkdirs()){ + if (!destAppFolder.toFile().exists()) { + if (!destAppFolder.toFile().mkdirs()) { throw new IOException("Failed to create directory " + destAppFolder.toString()); } } - + // Now copy the files FileUtils.copyDirectory(sourceFolder.toFile(), destAppFolder.toFile()); } - + private void copyBatchFile(String destPath, String appName) throws IOException, InvalidPathException { Path batchFilePath = Paths.get(destPath, "RunFromUSB.bat"); FileUtils.writeStringToFile(batchFilePath.toFile(), getBatchFileContents(appName), "UTF-8"); - + } - - private String getBatchFileContents(String appName){ - - String batchFile = - "@echo off\n" + - "SET appName=\"" + appName + "\"\n" + - "\n" + - "REM Create the configData directory. Exit if it does not exist after attempting to create it\n" + - "if not exist configData mkdir configData\n" + - "if not exist configData (\n" + - " echo Error creating directory configData\n" + - " goto end\n" + - ")\n" + - "\n" + - "REM Create the userdir sub directory. Exit if it does not exist after attempting to create it\n" + - "if not exist configData\\userdir mkdir configData\\userdir\n" + - "if not exist configData\\userdir (\n" + - " echo Error creating directory configData\\userdir\n" + - " goto end\n" + - ")\n" + - "\n" + - "REM Create the cachedir sub directory. Exit if it does not exist after attempting to create it\n" + - "REM If it exists to start with, delete it to clear out old data\n" + - "if exist configData\\cachedir rd /s /q configData\\cachedir\n" + - "mkdir configData\\cachedir\n" + - "if not exist configData\\cachedir (\n" + - " echo Error creating directory configData\\cachedir\n" + - " goto end\n" + - ")\n" + - "\n" + - "REM Create the temp sub directory. Exit if it does not exist after attempting to create it\n" + - "REM If it exists to start with, delete it to clear out old data\n" + - "if exist configData\\temp rd /s /q configData\\temp\n" + - "mkdir configData\\temp\n" + - "if not exist configData\\temp (\n" + - " echo Error creating directory configData\\temp\n" + - " goto end\n" + - ")\n" + - "\n" + - "REM Create the cases directory. It's ok if this fails.\n" + - "if not exist cases mkdir cases\n" + - "\n" + - "if exist %appName% (\n" + - " if not exist %appName%\\bin\\%appName%64.exe (\n" + - " echo %appName%\\bin\\%appName%64.exe does not exist\n" + - " goto end\n" + - " )\n" + - " %appName%\\bin\\%appName%64.exe --userdir ..\\configData\\userdir --cachedir ..\\configData\\cachedir -J-Djava.io.tmpdir=..\\configData\\temp\n" + - ") else (\n" + - " echo Could not find %appName% directory\n" + - " goto end\n" + - ")\n" + - "\n" + - ":end\n" + - "\n" + - "REM Keep the cmd window open in case there was an error\n" + - "@pause\n"; - return batchFile; + + private String getBatchFileContents(String appName) { + + String batchFile + = "@echo off\n" + + "SET appName=\"" + appName + "\"\n" + + "\n" + + "REM Create the configData directory. Exit if it does not exist after attempting to create it\n" + + "if not exist configData mkdir configData\n" + + "if not exist configData (\n" + + " echo Error creating directory configData\n" + + " goto end\n" + + ")\n" + + "\n" + + "REM Create the userdir sub directory. Exit if it does not exist after attempting to create it\n" + + "if not exist configData\\userdir mkdir configData\\userdir\n" + + "if not exist configData\\userdir (\n" + + " echo Error creating directory configData\\userdir\n" + + " goto end\n" + + ")\n" + + "\n" + + "REM Create the cachedir sub directory. Exit if it does not exist after attempting to create it\n" + + "REM If it exists to start with, delete it to clear out old data\n" + + "if exist configData\\cachedir rd /s /q configData\\cachedir\n" + + "mkdir configData\\cachedir\n" + + "if not exist configData\\cachedir (\n" + + " echo Error creating directory configData\\cachedir\n" + + " goto end\n" + + ")\n" + + "\n" + + "REM Create the temp sub directory. Exit if it does not exist after attempting to create it\n" + + "REM If it exists to start with, delete it to clear out old data\n" + + "if exist configData\\temp rd /s /q configData\\temp\n" + + "mkdir configData\\temp\n" + + "if not exist configData\\temp (\n" + + " echo Error creating directory configData\\temp\n" + + " goto end\n" + + ")\n" + + "\n" + + "REM Create the cases directory. It's ok if this fails.\n" + + "if not exist cases mkdir cases\n" + + "\n" + + "if exist %appName% (\n" + + " if not exist %appName%\\bin\\%appName%64.exe (\n" + + " echo %appName%\\bin\\%appName%64.exe does not exist\n" + + " goto end\n" + + " )\n" + + " %appName%\\bin\\%appName%64.exe --userdir ..\\configData\\userdir --cachedir ..\\configData\\cachedir -J-Djava.io.tmpdir=..\\configData\\temp\n" + + ") else (\n" + + " echo Could not find %appName% directory\n" + + " goto end\n" + + ")\n" + + "\n" + + ":end\n" + + "\n" + + "REM Keep the cmd window open in case there was an error\n" + + "@pause\n"; + return batchFile; } - + @Override public String getName() { return DISPLAY_NAME; } - + @Override public HelpCtx getHelpCtx() { return HelpCtx.DEFAULT_HELP; } - + @Override public boolean asynchronous() { return false; // run on edt diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java index d50d7aee2c..1ca506d323 100644 --- a/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java +++ b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java @@ -30,7 +30,7 @@ class SelectDriveDialog extends javax.swing.JDialog { private final LocalDiskModel model = new LocalDiskModel(); private final java.awt.Frame parent; private String drivePath = ""; - + /** * Creates new form SelectDriveDialog */ @@ -39,7 +39,7 @@ class SelectDriveDialog extends javax.swing.JDialog { super(parent, modal); initComponents(); this.parent = parent; - + model.loadDisks(); bnOk.setEnabled(false); diskTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @@ -53,10 +53,10 @@ class SelectDriveDialog extends javax.swing.JDialog { } }); } - - void display(){ + + void display() { this.setTitle(Bundle.SelectDriveDialog_title()); - + final Dimension parentSize = parent.getSize(); final Point parentLocationOnScreen = parent.getLocationOnScreen(); final Dimension childSize = this.getSize(); @@ -70,12 +70,11 @@ class SelectDriveDialog extends javax.swing.JDialog { setLocation(x, y); setVisible(true); } - - String getSelectedDrive(){ + + String getSelectedDrive() { return this.drivePath; } - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -231,7 +230,6 @@ class SelectDriveDialog extends javax.swing.JDialog { private javax.swing.JSeparator jSeparator1; // End of variables declaration//GEN-END:variables - /** * Table model for displaying information from LocalDisk Objects in a table. */ @@ -245,7 +243,7 @@ class SelectDriveDialog extends javax.swing.JDialog { "SelectDriveDialog.errLabel.drivesNotDetected.toolTipText=Local drives were not detected. Auto-detection not supported on this OS or admin privileges required", "SelectDriveDialog.errLabel.someDisksNotDetected.text=Some disks were not detected. On some systems it requires admin privileges", "SelectDriveDialog.errLabel.someDisksNotDetected.toolTipText=Some disks were not detected. On some systems it requires admin privileges" - + }) private class LocalDiskModel implements TableModel { From 15e296145df3a8d6f30c51a721ff034fc03551c2 Mon Sep 17 00:00:00 2001 From: Raman Date: Tue, 9 Jan 2018 09:39:26 -0500 Subject: [PATCH 04/52] Address review comments --- .../contentviewers/ApplicationContentViewer.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java index 4c079baca3..bf7c13279a 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java @@ -83,7 +83,7 @@ public class ApplicationContentViewer extends javax.swing.JPanel implements Data * mimetype */ private ContentViewer getSupportingViewer(String mimeType) { - return mimeTypeToViewerMap.containsKey(mimeType) ? mimeTypeToViewerMap.get(mimeType) : null; + return mimeTypeToViewerMap.get(mimeType); } /** @@ -104,6 +104,9 @@ public class ApplicationContentViewer extends javax.swing.JPanel implements Data @Override public void setNode(Node selectedNode) { + + resetComponent(); + if (selectedNode == null) { return; } @@ -208,16 +211,9 @@ public class ApplicationContentViewer extends javax.swing.JPanel implements Data @Override public int isPreferred(Node node) { - if (node == null) { - return 0; - } - AbstractFile file = node.getLookup().lookup(AbstractFile.class); - if (file == null) { - return 0; - } - String mimeType = file.getMIMEType(); + if (Strings.isNullOrEmpty(mimeType)) { LOGGER.log(Level.INFO, "Mimetype not known for file: {0}", file.getName()); //NON-NLS try { From 00e68c44aa6e14bb80d237068a98c0e7cd35246f Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 9 Jan 2018 09:44:27 -0500 Subject: [PATCH 05/52] Add fix to restore directory when running as admin --- .../autopsy/livetriage/CreateLiveTriageDriveAction.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java index a90993bb73..5f10b4f9df 100644 --- a/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java +++ b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java @@ -73,10 +73,6 @@ public final class CreateLiveTriageDriveAction extends CallableSystemAction { String installPath = PlatformUtil.getInstallPath(); Path exePath = Paths.get(installPath, "bin", exeName); - System.out.println("Exe expected at " + exePath); - - // TEMP for testing - allows this to run from Netbeans - exePath = Paths.get("C:\\Program Files\\Autopsy-4.5.0", "bin", exeName); if (!exePath.toFile().exists()) { JOptionPane.showMessageDialog(mainWindow, @@ -193,6 +189,11 @@ public final class CreateLiveTriageDriveAction extends CallableSystemAction { String batchFile = "@echo off\n" + + "\n" + + "REM This restores the working directory when using 'Run as administrator'" + + "@setlocal enableextensions\n" + + "@cd /d \"%~dp0\"" + + "\n" + "SET appName=\"" + appName + "\"\n" + "\n" + "REM Create the configData directory. Exit if it does not exist after attempting to create it\n" From 62e96ff4e06d61e6536434bc7d851db568de7e65 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Tue, 9 Jan 2018 17:11:45 -0500 Subject: [PATCH 06/52] 3449: Failed to generate report if couldn't create a report directory. --- .../autopsy/report/ReportGenerator.java | 44 +++++++------------ .../autopsy/report/ReportWizardAction.java | 21 ++++++--- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 0c8aa263c3..1bb05652d4 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -136,16 +136,9 @@ class ReportGenerator { /** * Run the GeneralReportModules using a SwingWorker. */ - void generateGeneralReport(GeneralReportModule generalReportModule) { + void generateGeneralReport(GeneralReportModule generalReportModule) throws IOException { if (generalReportModule != null) { - reportPathFormatString = String.format(reportPathFormatString, generalReportModule.getName()); - // Create the root reports directory. - try { - FileUtil.createFolder(new File(reportPathFormatString)); - } catch (IOException ex) { - errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedMakeRptFolder")); - logger.log(Level.SEVERE, "Failed to make report folder, may be unable to generate reports.", ex); //NON-NLS - } + reportPathFormatString = createReportDirectory(generalReportModule, reportPathFormatString); setupProgressPanel(generalReportModule); ReportWorker worker = new ReportWorker(() -> { generalReportModule.generateReport(reportPathFormatString, progressPanel); @@ -163,16 +156,9 @@ class ReportGenerator { * @param tagSelections the enabled/disabled state of the tag names * to be included in the report */ - void generateTableReport(TableReportModule tableReport, Map artifactTypeSelections, Map tagNameSelections) { + void generateTableReport(TableReportModule tableReport, Map artifactTypeSelections, Map tagNameSelections) throws IOException { if (tableReport != null && null != artifactTypeSelections) { - reportPathFormatString = String.format(reportPathFormatString, tableReport.getName()); - // Create the root reports directory. - try { - FileUtil.createFolder(new File(reportPathFormatString)); - } catch (IOException ex) { - errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedMakeRptFolder")); - logger.log(Level.SEVERE, "Failed to make report folder, may be unable to generate reports.", ex); //NON-NLS - } + reportPathFormatString = createReportDirectory(tableReport, reportPathFormatString); setupProgressPanel(tableReport); ReportWorker worker = new ReportWorker(() -> { tableReport.startReport(reportPathFormatString); @@ -194,16 +180,9 @@ class ReportGenerator { * @param enabledInfo the Information that should be included about each * file in the report. */ - void generateFileListReport(FileReportModule fileReportModule, Map enabledInfo) { + void generateFileListReport(FileReportModule fileReportModule, Map enabledInfo) throws IOException { if (fileReportModule != null && null != enabledInfo) { - reportPathFormatString = String.format(reportPathFormatString, fileReportModule.getName()); - // Create the root reports directory. - try { - FileUtil.createFolder(new File(reportPathFormatString)); - } catch (IOException ex) { - errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedMakeRptFolder")); - logger.log(Level.SEVERE, "Failed to make report folder, may be unable to generate reports.", ex); //NON-NLS - } + reportPathFormatString = createReportDirectory(fileReportModule, reportPathFormatString); List enabled = new ArrayList<>(); for (Entry e : enabledInfo.entrySet()) { if (e.getValue()) { @@ -285,6 +264,17 @@ class ReportGenerator { } } + private static String createReportDirectory(ReportModule module, String pathFormat) throws IOException { + String reportPath = String.format(pathFormat, module.getName()); + // Create the root reports directory. + try { + FileUtil.createFolder(new File(reportPath)); + } catch (IOException ex) { + throw new IOException("Failed to make report folder, unable to generate reports.", ex); + } + return reportPath; + } + private class ReportWorker extends SwingWorker { private final Runnable doInBackground; diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java b/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java index 49f37008be..618cba2a38 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2013-2015 Basis Technology Corp. + * Copyright 2013-2018 Basis Technology Corp. * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com @@ -26,12 +26,14 @@ import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; +import java.io.IOException; import java.text.MessageFormat; import java.util.EnumSet; import java.util.Map; import javax.swing.ImageIcon; import javax.swing.JButton; import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; import org.openide.WizardDescriptor; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; @@ -70,12 +72,17 @@ public final class ReportWizardAction extends CallableSystemAction implements Pr TableReportModule tableReport = (TableReportModule) wiz.getProperty("tableModule"); GeneralReportModule generalReport = (GeneralReportModule) wiz.getProperty("generalModule"); FileReportModule fileReport = (FileReportModule) wiz.getProperty("fileModule"); - if (tableReport != null) { - generator.generateTableReport(tableReport, (Map) wiz.getProperty("artifactStates"), (Map) wiz.getProperty("tagStates")); //NON-NLS - } else if (generalReport != null) { - generator.generateGeneralReport(generalReport); - } else if (fileReport != null) { - generator.generateFileListReport(fileReport, (Map) wiz.getProperty("fileReportOptions")); //NON-NLS + try { + if (tableReport != null) { + generator.generateTableReport(tableReport, (Map) wiz.getProperty("artifactStates"), (Map) wiz.getProperty("tagStates")); //NON-NLS + } else if (generalReport != null) { + generator.generateGeneralReport(generalReport); + } else if (fileReport != null) { + generator.generateFileListReport(fileReport, (Map) wiz.getProperty("fileReportOptions")); //NON-NLS + } + } catch (IOException e) { + NotifyDescriptor descriptor = new NotifyDescriptor.Message(e.getMessage(), NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(descriptor); } } } From 43d32eb1c809377eb1aa05f966d5ad47ebc5b432 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 10 Jan 2018 09:31:24 -0500 Subject: [PATCH 07/52] Changed progress bar --- .../autopsy/livetriage/Bundle.properties | 6 +- .../CreateLiveTriageDriveAction.java | 86 ++++++++++------- .../autopsy/livetriage/SelectDriveDialog.form | 93 ++++++++----------- .../autopsy/livetriage/SelectDriveDialog.java | 79 +++++----------- 4 files changed, 114 insertions(+), 150 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties b/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties index 49fdf032cb..61f522a6b4 100644 --- a/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties @@ -3,9 +3,5 @@ SelectDriveDialog.bnRefresh.text=Refresh SelectDriveDialog.lbSelectDrive.text=Select the drive to copy the application and script to: SelectDriveDialog.jLabel1.text=Select drive to use for live triage (may take time to load): SelectDriveDialog.errorLabel.text=jLabel2 -SelectDriveDialog.jLabel2.text=This feature copies the application and a batch file to a removable drive, -SelectDriveDialog.jLabel3.text=allowing systems to be analyzed without installing the software or imaging -SelectDriveDialog.jLabel4.text=the drives. -SelectDriveDialog.jLabel5.text=To analyze a system, insert the drive and run "RunFromUSB.bat" as -SelectDriveDialog.jLabel6.text=administrator. SelectDriveDialog.bnCancel.text=Cancel +SelectDriveDialog.jTextArea1.text=This feature copies the application and a batch file to a removable drive,\nallowing systems to be analyzed without installing the software or\nimaging the drives.\n\nTo analyze a system, insert the drive and run "RunFromUSB.bat" as\nadministrator, then select the "Local Disk" option on the Add Data Source\npanel. diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java index 5f10b4f9df..1c54ee633b 100644 --- a/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java +++ b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java @@ -23,11 +23,12 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.InvalidPathException; import java.util.logging.Level; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeEvent; import javax.swing.JOptionPane; import java.awt.Frame; import javax.swing.SwingWorker; import org.apache.commons.io.FileUtils; -import org.netbeans.api.progress.ProgressHandle; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionRegistration; @@ -39,14 +40,18 @@ import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator; @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.livetriage.CreateLiveTriageDriveAction") @ActionReference(path = "Menu/Tools", position = 1401) @ActionRegistration(displayName = "#CTL_CreateLiveTriageDriveAction", lazy = false) @NbBundle.Messages({"CTL_CreateLiveTriageDriveAction=Make Live Triage Drive"}) -public final class CreateLiveTriageDriveAction extends CallableSystemAction { +public final class CreateLiveTriageDriveAction extends CallableSystemAction implements PropertyChangeListener { private static final String DISPLAY_NAME = Bundle.CTL_CreateLiveTriageDriveAction(); + private ModalDialogProgressIndicator progressIndicator = null; + private String drivePath = ""; + private CopyFilesWorker worker; @Override public boolean isEnabled() { @@ -57,7 +62,7 @@ public final class CreateLiveTriageDriveAction extends CallableSystemAction { "CreateLiveTriageDriveAction.exenotfound.message=Executable could not be found", "CreateLiveTriageDriveAction.batchFileError.message=Error creating batch file", "CreateLiveTriageDriveAction.appPathError.message=Could not location application directory", - "CreateLiveTriageDriveAction.copyError.message=Could not copy application", + "CreateLiveTriageDriveAction.copyError.message=Could not copy application. Only works on installed version.", "CreateLiveTriageDriveAction.success.title=Success", "CreateLiveTriageDriveAction.success.message=Live triage drive created. Use RunFromUSB.bat to run the application" }) @@ -97,16 +102,46 @@ public final class CreateLiveTriageDriveAction extends CallableSystemAction { driveDialog.display(); if (!driveDialog.getSelectedDrive().isEmpty()) { - String drivePath = driveDialog.getSelectedDrive(); + drivePath = driveDialog.getSelectedDrive(); if (drivePath.startsWith("\\\\.\\")) { drivePath = drivePath.substring(4); } - System.out.println("Destination path: " + drivePath); - - CopyFilesWorker worker = new CopyFilesWorker(applicationBasePath, drivePath, appName); + + worker = new CopyFilesWorker(applicationBasePath, drivePath, appName); + worker.addPropertyChangeListener(this); worker.execute(); } - + } + + @NbBundle.Messages({"# {0} - drivePath", + "CreateLiveTriageDriveAction.progressBar.text=Copying live triage files to {0}", + "CreateLiveTriageDriveAction.progressBar.title=Please wait"}) + @Override + public void propertyChange(PropertyChangeEvent evt) { + + if ("state".equals(evt.getPropertyName()) + && (SwingWorker.StateValue.STARTED.equals(evt.getNewValue()))) { + + // Setup progress bar. + String displayStr = NbBundle.getMessage(this.getClass(), "CreateLiveTriageDriveAction.progressBar.text", + drivePath); + + progressIndicator = new ModalDialogProgressIndicator(WindowManager.getDefault().getMainWindow(), + NbBundle.getMessage(this.getClass(), "CreateLiveTriageDriveAction.progressBar.title")); + progressIndicator.start(displayStr); + + } else if ("state".equals(evt.getPropertyName()) + && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) { + if(progressIndicator != null){ + progressIndicator.finish(); + } + + if(worker.hadError()){ + MessageNotifyUtil.Message.error(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.error.text")); + } else { + MessageNotifyUtil.Message.info(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.done.text")); + } + } } private class CopyFilesWorker extends SwingWorker { @@ -114,27 +149,20 @@ public final class CreateLiveTriageDriveAction extends CallableSystemAction { private final Path sourceFolder; private final String drivePath; private final String appName; - private ProgressHandle progressHandle = null; + private boolean error = false; CopyFilesWorker(Path sourceFolder, String drivePath, String appName) { this.sourceFolder = sourceFolder; this.drivePath = drivePath; this.appName = appName; } - - @NbBundle.Messages({"# {0} - drivePath", - "CopyFilesWorker.progressBar.text=Live Triage: Copying files to {0}"}) + + boolean hadError(){ + return error; + } + @Override protected Void doInBackground() throws Exception { - // Setup progress bar. - String displayName = NbBundle.getMessage(this.getClass(), - "CopyFilesWorker.progressBar.text", - drivePath); - - // There's no way to stop FileUtils.copyDirectory, so don't include cancellation - progressHandle = ProgressHandle.createHandle(displayName); - progressHandle.start(); - progressHandle.switchToIndeterminate(); copyBatchFile(drivePath, appName); copyApplication(sourceFolder, drivePath, appName); @@ -142,25 +170,15 @@ public final class CreateLiveTriageDriveAction extends CallableSystemAction { return null; } - @NbBundle.Messages({"CopyFilesWorker.title=Create Live Triage Drive", - "CopyFilesWorker.error.text=Error copying live triage files", + @NbBundle.Messages({"CopyFilesWorker.error.text=Error copying live triage files", "CopyFilesWorker.done.text=Finished creating live triage disk"}) @Override protected void done() { try { super.get(); - - MessageNotifyUtil.Notify.info(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.title"), - NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.done.text")); - } catch (Exception ex) { - Logger.getLogger(CreateLiveTriageDriveAction.class.getName()).log(Level.SEVERE, "Fatal error during live triage drive creation", ex); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.title"), - NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.error.text")); - } finally { - if (progressHandle != null) { - progressHandle.finish(); - } + error = true; + Logger.getLogger(CreateLiveTriageDriveAction.class.getName()).log(Level.SEVERE, "Fatal error during live triage drive creation", ex); //NON-NLS } } } diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form index 87592836f0..ee776348dc 100644 --- a/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form +++ b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form @@ -23,27 +23,21 @@ - + - - - + + - - - - - - + @@ -53,16 +47,8 @@ - - - - - - - - - - + + @@ -129,43 +115,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -176,5 +127,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java index 1ca506d323..c13d82d324 100644 --- a/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java +++ b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java @@ -90,13 +90,10 @@ class SelectDriveDialog extends javax.swing.JDialog { bnRefresh = new javax.swing.JButton(); bnOk = new javax.swing.JButton(); errorLabel = new javax.swing.JLabel(); - jLabel2 = new javax.swing.JLabel(); - jLabel3 = new javax.swing.JLabel(); - jLabel4 = new javax.swing.JLabel(); jSeparator1 = new javax.swing.JSeparator(); - jLabel5 = new javax.swing.JLabel(); - jLabel6 = new javax.swing.JLabel(); bnCancel = new javax.swing.JButton(); + jScrollPane2 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -121,16 +118,6 @@ class SelectDriveDialog extends javax.swing.JDialog { org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.errorLabel.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel2.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel3.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel4.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel5.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel6.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(bnCancel, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.bnCancel.text")); // NOI18N bnCancel.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -138,6 +125,16 @@ class SelectDriveDialog extends javax.swing.JDialog { } }); + jScrollPane2.setBorder(null); + + jTextArea1.setBackground(new java.awt.Color(240, 240, 240)); + jTextArea1.setColumns(20); + jTextArea1.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N + jTextArea1.setRows(5); + jTextArea1.setText(org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jTextArea1.text")); // NOI18N + jTextArea1.setBorder(null); + jScrollPane2.setViewportView(jTextArea1); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -145,38 +142,25 @@ class SelectDriveDialog extends javax.swing.JDialog { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(jLabel6) .addGroup(layout.createSequentialGroup() - .addComponent(bnRefresh, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(bnRefresh, javax.swing.GroupLayout.DEFAULT_SIZE, 112, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 48, Short.MAX_VALUE) .addComponent(bnOk, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(bnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addComponent(jLabel4) .addComponent(jSeparator1) - .addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, 368, Short.MAX_VALUE) - .addComponent(errorLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(errorLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jScrollPane2)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(jLabel2) - .addGap(1, 1, 1) - .addComponent(jLabel3) - .addGap(1, 1, 1) - .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jLabel5) - .addGap(1, 1, 1) - .addComponent(jLabel6) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel1) @@ -221,13 +205,10 @@ class SelectDriveDialog extends javax.swing.JDialog { private javax.swing.JTable diskTable; private javax.swing.JLabel errorLabel; private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; - private javax.swing.JLabel jLabel3; - private javax.swing.JLabel jLabel4; - private javax.swing.JLabel jLabel5; - private javax.swing.JLabel jLabel6; private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; private javax.swing.JSeparator jSeparator1; + private javax.swing.JTextArea jTextArea1; // End of variables declaration//GEN-END:variables /** @@ -238,11 +219,7 @@ class SelectDriveDialog extends javax.swing.JDialog { "SelectDriveDialog.diskTable.column1.title=Disk Name", "SelectDriveDialog.diskTable.column2.title=Disk Size", "SelectDriveDialog.errLabel.disksNotDetected.text=Disks were not detected. On some systems it requires admin privileges", - "SelectDriveDialog.errLabel.disksNotDetected.toolTipText=Disks were not detected. On some systems it requires admin privileges", - "SelectDriveDialog.errLabel.drivesNotDetected.text=Local drives were not detected. Auto-detection not supported on this OS or admin privileges required", - "SelectDriveDialog.errLabel.drivesNotDetected.toolTipText=Local drives were not detected. Auto-detection not supported on this OS or admin privileges required", - "SelectDriveDialog.errLabel.someDisksNotDetected.text=Some disks were not detected. On some systems it requires admin privileges", - "SelectDriveDialog.errLabel.someDisksNotDetected.toolTipText=Some disks were not detected. On some systems it requires admin privileges" + "SelectDriveDialog.errLabel.disksNotDetected.toolTipText=Disks were not detected." }) private class LocalDiskModel implements TableModel { @@ -348,15 +325,12 @@ class SelectDriveDialog extends javax.swing.JDialog { class LocalDiskThread extends SwingWorker { private final Logger logger = Logger.getLogger(LocalDiskThread.class.getName()); - private List physicalDrives = new ArrayList<>(); private List partitions = new ArrayList<>(); @Override protected Object doInBackground() throws Exception { // Populate the lists - //physicalDrives = new ArrayList<>(); partitions = new ArrayList<>(); - //physicalDrives = PlatformUtil.getPhysicalDrives(); partitions = PlatformUtil.getPartitions(); return null; } @@ -366,7 +340,7 @@ class SelectDriveDialog extends javax.swing.JDialog { * the lists of physical drives or partitions. */ private void displayErrors() { - if (physicalDrives.isEmpty() && partitions.isEmpty()) { + if (partitions.isEmpty()) { if (PlatformUtil.isWindowsOS()) { errorLabel.setText( NbBundle.getMessage(this.getClass(), "SelectDriveDialog.errLabel.disksNotDetected.text")); @@ -380,13 +354,7 @@ class SelectDriveDialog extends javax.swing.JDialog { } errorLabel.setVisible(true); diskTable.setEnabled(false); - }/* else if (physicalDrives.isEmpty()) { - errorLabel.setText( - NbBundle.getMessage(this.getClass(), "SelectDriveDialog.errLabel.someDisksNotDetected.text")); - errorLabel.setToolTipText(NbBundle.getMessage(this.getClass(), - "SelectDriveDialog.errLabel.someDisksNotDetected.toolTipText")); - errorLabel.setVisible(true); - }*/ + } } @Override @@ -405,7 +373,6 @@ class SelectDriveDialog extends javax.swing.JDialog { worker = null; loadingDisks = false; disks = new ArrayList<>(); - //disks.addAll(physicalDrives); disks.addAll(partitions); if (disks.size() > 0) { diskTable.setEnabled(true); From 6c973af0b6e1e163b03b8d59275fee063763d6c6 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 10 Jan 2018 09:31:58 -0500 Subject: [PATCH 08/52] Formatting --- .../CreateLiveTriageDriveAction.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java index 1c54ee633b..846632a092 100644 --- a/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java +++ b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java @@ -106,40 +106,40 @@ public final class CreateLiveTriageDriveAction extends CallableSystemAction impl if (drivePath.startsWith("\\\\.\\")) { drivePath = drivePath.substring(4); } - + worker = new CopyFilesWorker(applicationBasePath, drivePath, appName); worker.addPropertyChangeListener(this); worker.execute(); } } - + @NbBundle.Messages({"# {0} - drivePath", - "CreateLiveTriageDriveAction.progressBar.text=Copying live triage files to {0}", - "CreateLiveTriageDriveAction.progressBar.title=Please wait"}) + "CreateLiveTriageDriveAction.progressBar.text=Copying live triage files to {0}", + "CreateLiveTriageDriveAction.progressBar.title=Please wait"}) @Override public void propertyChange(PropertyChangeEvent evt) { - + if ("state".equals(evt.getPropertyName()) - && (SwingWorker.StateValue.STARTED.equals(evt.getNewValue()))) { - + && (SwingWorker.StateValue.STARTED.equals(evt.getNewValue()))) { + // Setup progress bar. String displayStr = NbBundle.getMessage(this.getClass(), "CreateLiveTriageDriveAction.progressBar.text", drivePath); - + progressIndicator = new ModalDialogProgressIndicator(WindowManager.getDefault().getMainWindow(), NbBundle.getMessage(this.getClass(), "CreateLiveTriageDriveAction.progressBar.title")); progressIndicator.start(displayStr); - + } else if ("state".equals(evt.getPropertyName()) - && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) { - if(progressIndicator != null){ + && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) { + if (progressIndicator != null) { progressIndicator.finish(); } - - if(worker.hadError()){ + + if (worker.hadError()) { MessageNotifyUtil.Message.error(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.error.text")); } else { - MessageNotifyUtil.Message.info(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.done.text")); + MessageNotifyUtil.Message.info(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.done.text")); } } } @@ -156,11 +156,11 @@ public final class CreateLiveTriageDriveAction extends CallableSystemAction impl this.drivePath = drivePath; this.appName = appName; } - - boolean hadError(){ + + boolean hadError() { return error; } - + @Override protected Void doInBackground() throws Exception { From 30793eb51f962cd5a48e2d2535c8611e848b636f Mon Sep 17 00:00:00 2001 From: Raman Date: Thu, 11 Jan 2018 09:53:07 -0500 Subject: [PATCH 09/52] 3238: Add a SQLite content viewer: List tables - Also renamed the ContentViewer & ApplicationContentViewer based on review comments. --- .../autopsy/contentviewers/Bundle.properties | 2 + ...ContentViewer.java => FileTypeViewer.java} | 2 +- ...tionContentViewer.form => FileViewer.form} | 0 ...tionContentViewer.java => FileViewer.java} | 33 +- .../contentviewers/JPEGViewerDummy.java | 2 +- .../autopsy/contentviewers/SQLiteViewer.form | 153 +++++++ .../autopsy/contentviewers/SQLiteViewer.java | 389 ++++++++++++++++++ 7 files changed, 561 insertions(+), 20 deletions(-) rename Core/src/org/sleuthkit/autopsy/contentviewers/{ContentViewer.java => FileTypeViewer.java} (97%) rename Core/src/org/sleuthkit/autopsy/contentviewers/{ApplicationContentViewer.form => FileViewer.form} (100%) rename Core/src/org/sleuthkit/autopsy/contentviewers/{ApplicationContentViewer.java => FileViewer.java} (87%) create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties index cf082b2bab..8267587395 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties @@ -35,3 +35,5 @@ MessageContentViewer.attachmentsPanel.TabConstraints.tabTitle=Attachments MessageContentViewer.viewInNewWindowButton.text=View in New Window JPEGViewerDummy.jLabel1.text=You are looking at a JPEG file: JPEGViewerDummy.jTextField1.text=jTextField1 +SQLiteViewer.jLabel1.text=Table +SQLiteViewer.numEntriesField.text=num Entries diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/FileTypeViewer.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/contentviewers/ContentViewer.java rename to Core/src/org/sleuthkit/autopsy/contentviewers/FileTypeViewer.java index 98dbbd0b08..f4a677c4f4 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/FileTypeViewer.java @@ -26,7 +26,7 @@ import org.sleuthkit.datamodel.AbstractFile; * Defines an interface for application specific content viewer * */ -interface ContentViewer { +interface FileTypeViewer { /** * Returns list of MIME types supported by this viewer diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.form similarity index 100% rename from Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.form rename to Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.form diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java similarity index 87% rename from Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java rename to Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java index bf7c13279a..a58dea2d25 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ApplicationContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java @@ -24,42 +24,40 @@ import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import org.openide.nodes.Node; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; -import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.TskCoreException; /** * Generic Application content viewer */ @ServiceProvider(service = DataContentViewer.class, position = 5) -public class ApplicationContentViewer extends javax.swing.JPanel implements DataContentViewer { +public class FileViewer extends javax.swing.JPanel implements DataContentViewer { private static final int CONFIDENCE_LEVEL = 7; private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(ApplicationContentViewer.class.getName()); + private static final Logger LOGGER = Logger.getLogger(FileViewer.class.getName()); - private final Map mimeTypeToViewerMap = new HashMap<>(); + private final Map mimeTypeToViewerMap = new HashMap<>(); // TBD: This hardcoded list of viewers should be replaced with a dynamic lookup - private static final ContentViewer[] KNOWN_VIEWERS = new ContentViewer[]{ - new JPEGViewerDummy() // this if for testing only + private static final FileTypeViewer[] KNOWN_VIEWERS = new FileTypeViewer[]{ + new JPEGViewerDummy(), // this if for testing only + new SQLiteViewer() }; - private ContentViewer lastViewer; + private FileTypeViewer lastViewer; /** * Creates new form ApplicationContentViewer */ - public ApplicationContentViewer() { + public FileViewer() { // init the mimetype to viewer map - for (ContentViewer cv : KNOWN_VIEWERS) { + for (FileTypeViewer cv : KNOWN_VIEWERS) { cv.getSupportedMIMETypes().forEach((mimeType) -> { if (mimeTypeToViewerMap.containsKey(mimeType) == false) { mimeTypeToViewerMap.put(mimeType, cv); @@ -75,14 +73,13 @@ public class ApplicationContentViewer extends javax.swing.JPanel implements Data } /** - * Get the ContentViewer for a given mimetype + * Get the FileTypeViewer for a given mimetype * * @param mimeType * - * @return ContentViewer, null if no known content viewer supports the - * mimetype + * @return FileTypeViewer, null if no known content viewer supports the mimetype */ - private ContentViewer getSupportingViewer(String mimeType) { + private FileTypeViewer getSupportingViewer(String mimeType) { return mimeTypeToViewerMap.get(mimeType); } @@ -132,7 +129,7 @@ public class ApplicationContentViewer extends javax.swing.JPanel implements Data return; } else { - ContentViewer viewer = getSupportingViewer(mimeType); + FileTypeViewer viewer = getSupportingViewer(mimeType); if (viewer != null) { lastViewer = viewer; @@ -146,7 +143,7 @@ public class ApplicationContentViewer extends javax.swing.JPanel implements Data } @Override - @NbBundle.Messages("ApplicationContentViewer.title=Application Content Viewer") + @NbBundle.Messages("ApplicationContentViewer.title=Application") public String getTitle() { return Bundle.ApplicationContentViewer_title(); } @@ -159,7 +156,7 @@ public class ApplicationContentViewer extends javax.swing.JPanel implements Data @Override public DataContentViewer createInstance() { - return new ApplicationContentViewer(); + return new FileViewer(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java b/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java index cae2db12a0..8aea7540e1 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java @@ -10,7 +10,7 @@ import java.util.Arrays; import java.util.List; import org.sleuthkit.datamodel.AbstractFile; -public class JPEGViewerDummy extends javax.swing.JPanel implements ContentViewer { +public class JPEGViewerDummy extends javax.swing.JPanel implements FileTypeViewer { public static final String[] SUPPORTED_MIMETYPES = new String[]{"image/jpeg"}; diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form new file mode 100644 index 0000000000..3cdee8658c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form @@ -0,0 +1,153 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java new file mode 100644 index 0000000000..358277fd97 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java @@ -0,0 +1,389 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.contentviewers; + +import java.awt.Component; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; +import java.sql.SQLException; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ExecutionException; +import javax.swing.JComboBox; +import javax.swing.SwingWorker; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.AbstractFile; + + +public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { + + public static final String[] SUPPORTED_MIMETYPES = new String[]{"application/x-sqlite3"}; + private static final Logger LOGGER = Logger.getLogger(FileViewer.class.getName()); + private Connection connection = null; + + private String tmpDBPathName = null; + private File tmpDBFile = null; + + // TBD: Change the value to be a Array of ColDefs + Map dbTablesMap = new TreeMap<>(); + + /** + * Creates new form SQLiteViewer + */ + public SQLiteViewer() { + initComponents(); + + customizeComponents(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jHdrPanel = new javax.swing.JPanel(); + tablesDropdownList = new javax.swing.JComboBox<>(); + jLabel1 = new javax.swing.JLabel(); + numEntriesField = new javax.swing.JTextField(); + jTableDataPanel = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTable1 = new javax.swing.JTable(); + + tablesDropdownList.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); + tablesDropdownList.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + tablesDropdownListActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.jLabel1.text")); // NOI18N + + numEntriesField.setEditable(false); + numEntriesField.setText(org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.numEntriesField.text")); // NOI18N + numEntriesField.setBorder(null); + numEntriesField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + numEntriesFieldActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jHdrPanelLayout = new javax.swing.GroupLayout(jHdrPanel); + jHdrPanel.setLayout(jHdrPanelLayout); + jHdrPanelLayout.setHorizontalGroup( + jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jHdrPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(23, 23, 23) + .addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(130, Short.MAX_VALUE)) + ); + jHdrPanelLayout.setVerticalGroup( + jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jHdrPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel1) + .addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(16, Short.MAX_VALUE)) + ); + + jTable1.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + {null, null, null, null}, + {null, null, null, null}, + {null, null, null, null}, + {null, null, null, null} + }, + new String [] { + "Title 1", "Title 2", "Title 3", "Title 4" + } + )); + jScrollPane1.setViewportView(jTable1); + + javax.swing.GroupLayout jTableDataPanelLayout = new javax.swing.GroupLayout(jTableDataPanel); + jTableDataPanel.setLayout(jTableDataPanelLayout); + jTableDataPanelLayout.setHorizontalGroup( + jTableDataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jTableDataPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addGap(15, 15, 15)) + ); + jTableDataPanelLayout.setVerticalGroup( + jTableDataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jTableDataPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 275, Short.MAX_VALUE) + .addContainerGap()) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jHdrPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jTableDataPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jHdrPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jTableDataPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void numEntriesFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_numEntriesFieldActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_numEntriesFieldActionPerformed + + private void tablesDropdownListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tablesDropdownListActionPerformed + JComboBox cb = (JComboBox) evt.getSource(); + String tableName = (String) cb.getSelectedItem(); + if (null == tableName) { + return; + } + + readTable(tableName); + }//GEN-LAST:event_tablesDropdownListActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel jHdrPanel; + private javax.swing.JLabel jLabel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTable jTable1; + private javax.swing.JPanel jTableDataPanel; + private javax.swing.JTextField numEntriesField; + private javax.swing.JComboBox tablesDropdownList; + // End of variables declaration//GEN-END:variables + + @Override + public List getSupportedMIMETypes() { + return Arrays.asList(SUPPORTED_MIMETYPES); + } + + @Override + public void setFile(AbstractFile file) { + processSQLiteFile( file); + } + + @Override + public Component getComponent() { + return this; + } + + @Override + public void resetComponent() { + + dbTablesMap.clear(); + + tablesDropdownList.setEnabled(true); + tablesDropdownList.removeAllItems(); + numEntriesField.setText(""); + + // close DB connection to file + if (null != connection) { + try { + connection.close(); + connection = null; + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Failed to close DB connection to file.", ex); //NON-NLS + } + } + + // delete last temp file + if (null != tmpDBFile) { + tmpDBFile.delete(); + tmpDBFile = null; + } + } + + private void customizeComponents() { + + // add a actionListener to jTablesComboBox + } + + /** + * Process the given SQLite DB file + * + * @param sqliteFile - + * + * @return none + */ + private void processSQLiteFile(AbstractFile sqliteFile) { + + tablesDropdownList.removeAllItems(); + + new SwingWorker() { + @Override + protected Boolean doInBackground() throws Exception { + + try { + tmpDBPathName = Case.getCurrentCase().getTempDirectory() + File.separator + sqliteFile.getName() + "-" + sqliteFile.getId(); + tmpDBFile = new File(tmpDBPathName); + + // Copy the file to temp folder + ContentUtils.writeToFile(sqliteFile, tmpDBFile); + System.out.println("RAMAN: SQLite file copied to: " + tmpDBPathName); + + // Open copy using JDBC + Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + tmpDBPathName); //NON-NLS + + // Read all table names and schema + return getTables(); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Failed to copy DB file.", ex); //NON-NLS + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Failed to Open DB.", ex); //NON-NLS + } catch (ClassNotFoundException ex) { + LOGGER.log(Level.SEVERE, "Failed to initialize JDBC Sqlite.", ex); //NON-NLS + } + return false; + } + + @Override + protected void done() { + super.done(); + try { + boolean status = get(); + if ( (status == true) && (dbTablesMap.size() > 0) ) { + dbTablesMap.keySet().forEach((tableName) -> { + tablesDropdownList.addItem(tableName); + }); + } + else { + // Populate error message + tablesDropdownList.addItem("No tables found"); + tablesDropdownList.setEnabled(false); + } + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while opening DB file", ex); //NON-NLS + } + } + }.execute(); + + } + + /** + * Gets the table names and their schema from loaded SQLite db file + * + * @return true if success, false otherwise + */ + private boolean getTables() { + + try { + Statement statement = connection.createStatement(); + + ResultSet resultSet = statement.executeQuery( + "SELECT name, sql FROM sqlite_master " + + " WHERE type= 'table' " + + " ORDER BY name;"); //NON-NLS + + while (resultSet.next()) { + String tableName = resultSet.getString("name"); //NON-NLS + String tableSQL = resultSet.getString("sql"); //NON-NLS + + dbTablesMap.put(tableName, tableSQL); + String query = "PRAGMA table_info(" + tableName + ")"; //NON-NLS + ResultSet rs2; + try { + Statement statement2 = connection.createStatement(); + rs2 = statement2.executeQuery(query); + while (rs2.next()) { + + System.out.println("RAMAN: Col Name = " + rs2.getString("name") ); + System.out.println("RAMAN: Col Type = " + rs2.getString("type") ); + + // RAMAN TBD: parse and save the table schema + } + } catch (Exception ex) { + LOGGER.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS + } + } + } catch (Exception e) { + LOGGER.log(Level.SEVERE, "Error getting table names from the DB", e); //NON-NLS + } + return true; + } + + private void readTable(String tableName) { + + System.out.println("RAMAN: selected table = " + tableName); + + // TBD: need to handle cancelling if one is already in progress + new SwingWorker() { + @Override + protected Integer doInBackground() throws Exception { + + try { + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery( + "SELECT COUNT(*) as count FROM " + tableName ); //NON-NLS + + System.out.println("Row count = " + resultSet.getInt("count") ); + // Read all table names and schema + return resultSet.getInt("count"); + }catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Failed to Open DB.", ex); //NON-NLS + } + //NON-NLS + return 0; + } + + @Override + protected void done() { + super.done(); + try { + int numRows = get(); + numEntriesField.setText( numRows + " entries"); + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS + } + } + }.execute(); + + } + + enum SQLStorageClass { + NULL, + INTEGER, + REAL, + TEXT, + BLOB + }; + + private class SQLColDef { + + private final String colName; + private final SQLStorageClass storageClass; + + SQLColDef(String colName, SQLStorageClass sc ) { + this.colName = colName; + this.storageClass = sc; + } + + } +} From 1f44f08783cc7891ea5c692563371ccfc7efde03 Mon Sep 17 00:00:00 2001 From: Raman Date: Thu, 11 Jan 2018 10:17:33 -0500 Subject: [PATCH 10/52] Formatted file, & minor cleanup --- .../autopsy/contentviewers/FileViewer.java | 2 +- .../autopsy/contentviewers/SQLiteViewer.java | 164 +++++++++--------- 2 files changed, 86 insertions(+), 80 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java index a58dea2d25..0d17ce2cd6 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java @@ -45,7 +45,7 @@ public class FileViewer extends javax.swing.JPanel implements DataContentViewer // TBD: This hardcoded list of viewers should be replaced with a dynamic lookup private static final FileTypeViewer[] KNOWN_VIEWERS = new FileTypeViewer[]{ - new JPEGViewerDummy(), // this if for testing only + // new JPEGViewerDummy(), // this if for testing only new SQLiteViewer() }; diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java index 358277fd97..fff2f5d781 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java @@ -1,7 +1,20 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2018 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.contentviewers; @@ -22,30 +35,28 @@ import java.util.concurrent.ExecutionException; import javax.swing.JComboBox; import javax.swing.SwingWorker; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.datamodel.AbstractFile; - public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { public static final String[] SUPPORTED_MIMETYPES = new String[]{"application/x-sqlite3"}; private static final Logger LOGGER = Logger.getLogger(FileViewer.class.getName()); private Connection connection = null; - + private String tmpDBPathName = null; private File tmpDBFile = null; - + // TBD: Change the value to be a Array of ColDefs Map dbTablesMap = new TreeMap<>(); - + /** * Creates new form SQLiteViewer */ public SQLiteViewer() { initComponents(); - + customizeComponents(); } @@ -164,7 +175,7 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { if (null == tableName) { return; } - + readTable(tableName); }//GEN-LAST:event_tablesDropdownListActionPerformed @@ -181,12 +192,12 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { @Override public List getSupportedMIMETypes() { - return Arrays.asList(SUPPORTED_MIMETYPES); + return Arrays.asList(SUPPORTED_MIMETYPES); } @Override public void setFile(AbstractFile file) { - processSQLiteFile( file); + processSQLiteFile(file); } @Override @@ -196,13 +207,13 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { @Override public void resetComponent() { - + dbTablesMap.clear(); - + tablesDropdownList.setEnabled(true); tablesDropdownList.removeAllItems(); numEntriesField.setText(""); - + // close DB connection to file if (null != connection) { try { @@ -212,23 +223,23 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { LOGGER.log(Level.SEVERE, "Failed to close DB connection to file.", ex); //NON-NLS } } - + // delete last temp file if (null != tmpDBFile) { tmpDBFile.delete(); tmpDBFile = null; } } - + private void customizeComponents() { - + // add a actionListener to jTablesComboBox } - + /** * Process the given SQLite DB file * - * @param sqliteFile - + * @param sqliteFile - * * @return none */ @@ -239,15 +250,13 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { new SwingWorker() { @Override protected Boolean doInBackground() throws Exception { - + try { + // Copy the file to temp folder tmpDBPathName = Case.getCurrentCase().getTempDirectory() + File.separator + sqliteFile.getName() + "-" + sqliteFile.getId(); tmpDBFile = new File(tmpDBPathName); - - // Copy the file to temp folder ContentUtils.writeToFile(sqliteFile, tmpDBFile); - System.out.println("RAMAN: SQLite file copied to: " + tmpDBPathName); - + // Open copy using JDBC Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver connection = DriverManager.getConnection("jdbc:sqlite:" + tmpDBPathName); //NON-NLS @@ -266,18 +275,17 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { @Override protected void done() { - super.done(); + super.done(); try { boolean status = get(); - if ( (status == true) && (dbTablesMap.size() > 0) ) { + if ((status == true) && (dbTablesMap.size() > 0)) { dbTablesMap.keySet().forEach((tableName) -> { tablesDropdownList.addItem(tableName); }); - } - else { + } else { // Populate error message - tablesDropdownList.addItem("No tables found"); - tablesDropdownList.setEnabled(false); + tablesDropdownList.addItem("No tables found"); + tablesDropdownList.setEnabled(false); } } catch (InterruptedException | ExecutionException ex) { LOGGER.log(Level.SEVERE, "Unexpected exception while opening DB file", ex); //NON-NLS @@ -286,68 +294,66 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { }.execute(); } - + /** * Gets the table names and their schema from loaded SQLite db file * * @return true if success, false otherwise */ private boolean getTables() { - + try { Statement statement = connection.createStatement(); - - ResultSet resultSet = statement.executeQuery( - "SELECT name, sql FROM sqlite_master " - + " WHERE type= 'table' " - + " ORDER BY name;"); //NON-NLS - while (resultSet.next()) { - String tableName = resultSet.getString("name"); //NON-NLS - String tableSQL = resultSet.getString("sql"); //NON-NLS - - dbTablesMap.put(tableName, tableSQL); - String query = "PRAGMA table_info(" + tableName + ")"; //NON-NLS - ResultSet rs2; - try { - Statement statement2 = connection.createStatement(); - rs2 = statement2.executeQuery(query); - while (rs2.next()) { - - System.out.println("RAMAN: Col Name = " + rs2.getString("name") ); - System.out.println("RAMAN: Col Type = " + rs2.getString("type") ); - - // RAMAN TBD: parse and save the table schema - } - } catch (Exception ex) { - LOGGER.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS + ResultSet resultSet = statement.executeQuery( + "SELECT name, sql FROM sqlite_master " + + " WHERE type= 'table' " + + " ORDER BY name;"); //NON-NLS + + while (resultSet.next()) { + String tableName = resultSet.getString("name"); //NON-NLS + String tableSQL = resultSet.getString("sql"); //NON-NLS + + dbTablesMap.put(tableName, tableSQL); + String query = "PRAGMA table_info(" + tableName + ")"; //NON-NLS + ResultSet rs2; + try { + Statement statement2 = connection.createStatement(); + rs2 = statement2.executeQuery(query); + while (rs2.next()) { + + // System.out.println("RAMAN: Col Name = " + rs2.getString("name")); + // System.out.println("RAMAN: Col Type = " + rs2.getString("type")); + + // RAMAN TBD: parse and save the table schema } + } catch (Exception ex) { + LOGGER.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS } - } catch (Exception e) { - LOGGER.log(Level.SEVERE, "Error getting table names from the DB", e); //NON-NLS } + } catch (Exception e) { + LOGGER.log(Level.SEVERE, "Error getting table names from the DB", e); //NON-NLS + } return true; } - + private void readTable(String tableName) { - - System.out.println("RAMAN: selected table = " + tableName); - // TBD: need to handle cancelling if one is already in progress + new SwingWorker() { @Override protected Integer doInBackground() throws Exception { - + try { Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery( - "SELECT COUNT(*) as count FROM " + tableName ); //NON-NLS + "SELECT COUNT(*) as count FROM " + tableName); //NON-NLS - System.out.println("Row count = " + resultSet.getInt("count") ); - // Read all table names and schema + // TBD: read the rows here and popluate the ExplorerManager. + return resultSet.getInt("count"); - }catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Failed to Open DB.", ex); //NON-NLS + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Failed to get data for table.", ex); //NON-NLS } //NON-NLS return 0; @@ -355,35 +361,35 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { @Override protected void done() { - super.done(); + super.done(); try { int numRows = get(); - numEntriesField.setText( numRows + " entries"); + numEntriesField.setText(numRows + " entries"); } catch (InterruptedException | ExecutionException ex) { LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS } } }.execute(); - + } - + enum SQLStorageClass { NULL, - INTEGER, + INTEGER, REAL, TEXT, BLOB }; - + private class SQLColDef { - + private final String colName; private final SQLStorageClass storageClass; - - SQLColDef(String colName, SQLStorageClass sc ) { + + SQLColDef(String colName, SQLStorageClass sc) { this.colName = colName; this.storageClass = sc; } - + } } From d865b8ac7f23d446d91dae5ab4e91e027723bd62 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Tue, 16 Jan 2018 16:10:28 -0500 Subject: [PATCH 11/52] 3449: Use local variable instead of override a base format directory string. --- .../autopsy/report/ReportGenerator.java | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 1bb05652d4..ef20238c48 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -63,7 +63,7 @@ class ReportGenerator { */ private ReportProgressPanel progressPanel; - private String reportPathFormatString; + private static final String REPORT_PATH_FMT_STR = "%s" + File.separator + "%s %s %s" + File.separator; private final ReportGenerationPanel reportGenerationPanel = new ReportGenerationPanel(); static final String REPORTS_DIR = "Reports"; //NON-NLS @@ -89,12 +89,6 @@ class ReportGenerator { * Creates a report generator. */ ReportGenerator() { - // Create the root reports directory path of the form: /Reports/ / - DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); - Date date = new Date(); - String dateNoTime = dateFormat.format(date); - this.reportPathFormatString = currentCase.getReportDirectory() + File.separator + currentCase.getDisplayName() + " %s " + dateNoTime + File.separator; - this.errorList = new ArrayList<>(); } @@ -138,10 +132,10 @@ class ReportGenerator { */ void generateGeneralReport(GeneralReportModule generalReportModule) throws IOException { if (generalReportModule != null) { - reportPathFormatString = createReportDirectory(generalReportModule, reportPathFormatString); - setupProgressPanel(generalReportModule); + String reportDir = createReportDirectory(generalReportModule); + setupProgressPanel(generalReportModule, reportDir); ReportWorker worker = new ReportWorker(() -> { - generalReportModule.generateReport(reportPathFormatString, progressPanel); + generalReportModule.generateReport(reportDir, progressPanel); }); worker.execute(); displayProgressPanel(); @@ -158,10 +152,10 @@ class ReportGenerator { */ void generateTableReport(TableReportModule tableReport, Map artifactTypeSelections, Map tagNameSelections) throws IOException { if (tableReport != null && null != artifactTypeSelections) { - reportPathFormatString = createReportDirectory(tableReport, reportPathFormatString); - setupProgressPanel(tableReport); + String reportDir = createReportDirectory(tableReport); + setupProgressPanel(tableReport, reportDir); ReportWorker worker = new ReportWorker(() -> { - tableReport.startReport(reportPathFormatString); + tableReport.startReport(reportDir); TableReportGenerator generator = new TableReportGenerator(artifactTypeSelections, tagNameSelections, progressPanel, tableReport); generator.execute(); tableReport.endReport(); @@ -182,14 +176,14 @@ class ReportGenerator { */ void generateFileListReport(FileReportModule fileReportModule, Map enabledInfo) throws IOException { if (fileReportModule != null && null != enabledInfo) { - reportPathFormatString = createReportDirectory(fileReportModule, reportPathFormatString); + String reportDir = createReportDirectory(fileReportModule); List enabled = new ArrayList<>(); for (Entry e : enabledInfo.entrySet()) { if (e.getValue()) { enabled.add(e.getKey()); } } - setupProgressPanel(fileReportModule); + setupProgressPanel(fileReportModule, reportDir); ReportWorker worker = new ReportWorker(() -> { if (progressPanel.getStatus() != ReportStatus.CANCELED) { progressPanel.start(); @@ -200,7 +194,7 @@ class ReportGenerator { List files = getFiles(); int numFiles = files.size(); if (progressPanel.getStatus() != ReportStatus.CANCELED) { - fileReportModule.startReport(reportPathFormatString); + fileReportModule.startReport(reportDir); fileReportModule.startTable(enabled); } progressPanel.setIndeterminate(false); @@ -255,17 +249,22 @@ class ReportGenerator { } } - private void setupProgressPanel(ReportModule module) { + private void setupProgressPanel(ReportModule module, String reportDir) { String reportFilePath = module.getRelativeFilePath(); if (!reportFilePath.isEmpty()) { - this.progressPanel = reportGenerationPanel.addReport(module.getName(), String.format(reportPathFormatString, module.getName()) + reportFilePath); + this.progressPanel = reportGenerationPanel.addReport(module.getName(), reportDir + reportFilePath); } else { this.progressPanel = reportGenerationPanel.addReport(module.getName(), null); } } - private static String createReportDirectory(ReportModule module, String pathFormat) throws IOException { - String reportPath = String.format(pathFormat, module.getName()); + private static String createReportDirectory(ReportModule module) throws IOException { + Case currentCase = Case.getCurrentCase(); + // Create the root reports directory path of the form: /Reports/ / + DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); + Date date = new Date(); + String dateNoTime = dateFormat.format(date); + String reportPath = String.format(REPORT_PATH_FMT_STR, currentCase.getReportDirectory(), currentCase.getDisplayName(), module.getName(), dateNoTime); // Create the root reports directory. try { FileUtil.createFolder(new File(reportPath)); From c4bb6dba614753e83cc87c20ca3f67729a0d0ec3 Mon Sep 17 00:00:00 2001 From: Raman Date: Fri, 19 Jan 2018 13:01:08 -0500 Subject: [PATCH 12/52] 3415: Show SQLite table contents - First cut. --- .../autopsy/contentviewers/Bundle.properties | 8 +- .../contentviewers/SQLiteTableRowFactory.java | 89 ++++++ .../contentviewers/SQLiteTableView.form | 34 ++ .../contentviewers/SQLiteTableView.java | 143 +++++++++ .../autopsy/contentviewers/SQLiteViewer.form | 189 +++++++---- .../autopsy/contentviewers/SQLiteViewer.java | 299 +++++++++++++----- 6 files changed, 619 insertions(+), 143 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties index 8267587395..68e938a107 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties @@ -35,5 +35,11 @@ MessageContentViewer.attachmentsPanel.TabConstraints.tabTitle=Attachments MessageContentViewer.viewInNewWindowButton.text=View in New Window JPEGViewerDummy.jLabel1.text=You are looking at a JPEG file: JPEGViewerDummy.jTextField1.text=jTextField1 -SQLiteViewer.jLabel1.text=Table +SQLiteViewer.nextPageButton.text= +SQLiteViewer.prevPageButton.text= +SQLiteViewer.numPagesLabel.text=N +SQLiteViewer.jLabel3.text=of +SQLiteViewer.currPageLabel.text=x +SQLiteViewer.jLabel2.text=Page SQLiteViewer.numEntriesField.text=num Entries +SQLiteViewer.jLabel1.text=Table diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java new file mode 100644 index 0000000000..98b21149ce --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java @@ -0,0 +1,89 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 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.contentviewers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; +import org.sleuthkit.autopsy.datamodel.NodeProperty; + +public class SQLiteTableRowFactory extends ChildFactory { + + private final ArrayList> rows; + + public SQLiteTableRowFactory(ArrayList> rows) { + this.rows = rows; + } + + @Override + protected boolean createKeys(List keys) { + if (rows != null) { + for (int i = 0; i < rows.size(); i++) { + keys.add(i); + } + } + return true; + } + + @Override + protected Node createNodeForKey(Integer key) { + if (Objects.isNull(rows) || rows.isEmpty() || key >= rows.size()) { + return null; + } + + return new SQLiteTableRowNode(rows.get(key)); + } + +} + +class SQLiteTableRowNode extends AbstractNode { + + private final Map row; + + public SQLiteTableRowNode(Map row) { + super(Children.LEAF); + this.row = row; + } + + @Override + protected Sheet createSheet() { + + Sheet s = super.createSheet(); + Sheet.Set properties = s.get(Sheet.PROPERTIES); + if (properties == null) { + properties = Sheet.createPropertiesSet(); + s.put(properties); + } + + for (Map.Entry col : row.entrySet()) { + String colName = col.getKey(); + String colVal = col.getValue().toString(); + + properties.put(new NodeProperty<>(colName, colName, colName, colVal)); // NON-NLS + } + + return s; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form new file mode 100644 index 0000000000..a34fd71d16 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form @@ -0,0 +1,34 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java new file mode 100644 index 0000000000..b2fdc912d5 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java @@ -0,0 +1,143 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 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.contentviewers; + +import java.util.ArrayList; +import java.util.Map; +import java.util.Objects; +import javax.swing.ListSelectionModel; +import javax.swing.table.TableColumnModel; +import org.netbeans.swing.etable.ETableColumn; +import org.netbeans.swing.etable.ETableColumnModel; +import org.netbeans.swing.outline.Outline; +import org.openide.explorer.ExplorerManager; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; + + +public class SQLiteTableView extends javax.swing.JPanel implements ExplorerManager.Provider { + + private final Outline outline; + private final org.openide.explorer.view.OutlineView outlineView; + private ExplorerManager explorerManager; + + private final ArrayList> tableRows; + + /** + * Creates new form SQLiteTableView + * @param rows + */ + public SQLiteTableView(ArrayList> rows) { + + this.tableRows = rows; + + outlineView = new org.openide.explorer.view.OutlineView(); + + initComponents(); + + outline = outlineView.getOutline(); + outlineView.setPropertyColumns(); // column headers will be set later + outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + customize(); + } + + private void customize() { + + tableScrollPane.setViewportView(outlineView); + this.setVisible(true); + outline.setRowSelectionAllowed(false); + outline.setRootVisible(false); + + explorerManager = new ExplorerManager(); + explorerManager.setRootContext(new AbstractNode(Children.create(new SQLiteTableRowFactory(tableRows), true))); + + setupColumns(); + } + + /** + * Sets up the columns in the display table + */ + private void setupColumns() { + if (Objects.isNull(tableRows) || tableRows.isEmpty()) + return; + + Map row = tableRows.get(0); + + // Get the columns setup with respect to names and sortability + String[] propStrings = new String[row.size() * 2]; + + int i = 0; + for (Map.Entry col: row.entrySet()) { + String colName = col.getKey(); + propStrings[2 * i] = colName; + propStrings[2 * i + 1] = colName; + i++; + } + + + outlineView.setPropertyColumns(propStrings); + + // RAMAN TBD: Set width based on actual data in the top N rows?? + // TBD: Cant seem to geta horizontal scroll bar + for (int col = 0; col< outline.getModel().getColumnCount(); col++) { + outline.getColumnModel().getColumn(col).setMinWidth(50); + } + + // Hide the 'Nodes' column + TableColumnModel columnModel = outline.getColumnModel(); + ETableColumn column = (ETableColumn) columnModel.getColumn(0); + ((ETableColumnModel) columnModel).setColumnHidden(column, true); + + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + tableScrollPane = new javax.swing.JScrollPane(); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + + + @Override + public ExplorerManager getExplorerManager() { + return explorerManager; + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane tableScrollPane; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form index 3cdee8658c..121a96c823 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form @@ -1,6 +1,6 @@ -
+ @@ -16,22 +16,27 @@ - - + + - - - + + + + + + + + @@ -39,11 +44,23 @@ - + - + - + + + + + + + + + + + + + @@ -55,8 +72,14 @@ + + + + + + - + @@ -97,57 +120,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java index fff2f5d781..a60037fad1 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java @@ -1,21 +1,4 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2018 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.contentviewers; import java.awt.Component; @@ -27,12 +10,17 @@ import java.util.logging.Level; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; +import java.sql.ResultSetMetaData; import java.sql.Statement; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.Objects; import java.util.TreeMap; import java.util.concurrent.ExecutionException; import javax.swing.JComboBox; +import javax.swing.JPanel; import javax.swing.SwingWorker; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; @@ -44,20 +32,21 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { public static final String[] SUPPORTED_MIMETYPES = new String[]{"application/x-sqlite3"}; private static final Logger LOGGER = Logger.getLogger(FileViewer.class.getName()); private Connection connection = null; - + private String tmpDBPathName = null; private File tmpDBFile = null; - // TBD: Change the value to be a Array of ColDefs Map dbTablesMap = new TreeMap<>(); + private static final int ROWS_PER_PAGE = 100; + private int numRows; // num of rows in the selected table + private int currPage = 0; // curr page of rows being displayed + /** * Creates new form SQLiteViewer */ public SQLiteViewer() { initComponents(); - - customizeComponents(); } /** @@ -73,9 +62,15 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { tablesDropdownList = new javax.swing.JComboBox<>(); jLabel1 = new javax.swing.JLabel(); numEntriesField = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + currPageLabel = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + numPagesLabel = new javax.swing.JLabel(); + prevPageButton = new javax.swing.JButton(); + nextPageButton = new javax.swing.JButton(); jTableDataPanel = new javax.swing.JPanel(); - jScrollPane1 = new javax.swing.JScrollPane(); - jTable1 = new javax.swing.JTable(); + + jHdrPanel.setPreferredSize(new java.awt.Dimension(536, 40)); tablesDropdownList.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); tablesDropdownList.addActionListener(new java.awt.event.ActionListener() { @@ -89,9 +84,38 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { numEntriesField.setEditable(false); numEntriesField.setText(org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.numEntriesField.text")); // NOI18N numEntriesField.setBorder(null); - numEntriesField.addActionListener(new java.awt.event.ActionListener() { + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.jLabel2.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(currPageLabel, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.currPageLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.jLabel3.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(numPagesLabel, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.numPagesLabel.text")); // NOI18N + + prevPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(prevPageButton, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.prevPageButton.text")); // NOI18N + prevPageButton.setBorderPainted(false); + prevPageButton.setContentAreaFilled(false); + prevPageButton.setDisabledSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N + prevPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0)); + prevPageButton.setPreferredSize(new java.awt.Dimension(23, 23)); + prevPageButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - numEntriesFieldActionPerformed(evt); + prevPageButtonActionPerformed(evt); + } + }); + + nextPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(nextPageButton, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.nextPageButton.text")); // NOI18N + nextPageButton.setBorderPainted(false); + nextPageButton.setContentAreaFilled(false); + nextPageButton.setDisabledSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N + nextPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0)); + nextPageButton.setPreferredSize(new java.awt.Dimension(23, 23)); + nextPageButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + nextPageButtonActionPerformed(evt); } }); @@ -102,11 +126,23 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { .addGroup(jHdrPanelLayout.createSequentialGroup() .addContainerGap() .addComponent(jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(23, 23, 23) + .addGap(18, 18, 18) .addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(130, Short.MAX_VALUE)) + .addGap(15, 15, 15) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(currPageLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(numPagesLabel) + .addGap(18, 18, 18) + .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(133, Short.MAX_VALUE)) ); jHdrPanelLayout.setVerticalGroup( jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -115,40 +151,18 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { .addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel1) - .addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap(16, Short.MAX_VALUE)) - ); - - jTable1.setModel(new javax.swing.table.DefaultTableModel( - new Object [][] { - {null, null, null, null}, - {null, null, null, null}, - {null, null, null, null}, - {null, null, null, null} - }, - new String [] { - "Title 1", "Title 2", "Title 3", "Title 4" - } - )); - jScrollPane1.setViewportView(jTable1); - - javax.swing.GroupLayout jTableDataPanelLayout = new javax.swing.GroupLayout(jTableDataPanel); - jTableDataPanel.setLayout(jTableDataPanelLayout); - jTableDataPanelLayout.setHorizontalGroup( - jTableDataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jTableDataPanelLayout.createSequentialGroup() - .addContainerGap() - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addGap(15, 15, 15)) - ); - jTableDataPanelLayout.setVerticalGroup( - jTableDataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jTableDataPanelLayout.createSequentialGroup() - .addContainerGap() - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 275, Short.MAX_VALUE) + .addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel2) + .addComponent(currPageLabel) + .addComponent(jLabel3) + .addComponent(numPagesLabel) + .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap()) ); + jTableDataPanel.setLayout(new javax.swing.OverlayLayout(jTableDataPanel)); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -159,15 +173,39 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(jHdrPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jTableDataPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(jHdrPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jTableDataPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE)) ); }// //GEN-END:initComponents - private void numEntriesFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_numEntriesFieldActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_numEntriesFieldActionPerformed + private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed + + currPage++; + if (currPage * ROWS_PER_PAGE > numRows) { + nextPageButton.setEnabled(false); + } + currPageLabel.setText(Integer.toString(currPage)); + prevPageButton.setEnabled(true); + + // read and display a page of rows + String tableName = (String) this.tablesDropdownList.getSelectedItem(); + readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE); + }//GEN-LAST:event_nextPageButtonActionPerformed + + private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed + + currPage--; + if (currPage == 1) { + prevPageButton.setEnabled(false); + } + currPageLabel.setText(Integer.toString(currPage)); + nextPageButton.setEnabled(true); + + // read and display a page of rows + String tableName = (String) this.tablesDropdownList.getSelectedItem(); + readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE); + }//GEN-LAST:event_prevPageButtonActionPerformed private void tablesDropdownListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tablesDropdownListActionPerformed JComboBox cb = (JComboBox) evt.getSource(); @@ -176,17 +214,21 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { return; } - readTable(tableName); + selectTable(tableName); }//GEN-LAST:event_tablesDropdownListActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel currPageLabel; private javax.swing.JPanel jHdrPanel; private javax.swing.JLabel jLabel1; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JTable jTable1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; private javax.swing.JPanel jTableDataPanel; + private javax.swing.JButton nextPageButton; private javax.swing.JTextField numEntriesField; + private javax.swing.JLabel numPagesLabel; + private javax.swing.JButton prevPageButton; private javax.swing.JComboBox tablesDropdownList; // End of variables declaration//GEN-END:variables @@ -209,11 +251,11 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { public void resetComponent() { dbTablesMap.clear(); - + tablesDropdownList.setEnabled(true); tablesDropdownList.removeAllItems(); numEntriesField.setText(""); - + // close DB connection to file if (null != connection) { try { @@ -231,11 +273,6 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { } } - private void customizeComponents() { - - // add a actionListener to jTablesComboBox - } - /** * Process the given SQLite DB file * @@ -327,30 +364,26 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { // RAMAN TBD: parse and save the table schema } - } catch (Exception ex) { + } catch (SQLException ex) { LOGGER.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS } } - } catch (Exception e) { + } catch (SQLException e) { LOGGER.log(Level.SEVERE, "Error getting table names from the DB", e); //NON-NLS } return true; } - private void readTable(String tableName) { - // TBD: need to handle cancelling if one is already in progress - - new SwingWorker() { + private void selectTable(String tableName) { + new SwingWorker() { @Override protected Integer doInBackground() throws Exception { try { Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery( - "SELECT COUNT(*) as count FROM " + tableName); //NON-NLS + "SELECT count (*) as count FROM " + tableName); //NON-NLS - // TBD: read the rows here and popluate the ExplorerManager. - return resultSet.getInt("count"); } catch (SQLException ex) { LOGGER.log(Level.SEVERE, "Failed to get data for table.", ex); //NON-NLS @@ -363,8 +396,70 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { protected void done() { super.done(); try { - int numRows = get(); + + numRows = get(); numEntriesField.setText(numRows + " entries"); + + currPage = 1; + currPageLabel.setText(Integer.toString(currPage)); + numPagesLabel.setText(Integer.toString((numRows/ROWS_PER_PAGE)+1)); + + prevPageButton.setEnabled(false); + + jTableDataPanel.removeAll(); + jTableDataPanel.repaint(); + + if (numRows > 0) { + nextPageButton.setEnabled(((numRows > ROWS_PER_PAGE))); + readTable(tableName, (currPage-1)*ROWS_PER_PAGE + 1, ROWS_PER_PAGE); + } + else { + nextPageButton.setEnabled(false); + } + + + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS + } + } + }.execute(); + } + private void readTable(String tableName, int startRow, int numRowsToRead) { + + // TBD: need to handle cancelling if one is already in progress + + new SwingWorker>, Void>() { + @Override + protected ArrayList> doInBackground() throws Exception { + try { + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery( + "SELECT * FROM " + tableName + + " LIMIT " + Integer.toString(numRowsToRead) + + " OFFSET " + Integer.toString(startRow - 1) + ); //NON-NLS + + return resultSetToArrayList(resultSet); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Failed to get data for table.", ex); //NON-NLS + } + //NON-NLS + return null; + } + + @Override + protected void done() { + super.done(); + try { + ArrayList> rows = get(); + if (Objects.nonNull(rows)) { + JPanel selectedTableView = new SQLiteTableView(rows); + + jTableDataPanel.removeAll(); + jTableDataPanel.setLayout(new javax.swing.OverlayLayout(jTableDataPanel)); + jTableDataPanel.add(selectedTableView); + jTableDataPanel.repaint(); + } } catch (InterruptedException | ExecutionException ex) { LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS } @@ -373,6 +468,29 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { } + private ArrayList> resultSetToArrayList(ResultSet rs) throws SQLException { + ResultSetMetaData md = rs.getMetaData(); + int columns = md.getColumnCount(); + ArrayList> arraylist = new ArrayList<>(); + while (rs.next()) { + Map row = new LinkedHashMap<>(columns); + for (int i = 1; i <= columns; ++i) { + if (rs.getObject(i) == null) { + row.put(md.getColumnName(i), ""); + } else { + if (md.getColumnTypeName(i).compareToIgnoreCase("blob") == 0) { + row.put(md.getColumnName(i), "BLOB Data not shown..."); + } else { + row.put(md.getColumnName(i), rs.getObject(i)); + } + } + } + arraylist.add(row); + } + + return arraylist; + } + enum SQLStorageClass { NULL, INTEGER, @@ -390,6 +508,13 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { this.colName = colName; this.storageClass = sc; } - + + public String getColName() { + return colName; + } + + public SQLStorageClass getColStorageClass() { + return storageClass; + } } } From b8d9efb181ffb99b59eed5e0007afd6b88ae5ef2 Mon Sep 17 00:00:00 2001 From: Raman Date: Mon, 22 Jan 2018 10:19:06 -0500 Subject: [PATCH 13/52] Fixing scrollbar on the SQLiteTableView. - Removes the doubles vertical scroll bar. - A horizontal scroll bar appears but it is disabled and not functional --- .../contentviewers/SQLiteTableView.form | 25 +++++------------ .../contentviewers/SQLiteTableView.java | 28 ++++++++----------- 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form index a34fd71d16..75cb61a443 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form @@ -1,6 +1,11 @@
+ + + + + @@ -11,24 +16,8 @@ + - - - - - - - - - - - - - - - - - - + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java index b2fdc912d5..dc5d6c97af 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.contentviewers; +import java.awt.BorderLayout; import java.util.ArrayList; import java.util.Map; import java.util.Objects; @@ -48,9 +49,12 @@ public class SQLiteTableView extends javax.swing.JPanel implements ExplorerManag this.tableRows = rows; outlineView = new org.openide.explorer.view.OutlineView(); - + outlineView.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + initComponents(); + add(outlineView,BorderLayout.CENTER); + outline = outlineView.getOutline(); outlineView.setPropertyColumns(); // column headers will be set later outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); @@ -60,11 +64,12 @@ public class SQLiteTableView extends javax.swing.JPanel implements ExplorerManag private void customize() { - tableScrollPane.setViewportView(outlineView); + //tableScrollPane.setViewportView(outlineView); + this.setVisible(true); outline.setRowSelectionAllowed(false); outline.setRootVisible(false); - + explorerManager = new ExplorerManager(); explorerManager.setRootContext(new AbstractNode(Children.create(new SQLiteTableRowFactory(tableRows), true))); @@ -95,7 +100,7 @@ public class SQLiteTableView extends javax.swing.JPanel implements ExplorerManag outlineView.setPropertyColumns(propStrings); // RAMAN TBD: Set width based on actual data in the top N rows?? - // TBD: Cant seem to geta horizontal scroll bar + // TBD: Can't seem to geta horizontal scroll bar for (int col = 0; col< outline.getModel().getColumnCount(); col++) { outline.getColumnModel().getColumn(col).setMinWidth(50); } @@ -116,18 +121,8 @@ public class SQLiteTableView extends javax.swing.JPanel implements ExplorerManag // //GEN-BEGIN:initComponents private void initComponents() { - tableScrollPane = new javax.swing.JScrollPane(); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) - ); + setPreferredSize(new java.awt.Dimension(600, 400)); + setLayout(new java.awt.BorderLayout()); }// //GEN-END:initComponents @@ -138,6 +133,5 @@ public class SQLiteTableView extends javax.swing.JPanel implements ExplorerManag } // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JScrollPane tableScrollPane; // End of variables declaration//GEN-END:variables } From 71c510c4916d0267a6515bacb2c7c0e410a2afb1 Mon Sep 17 00:00:00 2001 From: Raman Date: Mon, 22 Jan 2018 13:39:02 -0500 Subject: [PATCH 14/52] 3415: Show SQLite table contents. - Cleanup --- .../contentviewers/SQLiteTableView.java | 4 +- .../autopsy/contentviewers/SQLiteViewer.java | 80 ++++++++----------- 2 files changed, 35 insertions(+), 49 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java index dc5d6c97af..c795133f73 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java @@ -99,8 +99,8 @@ public class SQLiteTableView extends javax.swing.JPanel implements ExplorerManag outlineView.setPropertyColumns(propStrings); - // RAMAN TBD: Set width based on actual data in the top N rows?? - // TBD: Can't seem to geta horizontal scroll bar + // TBD: Set width based on actual data in the top N rows?? + // TBD: Can't seem to get the horizontal scrollbar working for (int col = 0; col< outline.getModel().getColumnCount(); col++) { outline.getColumnModel().getColumn(col).setMinWidth(50); } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java index a60037fad1..5d90562834 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java @@ -1,3 +1,21 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 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.contentviewers; @@ -42,6 +60,7 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { private int numRows; // num of rows in the selected table private int currPage = 0; // curr page of rows being displayed + private SwingWorker>, Void> worker; /** * Creates new form SQLiteViewer */ @@ -352,21 +371,6 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { String tableSQL = resultSet.getString("sql"); //NON-NLS dbTablesMap.put(tableName, tableSQL); - String query = "PRAGMA table_info(" + tableName + ")"; //NON-NLS - ResultSet rs2; - try { - Statement statement2 = connection.createStatement(); - rs2 = statement2.executeQuery(query); - while (rs2.next()) { - - // System.out.println("RAMAN: Col Name = " + rs2.getString("name")); - // System.out.println("RAMAN: Col Type = " + rs2.getString("type")); - - // RAMAN TBD: parse and save the table schema - } - } catch (SQLException ex) { - LOGGER.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS - } } } catch (SQLException e) { LOGGER.log(Level.SEVERE, "Error getting table names from the DB", e); //NON-NLS @@ -426,9 +430,12 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { } private void readTable(String tableName, int startRow, int numRowsToRead) { - // TBD: need to handle cancelling if one is already in progress - - new SwingWorker>, Void>() { + if (worker != null && !worker.isDone()) { + worker.cancel(false); + worker = null; + } + + worker = new SwingWorker>, Void>() { @Override protected ArrayList> doInBackground() throws Exception { try { @@ -449,6 +456,11 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { @Override protected void done() { + + if (isCancelled()) { + return; + } + super.done(); try { ArrayList> rows = get(); @@ -464,8 +476,9 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS } } - }.execute(); - + }; + + worker.execute(); } private ArrayList> resultSetToArrayList(ResultSet rs) throws SQLException { @@ -490,31 +503,4 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { return arraylist; } - - enum SQLStorageClass { - NULL, - INTEGER, - REAL, - TEXT, - BLOB - }; - - private class SQLColDef { - - private final String colName; - private final SQLStorageClass storageClass; - - SQLColDef(String colName, SQLStorageClass sc) { - this.colName = colName; - this.storageClass = sc; - } - - public String getColName() { - return colName; - } - - public SQLStorageClass getColStorageClass() { - return storageClass; - } - } } From 75f6198190266102e433e589dcc9c2e2a42b6e5c Mon Sep 17 00:00:00 2001 From: Raman Date: Tue, 23 Jan 2018 13:33:03 -0500 Subject: [PATCH 15/52] Fixed a warning. --- Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java index 5d90562834..6442b645d1 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java @@ -227,7 +227,7 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { }//GEN-LAST:event_prevPageButtonActionPerformed private void tablesDropdownListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tablesDropdownListActionPerformed - JComboBox cb = (JComboBox) evt.getSource(); + JComboBox cb = (JComboBox) evt.getSource(); String tableName = (String) cb.getSelectedItem(); if (null == tableName) { return; From 6b02ab135864fff8ca223cab11743a95a849aafc Mon Sep 17 00:00:00 2001 From: millmanorama Date: Wed, 24 Jan 2018 11:44:57 +0100 Subject: [PATCH 16/52] refactor SQLiteViewer to fix scroll bar and painting issues. --- .../contentviewers/SQLiteTableRowFactory.java | 7 +- .../contentviewers/SQLiteTableView.form | 5 - .../contentviewers/SQLiteTableView.java | 99 +++++++--------- .../autopsy/contentviewers/SQLiteViewer.form | 47 ++------ .../autopsy/contentviewers/SQLiteViewer.java | 110 +++++++++--------- 5 files changed, 118 insertions(+), 150 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java index 98b21149ce..633f40260c 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.contentviewers; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -31,9 +30,9 @@ import org.sleuthkit.autopsy.datamodel.NodeProperty; public class SQLiteTableRowFactory extends ChildFactory { - private final ArrayList> rows; + private final List> rows; - public SQLiteTableRowFactory(ArrayList> rows) { + public SQLiteTableRowFactory(List> rows) { this.rows = rows; } @@ -62,7 +61,7 @@ class SQLiteTableRowNode extends AbstractNode { private final Map row; - public SQLiteTableRowNode(Map row) { + SQLiteTableRowNode(Map row) { super(Children.LEAF); this.row = row; } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form index 75cb61a443..2c7924e2a4 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.form @@ -1,11 +1,6 @@
- - - - - diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java index c795133f73..ad1117f0a0 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java @@ -19,10 +19,13 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.BorderLayout; -import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Objects; +import javax.swing.JPanel; +import javax.swing.JTable; import javax.swing.ListSelectionModel; +import javax.swing.ScrollPaneConstants; import javax.swing.table.TableColumnModel; import org.netbeans.swing.etable.ETableColumn; import org.netbeans.swing.etable.ETableColumnModel; @@ -31,73 +34,64 @@ import org.openide.explorer.ExplorerManager; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; +class SQLiteTableView extends JPanel implements ExplorerManager.Provider { -public class SQLiteTableView extends javax.swing.JPanel implements ExplorerManager.Provider { - - private final Outline outline; private final org.openide.explorer.view.OutlineView outlineView; - private ExplorerManager explorerManager; + private final Outline outline; + private final ExplorerManager explorerManager; - private final ArrayList> tableRows; - /** * Creates new form SQLiteTableView - * @param rows + * */ - public SQLiteTableView(ArrayList> rows) { - - this.tableRows = rows; - - outlineView = new org.openide.explorer.view.OutlineView(); - outlineView.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); - + SQLiteTableView() { + initComponents(); - - add(outlineView,BorderLayout.CENTER); - - outline = outlineView.getOutline(); + outlineView = new org.openide.explorer.view.OutlineView(); + add(outlineView, BorderLayout.CENTER); outlineView.setPropertyColumns(); // column headers will be set later + outlineView.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + outlineView.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + + outline = outlineView.getOutline(); + outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - customize(); + outline.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + outline.setRowSelectionAllowed(false); + outline.setRootVisible(false); + + explorerManager = new ExplorerManager(); } - private void customize() { - - //tableScrollPane.setViewportView(outlineView); - - this.setVisible(true); - outline.setRowSelectionAllowed(false); - outline.setRootVisible(false); - - explorerManager = new ExplorerManager(); - explorerManager.setRootContext(new AbstractNode(Children.create(new SQLiteTableRowFactory(tableRows), true))); - - setupColumns(); - } - /** * Sets up the columns in the display table + * + * @param tableRows */ - private void setupColumns() { - if (Objects.isNull(tableRows) || tableRows.isEmpty()) - return; - - Map row = tableRows.get(0); - - // Get the columns setup with respect to names and sortability - String[] propStrings = new String[row.size() * 2]; - - int i = 0; - for (Map.Entry col: row.entrySet()) { + void setupTable(List> tableRows) { + + explorerManager.setRootContext(new AbstractNode(Children.create(new SQLiteTableRowFactory(tableRows), true))); + + if (Objects.isNull(tableRows) || tableRows.isEmpty()) { + outlineView.setPropertyColumns(); +// return; + } else { + + Map row = tableRows.get(0); + + // Get the columns setup with respect to names and sortability + String[] propStrings = new String[row.size() * 2]; + + int i = 0; + for (Map.Entry col : row.entrySet()) { String colName = col.getKey(); propStrings[2 * i] = colName; propStrings[2 * i + 1] = colName; i++; + } + + outlineView.setPropertyColumns(propStrings); } - - - outlineView.setPropertyColumns(propStrings); // TBD: Set width based on actual data in the top N rows?? // TBD: Can't seem to get the horizontal scrollbar working @@ -109,9 +103,9 @@ public class SQLiteTableView extends javax.swing.JPanel implements ExplorerManag TableColumnModel columnModel = outline.getColumnModel(); ETableColumn column = (ETableColumn) columnModel.getColumn(0); ((ETableColumnModel) columnModel).setColumnHidden(column, true); - + } - + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -121,12 +115,9 @@ public class SQLiteTableView extends javax.swing.JPanel implements ExplorerManag // //GEN-BEGIN:initComponents private void initComponents() { - setPreferredSize(new java.awt.Dimension(600, 400)); setLayout(new java.awt.BorderLayout()); }// //GEN-END:initComponents - - @Override public ExplorerManager getExplorerManager() { return explorerManager; diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form index 121a96c823..0469da7b73 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form @@ -68,16 +68,18 @@ - - - - - - - - + + + + + + + + + + @@ -200,33 +202,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java index 6442b645d1..d5b5afdb68 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java @@ -16,29 +16,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.sleuthkit.autopsy.contentviewers; +import java.awt.BorderLayout; import java.awt.Component; import java.io.File; import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.logging.Level; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; -import java.sql.Statement; import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.TreeMap; import java.util.concurrent.ExecutionException; +import java.util.logging.Level; import javax.swing.JComboBox; -import javax.swing.JPanel; import javax.swing.SwingWorker; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; @@ -50,22 +50,26 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { public static final String[] SUPPORTED_MIMETYPES = new String[]{"application/x-sqlite3"}; private static final Logger LOGGER = Logger.getLogger(FileViewer.class.getName()); private Connection connection = null; - + private String tmpDBPathName = null; private File tmpDBFile = null; - Map dbTablesMap = new TreeMap<>(); + private final Map dbTablesMap = new TreeMap<>(); private static final int ROWS_PER_PAGE = 100; private int numRows; // num of rows in the selected table private int currPage = 0; // curr page of rows being displayed - - private SwingWorker>, Void> worker; + + SQLiteTableView selectedTableView = new SQLiteTableView(); + + private SwingWorker worker; + /** * Creates new form SQLiteViewer */ public SQLiteViewer() { initComponents(); + jTableDataPanel.add(selectedTableView, BorderLayout.CENTER); } /** @@ -167,20 +171,21 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jHdrPanelLayout.createSequentialGroup() .addContainerGap() - .addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel1) - .addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel2) - .addComponent(currPageLabel) - .addComponent(jLabel3) - .addComponent(numPagesLabel) + .addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel1) + .addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel2) + .addComponent(currPageLabel) + .addComponent(jLabel3) + .addComponent(numPagesLabel))) .addContainerGap()) ); - jTableDataPanel.setLayout(new javax.swing.OverlayLayout(jTableDataPanel)); + jTableDataPanel.setLayout(new java.awt.BorderLayout()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); @@ -270,11 +275,11 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { public void resetComponent() { dbTablesMap.clear(); - + tablesDropdownList.setEnabled(true); tablesDropdownList.removeAllItems(); numEntriesField.setText(""); - + // close DB connection to file if (null != connection) { try { @@ -312,7 +317,7 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { tmpDBPathName = Case.getCurrentCase().getTempDirectory() + File.separator + sqliteFile.getName() + "-" + sqliteFile.getId(); tmpDBFile = new File(tmpDBPathName); ContentUtils.writeToFile(sqliteFile, tmpDBFile); - + // Open copy using JDBC Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver connection = DriverManager.getConnection("jdbc:sqlite:" + tmpDBPathName); //NON-NLS @@ -379,7 +384,12 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { } private void selectTable(String tableName) { - new SwingWorker() { + if (worker != null && !worker.isDone()) { + worker.cancel(false); + worker = null; + } + + worker = new SwingWorker() { @Override protected Integer doInBackground() throws Exception { @@ -400,48 +410,47 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { protected void done() { super.done(); try { - + numRows = get(); numEntriesField.setText(numRows + " entries"); - + currPage = 1; currPageLabel.setText(Integer.toString(currPage)); - numPagesLabel.setText(Integer.toString((numRows/ROWS_PER_PAGE)+1)); - + numPagesLabel.setText(Integer.toString((numRows / ROWS_PER_PAGE) + 1)); + prevPageButton.setEnabled(false); - - jTableDataPanel.removeAll(); - jTableDataPanel.repaint(); - + + if (numRows > 0) { nextPageButton.setEnabled(((numRows > ROWS_PER_PAGE))); - readTable(tableName, (currPage-1)*ROWS_PER_PAGE + 1, ROWS_PER_PAGE); - } - else { + readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE); + } else { nextPageButton.setEnabled(false); + selectedTableView.setupTable(Collections.emptyList()); } - - + } catch (InterruptedException | ExecutionException ex) { LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS } } - }.execute(); + }; + worker.execute(); } + private void readTable(String tableName, int startRow, int numRowsToRead) { - + if (worker != null && !worker.isDone()) { worker.cancel(false); worker = null; } - + worker = new SwingWorker>, Void>() { @Override protected ArrayList> doInBackground() throws Exception { try { Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery( - "SELECT * FROM " + tableName + "SELECT * FROM " + tableName + " LIMIT " + Integer.toString(numRowsToRead) + " OFFSET " + Integer.toString(startRow - 1) ); //NON-NLS @@ -456,32 +465,29 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { @Override protected void done() { - + if (isCancelled()) { return; } - + super.done(); try { ArrayList> rows = get(); if (Objects.nonNull(rows)) { - JPanel selectedTableView = new SQLiteTableView(rows); - - jTableDataPanel.removeAll(); - jTableDataPanel.setLayout(new javax.swing.OverlayLayout(jTableDataPanel)); - jTableDataPanel.add(selectedTableView); - jTableDataPanel.repaint(); + selectedTableView.setupTable(rows); + }else{ + selectedTableView.setupTable(Collections.emptyList()); } } catch (InterruptedException | ExecutionException ex) { LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS } } }; - + worker.execute(); } - private ArrayList> resultSetToArrayList(ResultSet rs) throws SQLException { + private ArrayList> resultSetToArrayList(ResultSet rs) throws SQLException { ResultSetMetaData md = rs.getMetaData(); int columns = md.getColumnCount(); ArrayList> arraylist = new ArrayList<>(); @@ -502,5 +508,5 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { } return arraylist; - } + } } From 299c80669ca4d34009f8f91513a011480c3a790c Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 25 Jan 2018 13:10:06 -0500 Subject: [PATCH 17/52] Made initial test method for central repo. Made a few method public/made new public methods needed for tests. --- .../datamodel/CorrelationCase.java | 6 +- .../datamodel/CorrelationDataSource.java | 10 + .../datamodel/CentralRepoDatamodelTest.java | 174 ++++++++++++++++++ 3 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationCase.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationCase.java index 79d94837ee..2d441881de 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationCase.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationCase.java @@ -50,6 +50,10 @@ public class CorrelationCase implements Serializable { * @param caseUUID Globally unique identifier * @param displayName */ + public CorrelationCase(String caseUUID, String displayName) { + this(-1, caseUUID, displayName); + } + CorrelationCase(int ID, String caseUUID, String displayName) { this(ID, caseUUID, null, displayName, DATE_FORMAT.format(new Date()), null, null, null, null, null); } @@ -156,7 +160,7 @@ public class CorrelationCase implements Serializable { /** * @return the database ID for the case or -1 if it is unknown (or not in the DB) */ - int getID() { + public int getID() { // @@@ Should probably have some lazy logic here to lead the ID from the DB if it is -1 return databaseId; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java index 9bad6dbac7..9aa9fada32 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java @@ -38,6 +38,16 @@ public class CorrelationDataSource implements Serializable { private final String deviceID; //< Unique to its associated case (not necessarily globally unique) private final String name; + /** + * + * @param caseId + * @param deviceId + * @param name + */ + public CorrelationDataSource(int caseId, String deviceId, String name) { + this(caseId, -1, deviceId, name); + } + CorrelationDataSource(int caseId, int dataSourceId, String deviceId, diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java new file mode 100644 index 0000000000..345dff4cd3 --- /dev/null +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -0,0 +1,174 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.centralrepository.datamodel; + +import java.io.IOException; +import java.util.Map; +import java.nio.file.Path; +import java.nio.file.Paths; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; +import junit.framework.Test; +import junit.framework.TestCase; +import org.apache.commons.io.FileUtils; +import org.netbeans.junit.NbModuleSuite; +import org.openide.util.Exceptions; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.CaseActionException; +import org.sleuthkit.autopsy.casemodule.CaseDetails; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; + +/** + * + */ +public class CentralRepoDatamodelTest extends TestCase{ + + private static final String PROPERTIES_FILE = "CentralRepository"; + private static final String CR_DB_NAME = "testcentralrepo.db"; + private static final Path testDirectory = Paths.get(System.getProperty("java.io.tmpdir"), "CentralRepoDatamodelTest"); + + private CorrelationCase case1; + private CorrelationCase case2; + private CorrelationDataSource dataSource1fromCase1; + private CorrelationDataSource dataSource2fromCase1; + private EamOrganization org1; + private EamOrganization org2; + + private Map propertiesMap = null; + + public static Test suite() { + NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(CentralRepoDatamodelTest.class). + clusters(".*"). + enableModules(".*"); + return conf.suite(); + } + + @Override + public void setUp() { + + boolean errorsOccurred; + SqliteEamDbSettings dbSettingsSqlite = new SqliteEamDbSettings(); + + // Delete the test directory, if it exists + if(testDirectory.toFile().exists()){ + try{ + FileUtils.deleteDirectory(testDirectory.toFile()); + } catch (IOException ex){ + Exceptions.printStackTrace(ex); + } + } + assertFalse("Unable to delete existing test directory", testDirectory.toFile().exists()); + + // Create the test directory + testDirectory.toFile().mkdirs(); + assertTrue("Unable to create test directory", testDirectory.toFile().exists()); + + // Save the current central repo settings + propertiesMap = ModuleSettings.getConfigSettings(PROPERTIES_FILE); + + // Set up an Autopsy case for testing + try { + Case.createAsCurrentCase(Case.CaseType.SINGLE_USER_CASE, testDirectory.toString(), new CaseDetails("CentralRepoDatamodelTestCase")); + } catch (CaseActionException ex) { + Exceptions.printStackTrace(ex); + } + assertTrue("Failed to create test case", testDirectory.toFile().exists()); + + errorsOccurred = false; + try{ + dbSettingsSqlite.setDbName(CR_DB_NAME); + dbSettingsSqlite.setDbDirectory(testDirectory.toString()); + if (!dbSettingsSqlite.dbDirectoryExists()) { + dbSettingsSqlite.createDbDirectory(); + } + + assertTrue("Failed to created central repo directory " + dbSettingsSqlite.getDbDirectory(), dbSettingsSqlite.dbDirectoryExists()); + + boolean result = dbSettingsSqlite.initializeDatabaseSchema() + && dbSettingsSqlite.insertDefaultDatabaseContent(); + + assertTrue("Failed to initialize central repo database", result); + + dbSettingsSqlite.saveSettings(); + EamDbUtil.setUseCentralRepo(true); + EamDbPlatformEnum.setSelectedPlatform(EamDbPlatformEnum.SQLITE.name()); + EamDbPlatformEnum.saveSelectedPlatform(); + + EamDb.getInstance().getCases(); + } catch (Exception ex){ + errorsOccurred = true; + Exceptions.printStackTrace(ex); + } + + assertFalse("Failed to create/initialize central repo database", errorsOccurred); + Path crDbFilePath = Paths.get(testDirectory.toString(), CR_DB_NAME); + assertTrue("Failed to create central repo database at " + crDbFilePath, crDbFilePath.toFile().exists()); + + // Set up some default objects to be used by the tests + errorsOccurred = false; + try{ + case1 = new CorrelationCase("case1_uuid", "case1"); + case1 = EamDb.getInstance().newCase(case1); + assertTrue("Failed to create test object case1", case1 != null); + + case2 = new CorrelationCase("case2_uuid", "case2"); + case2 = EamDb.getInstance().newCase(case2); + assertTrue("Failed to create test object case2", case2 != null); + + dataSource1fromCase1 = new CorrelationDataSource(case1.getID(), "dataSource1_deviceID", "dataSource1"); + EamDb.getInstance().newDataSource(dataSource1fromCase1); + dataSource1fromCase1 = EamDb.getInstance().getDataSource(case1, dataSource1fromCase1.getDeviceID()); + assertTrue("Failed to create test object dataSource1fromCase1", dataSource1fromCase1 != null); + + dataSource2fromCase1 = new CorrelationDataSource(case1.getID(), "dataSource2_deviceID", "dataSource2"); + EamDb.getInstance().newDataSource(dataSource2fromCase1); + dataSource2fromCase1 = EamDb.getInstance().getDataSource(case1, dataSource2fromCase1.getDeviceID()); + assertTrue("Failed to create test object dataSource2fromCase1", dataSource2fromCase1 != null); + + org1 = new EamOrganization("org1"); + org1.setOrgID((int)EamDb.getInstance().newOrganization(org1)); + + org2 = new EamOrganization("org2"); + org2.setOrgID((int)EamDb.getInstance().newOrganization(org2)); + + + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + errorsOccurred = true; + } + + assertFalse("Failed to create default database objects", errorsOccurred); + + + } + + @Override + public void tearDown() { + + // Restore the original properties + ModuleSettings.setConfigSettings(PROPERTIES_FILE, propertiesMap); + + // Close and delete the test case and central repo db + try { + EamDb.getInstance().shutdownConnections(); + Case.closeCurrentCase(); + FileUtils.deleteDirectory(testDirectory.toFile()); + + } catch (EamDbException | CaseActionException | IOException ex) { + Exceptions.printStackTrace(ex); + } + assertFalse("Error deleting test directory " + testDirectory.toString(), testDirectory.toFile().exists()); + } + + public void test1(){ + System.out.println("It's test 1"); + } + + // public void test2(){ + + // } + +} From f80b3d94c1478e008922033b4d5da3d299e24776 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Thu, 25 Jan 2018 13:37:59 -0500 Subject: [PATCH 18/52] 3469_3470: Catch Runtime exception for too large data for Excel cell and fix the HTML formatting issue. --- .../sleuthkit/autopsy/report/ReportExcel.java | 16 +++++++++++++++- .../org/sleuthkit/autopsy/report/ReportHTML.java | 4 +++- .../autopsy/report/TableReportGenerator.java | 3 +-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java index 19526a0a19..f1b8c421b5 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java @@ -34,6 +34,7 @@ class ReportExcel implements TableReportModule { private static final Logger logger = Logger.getLogger(ReportExcel.class.getName()); private static ReportExcel instance; + private static final int EXCEL_CELL_MAXIMUM_SIZE = 36767; private Workbook wb; private Sheet sheet; @@ -236,10 +237,23 @@ class ReportExcel implements TableReportModule { * @param row cells to add */ @Override + @NbBundle.Messages({ + "ReportExcel.exceptionMessage.dataTooLarge=Value is too long to fit into an Excel cell. ", + "ReportExcel.exceptionMessage.errorText=Error showing data into an Excel cell." + }) + public void addRow(List rowData) { Row row = sheet.createRow(rowIndex); for (int i = 0; i < rowData.size(); ++i) { - row.createCell(i).setCellValue(rowData.get(i)); + try { + row.createCell(i).setCellValue(rowData.get(i)); + } catch (Exception e) { + if (e instanceof java.lang.IllegalArgumentException && rowData.get(i).length() > EXCEL_CELL_MAXIMUM_SIZE) { + row.getCell(i).setCellValue(Bundle.ReportExcel_exceptionMessage_dataTooLarge() + e.getMessage()); + } else { + row.getCell(i).setCellValue(Bundle.ReportExcel_exceptionMessage_errorText()); + } + } } ++rowIndex; } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index 88d9fe44b1..01a179a370 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -51,6 +51,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Services; import org.sleuthkit.autopsy.casemodule.services.TagsManager; +import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor; @@ -554,7 +555,8 @@ class ReportHTML implements TableReportModule { StringBuilder builder = new StringBuilder(); builder.append("\t\n"); //NON-NLS for (String cell : row) { - builder.append("\t\t").append(cell).append("\n"); //NON-NLS + String escapeHTMLCell = EscapeUtil.escapeHtml(cell); + builder.append("\t\t").append(escapeHTMLCell).append("\n"); //NON-NLS } builder.append("\t\n"); //NON-NLS rowCount++; diff --git a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java index 93894022b3..58e38a7d23 100644 --- a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java @@ -666,8 +666,7 @@ class TableReportGenerator { tableModule.startTable(columnHeaderNames); } - String previewreplace = EscapeUtil.escapeHtml(preview); - tableModule.addRow(Arrays.asList(new String[]{previewreplace.replaceAll(" Date: Fri, 26 Jan 2018 11:58:29 -0500 Subject: [PATCH 19/52] 3469_3470: cleanup --- .../src/org/sleuthkit/autopsy/report/TableReportGenerator.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java index 58e38a7d23..499f848d54 100644 --- a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-16 Basis Technology Corp. + * Copyright 2013-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,7 +40,6 @@ import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.TagsManager; -import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils; From c7a7898b957516f0a08b8d2945a5aaa41c8b848c Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Fri, 26 Jan 2018 15:14:27 -0500 Subject: [PATCH 20/52] 3469_3470: Use variable to make code more readable. --- Core/src/org/sleuthkit/autopsy/report/ReportExcel.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java index f1b8c421b5..81045dc5b1 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java @@ -245,13 +245,14 @@ class ReportExcel implements TableReportModule { public void addRow(List rowData) { Row row = sheet.createRow(rowIndex); for (int i = 0; i < rowData.size(); ++i) { + Cell excelCell = row.createCell(i); try { - row.createCell(i).setCellValue(rowData.get(i)); + excelCell.setCellValue(rowData.get(i)); } catch (Exception e) { if (e instanceof java.lang.IllegalArgumentException && rowData.get(i).length() > EXCEL_CELL_MAXIMUM_SIZE) { - row.getCell(i).setCellValue(Bundle.ReportExcel_exceptionMessage_dataTooLarge() + e.getMessage()); + excelCell.setCellValue(Bundle.ReportExcel_exceptionMessage_dataTooLarge() + e.getMessage()); } else { - row.getCell(i).setCellValue(Bundle.ReportExcel_exceptionMessage_errorText()); + excelCell.setCellValue(Bundle.ReportExcel_exceptionMessage_errorText()); } } } From 487202790f109713aa81d7514b0d11f88c30595b Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 29 Jan 2018 08:05:48 -0500 Subject: [PATCH 21/52] Case test method is done --- .../datamodel/AbstractSqlEamDb.java | 16 +- .../datamodel/CentralRepoDatamodelTest.java | 434 +++++++++++++++--- 2 files changed, 388 insertions(+), 62 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 2cac9b4927..c5b9af62a6 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -271,6 +271,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public void updateCase(CorrelationCase eamCase) throws EamDbException { + if(eamCase == null) { + throw new EamDbException("CorrelationCase argument is null"); + } + Connection conn = connect(); PreparedStatement preparedStatement = null; @@ -929,12 +933,16 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public void bulkInsertCases(List cases) throws EamDbException { - Connection conn = connect(); - + if(cases == null) { + throw new EamDbException("cases argument is null"); + } + if (cases.isEmpty()) { return; } + Connection conn = connect(); + int counter = 0; PreparedStatement bulkPs = null; try { @@ -1012,11 +1020,11 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public void setArtifactInstanceKnownStatus(CorrelationAttribute eamArtifact, TskData.FileKnown knownStatus) throws EamDbException { - Connection conn = connect(); - if (1 != eamArtifact.getInstances().size()) { throw new EamDbException("Error: Artifact must have exactly one (1) Artifact Instance to set as notable."); // NON-NLS } + + Connection conn = connect(); List eamInstances = eamArtifact.getInstances(); CorrelationAttributeInstance eamInstance = eamInstances.get(0); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 345dff4cd3..489f651e23 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -7,8 +7,11 @@ package org.sleuthkit.autopsy.centralrepository.datamodel; import java.io.IOException; import java.util.Map; +import java.util.List; +import java.util.ArrayList; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.stream.Collectors; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import junit.framework.Test; @@ -16,6 +19,7 @@ import junit.framework.TestCase; import org.apache.commons.io.FileUtils; import org.netbeans.junit.NbModuleSuite; import org.openide.util.Exceptions; +import org.python.icu.impl.Assert; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.CaseActionException; import org.sleuthkit.autopsy.casemodule.CaseDetails; @@ -24,100 +28,95 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings; /** * */ -public class CentralRepoDatamodelTest extends TestCase{ - +public class CentralRepoDatamodelTest extends TestCase { + private static final String PROPERTIES_FILE = "CentralRepository"; private static final String CR_DB_NAME = "testcentralrepo.db"; private static final Path testDirectory = Paths.get(System.getProperty("java.io.tmpdir"), "CentralRepoDatamodelTest"); - + SqliteEamDbSettings dbSettingsSqlite; + private CorrelationCase case1; private CorrelationCase case2; private CorrelationDataSource dataSource1fromCase1; private CorrelationDataSource dataSource2fromCase1; private EamOrganization org1; private EamOrganization org2; - + private Map propertiesMap = null; - + public static Test suite() { NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(CentralRepoDatamodelTest.class). clusters(".*"). enableModules(".*"); return conf.suite(); } - + @Override public void setUp() { - - boolean errorsOccurred; - SqliteEamDbSettings dbSettingsSqlite = new SqliteEamDbSettings(); - + dbSettingsSqlite = new SqliteEamDbSettings(); + // Delete the test directory, if it exists - if(testDirectory.toFile().exists()){ - try{ + if (testDirectory.toFile().exists()) { + try { FileUtils.deleteDirectory(testDirectory.toFile()); - } catch (IOException ex){ - Exceptions.printStackTrace(ex); + } catch (IOException ex) { + Assert.fail(ex); } } assertFalse("Unable to delete existing test directory", testDirectory.toFile().exists()); - + // Create the test directory testDirectory.toFile().mkdirs(); assertTrue("Unable to create test directory", testDirectory.toFile().exists()); - + // Save the current central repo settings propertiesMap = ModuleSettings.getConfigSettings(PROPERTIES_FILE); - + // Set up an Autopsy case for testing try { Case.createAsCurrentCase(Case.CaseType.SINGLE_USER_CASE, testDirectory.toString(), new CaseDetails("CentralRepoDatamodelTestCase")); } catch (CaseActionException ex) { Exceptions.printStackTrace(ex); - } + Assert.fail(ex); + } assertTrue("Failed to create test case", testDirectory.toFile().exists()); - - errorsOccurred = false; - try{ + + try { dbSettingsSqlite.setDbName(CR_DB_NAME); dbSettingsSqlite.setDbDirectory(testDirectory.toString()); if (!dbSettingsSqlite.dbDirectoryExists()) { dbSettingsSqlite.createDbDirectory(); } - + assertTrue("Failed to created central repo directory " + dbSettingsSqlite.getDbDirectory(), dbSettingsSqlite.dbDirectoryExists()); boolean result = dbSettingsSqlite.initializeDatabaseSchema() - && dbSettingsSqlite.insertDefaultDatabaseContent(); + && dbSettingsSqlite.insertDefaultDatabaseContent(); assertTrue("Failed to initialize central repo database", result); - + dbSettingsSqlite.saveSettings(); EamDbUtil.setUseCentralRepo(true); EamDbPlatformEnum.setSelectedPlatform(EamDbPlatformEnum.SQLITE.name()); EamDbPlatformEnum.saveSelectedPlatform(); - - EamDb.getInstance().getCases(); - } catch (Exception ex){ - errorsOccurred = true; + } catch (Exception ex) { Exceptions.printStackTrace(ex); + Assert.fail(ex); } - - assertFalse("Failed to create/initialize central repo database", errorsOccurred); + Path crDbFilePath = Paths.get(testDirectory.toString(), CR_DB_NAME); assertTrue("Failed to create central repo database at " + crDbFilePath, crDbFilePath.toFile().exists()); - + // Set up some default objects to be used by the tests - errorsOccurred = false; - try{ + try { case1 = new CorrelationCase("case1_uuid", "case1"); case1 = EamDb.getInstance().newCase(case1); assertTrue("Failed to create test object case1", case1 != null); - + case2 = new CorrelationCase("case2_uuid", "case2"); case2 = EamDb.getInstance().newCase(case2); assertTrue("Failed to create test object case2", case2 != null); - + dataSource1fromCase1 = new CorrelationDataSource(case1.getID(), "dataSource1_deviceID", "dataSource1"); EamDb.getInstance().newDataSource(dataSource1fromCase1); dataSource1fromCase1 = EamDb.getInstance().getDataSource(case1, dataSource1fromCase1.getDeviceID()); @@ -126,31 +125,27 @@ public class CentralRepoDatamodelTest extends TestCase{ dataSource2fromCase1 = new CorrelationDataSource(case1.getID(), "dataSource2_deviceID", "dataSource2"); EamDb.getInstance().newDataSource(dataSource2fromCase1); dataSource2fromCase1 = EamDb.getInstance().getDataSource(case1, dataSource2fromCase1.getDeviceID()); - assertTrue("Failed to create test object dataSource2fromCase1", dataSource2fromCase1 != null); - + assertTrue("Failed to create test object dataSource2fromCase1", dataSource2fromCase1 != null); + org1 = new EamOrganization("org1"); - org1.setOrgID((int)EamDb.getInstance().newOrganization(org1)); - + org1.setOrgID((int) EamDb.getInstance().newOrganization(org1)); + org2 = new EamOrganization("org2"); - org2.setOrgID((int)EamDb.getInstance().newOrganization(org2)); - - - } catch (EamDbException ex){ + org2.setOrgID((int) EamDb.getInstance().newOrganization(org2)); + + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - errorsOccurred = true; + Assert.fail(ex); } - - assertFalse("Failed to create default database objects", errorsOccurred); - } - + @Override public void tearDown() { - + // Restore the original properties ModuleSettings.setConfigSettings(PROPERTIES_FILE, propertiesMap); - + // Close and delete the test case and central repo db try { EamDb.getInstance().shutdownConnections(); @@ -158,17 +153,340 @@ public class CentralRepoDatamodelTest extends TestCase{ FileUtils.deleteDirectory(testDirectory.toFile()); } catch (EamDbException | CaseActionException | IOException ex) { + //} catch (EamDbException | CaseActionException ex) { Exceptions.printStackTrace(ex); + Assert.fail(ex); } assertFalse("Error deleting test directory " + testDirectory.toString(), testDirectory.toFile().exists()); } - - public void test1(){ - System.out.println("It's test 1"); - } - - // public void test2(){ + + /** + * Test method for the methods related to the cases table + * newCase(CorrelationCase eamCase) tests: + * - Test valid data + * - Test null UUID + * - Test null case name + * - Test repeated UUID + * newCase(Case autopsyCase) tests: + * - Test valid data + * - Test null autopsyCase + * updateCase(CorrelationCase eamCase) tests: + * - Test with valid data, checking all fields + * - Test null eamCase + * getCase(Case autopsyCase) tests: + * - Test ?? + * getCaseByUUID(String caseUUID) getCases() + * - Test with UUID that is in the database + * - Test with UUID that is not in the database + * - Test with null UUID + * bulkInsertCases(List cases) + * - Test on a list of cases larger than the bulk insert threshold. + * - Test on a null list + */ + public void testCases() { + final String caseAname = "caseA"; + final String caseAuuid = "caseA_uuid"; + CorrelationCase caseA; + CorrelationCase caseB; + + // Test creating a case with valid name and uuid + try { + caseA = new CorrelationCase(caseAuuid, caseAname); + caseA = EamDb.getInstance().newCase(caseA); + assertTrue("Failed to create case", caseA != null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test null uuid + try { + CorrelationCase tempCase = new CorrelationCase(null, "nullUuidCase"); + tempCase = EamDb.getInstance().newCase(tempCase); + Assert.fail("newCase did not throw expected exception from null uuid"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test null name + try { + CorrelationCase tempCase = new CorrelationCase("nullCaseUuid", null); + tempCase = EamDb.getInstance().newCase(tempCase); + Assert.fail("newCase did not throw expected exception from null name"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test creating a case with an already used UUID + // This should just return the existing case object. Check that the total + // number of cases does not increase. + try { + int nCases = EamDb.getInstance().getCases().size(); + CorrelationCase tempCase = new CorrelationCase(caseAuuid, "newCaseWithSameUUID"); + tempCase = EamDb.getInstance().newCase(tempCase); + assertTrue("newCase returned null for existing UUID", tempCase != null); + assertTrue("newCase created a new case for an already existing UUID", nCases == EamDb.getInstance().getCases().size()); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test creating a case from an Autopsy case + // The case may already be in the database - the result is the same either way + try { + caseB = EamDb.getInstance().newCase(Case.getCurrentCase()); + assertTrue("Failed to create correlation case from Autopsy case", caseB != null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test null Autopsy case + try { + Case nullCase = null; + CorrelationCase tempCase = EamDb.getInstance().newCase(nullCase); + Assert.fail("newCase did not throw expected exception from null case"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test update case + // Will update the fields of an existing case object, save it, and then + // pull a new copy out of the database + try { + assertTrue(caseA != null); + String caseNumber = "12-34-56"; + String creationDate = "01/12/2018"; + String displayName = "Test Case"; + String examinerEmail = "john@sample.com"; + String examinerName = "John Doe"; + String examinerPhone = "123-555-4567"; + String notes = "Notes"; + + caseA.setCaseNumber(caseNumber); + caseA.setCreationDate(creationDate); + caseA.setDisplayName(displayName); + caseA.setExaminerEmail(examinerEmail); + caseA.setExaminerName(examinerName); + caseA.setExaminerPhone(examinerPhone); + caseA.setNotes(notes); + caseA.setOrg(org1); + + EamDb.getInstance().updateCase(caseA); + + // Retrievex a new copy of the case from the database to check that the + // fields were properly updated + CorrelationCase updatedCase = EamDb.getInstance().getCaseByUUID(caseA.getCaseUUID()); + + assertTrue("updateCase failed to update case number", caseNumber.equals(updatedCase.getCaseNumber())); + assertTrue("updateCase failed to update creation date", creationDate.equals(updatedCase.getCreationDate())); + assertTrue("updateCase failed to update display name", displayName.equals(updatedCase.getDisplayName())); + assertTrue("updateCase failed to update examiner email", examinerEmail.equals(updatedCase.getExaminerEmail())); + assertTrue("updateCase failed to update examiner name", examinerName.equals(updatedCase.getExaminerName())); + assertTrue("updateCase failed to update examiner phone number", examinerPhone.equals(updatedCase.getExaminerPhone())); + assertTrue("updateCase failed to update notes", notes.equals(updatedCase.getNotes())); + assertTrue("updateCase failed to update org (org is null)", updatedCase.getOrg() != null); + assertTrue("updateCase failed to update org (org ID is wrong)", org1.getOrgID() == updatedCase.getOrg().getOrgID()); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test update case with null case + try { + EamDb.getInstance().updateCase(null); + Assert.fail("updateCase did not throw expected exception from null case"); + } catch (EamDbException ex) { + // This is the expected behavior + } - // } - + // Test getting a case from an Autopsy case + try { + CorrelationCase tempCase = EamDb.getInstance().getCase(Case.getCurrentCase()); + assertTrue("getCase returned null for current Autopsy case", tempCase != null); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting a case by UUID + try { + CorrelationCase tempCase = EamDb.getInstance().getCaseByUUID(caseAuuid); + assertTrue("Failed to get case by UUID", tempCase != null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting a case with a non-existent UUID + try { + CorrelationCase tempCase = EamDb.getInstance().getCaseByUUID("badUUID"); + assertTrue("getCaseByUUID returned non-null case for non-existent UUID", tempCase == null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting a case with null UUID + try { + CorrelationCase tempCase = EamDb.getInstance().getCaseByUUID(null); + assertTrue("getCaseByUUID returned non-null case for null UUID", tempCase == null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting the list of cases + // The test is to make sure the three cases we know are in the database are in the list + try { + List caseList = EamDb.getInstance().getCases(); + List uuidList + = caseList.stream().map(c -> c.getCaseUUID()).collect(Collectors.toList()); + assertTrue("getCases is missing data for existing cases", uuidList.contains(case1.getCaseUUID()) + && uuidList.contains(case2.getCaseUUID()) && (uuidList.contains(caseA.getCaseUUID())) + && uuidList.contains(caseB.getCaseUUID())); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test bulk case insert + try { + // Create a list of correlation cases. Make enough that the bulk threshold should be hit once. + List cases = new ArrayList<>(); + String bulkTestUuid = "bulkTestUUID_"; + String bulkTestName = "bulkTestName_"; + for (int i = 0; i < dbSettingsSqlite.getBulkThreshold() * 1.5; i++) { + String name = bulkTestUuid + String.valueOf(i); + String uuid = bulkTestName + String.valueOf(i); + cases.add(new CorrelationCase(uuid, name)); + } + + // Get the current case count + int nCases = EamDb.getInstance().getCases().size(); + + // Insert the big list of cases + EamDb.getInstance().bulkInsertCases(cases); + + // Check that the case count is what is expected + assertTrue("bulkInsertCases did not insert the expected number of cases", nCases + cases.size() == EamDb.getInstance().getCases().size()); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test bulk case insert with null list + try { + EamDb.getInstance().bulkInsertCases(null); + Assert.fail("bulkInsertCases did not throw expected exception from null list"); + } catch (EamDbException ex) { + // This is the expected behavior + } + } + + /** + * Test method for the three methods related to the db_info table + * newDbInfo(String name, String value) tests: - Test valid data - Test null + * name - Test null value getDbInfo(String name) - Test getting value for + * existing name - Test getting value for non-existing name - Test getting + * value for null name updateDbInfo(String name, String value) - Test + * updating existing name to valid new value - Test updating existing name + * to null value - Test updating null name - Test updating non-existing name + * to new value + */ + public void testDbInfo() { + final String name1 = "testName1"; + final String name2 = "testName2"; + final String name3 = "testName3"; + final String value1 = "testValue1"; + final String value2 = "testValue2"; + + // Test setting a valid value in DbInfo + try { + EamDb.getInstance().newDbInfo(name1, value1); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test null name + try { + EamDb.getInstance().newDbInfo(null, value1); + Assert.fail("newDbInfo did not throw expected exception from null name"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test null value + try { + EamDb.getInstance().newDbInfo(name2, null); + Assert.fail("newDbInfo did not throw expected exception from null value"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Try getting the dbInfo entry that should exist + try { + String tempVal = EamDb.getInstance().getDbInfo(name1); + assertTrue("dbInfo value for name1 does not match", value1.equals(tempVal)); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Try getting the dbInfo entry that should not exist + try { + String tempVal = EamDb.getInstance().getDbInfo(name3); + assertTrue("dbInfo value is unexpectedly non-null given non-existent name", tempVal == null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Try getting dbInfo for a null value + try { + String tempVal = EamDb.getInstance().getDbInfo(null); + assertTrue("dbInfo value is unexpectedly non-null given null name", tempVal == null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Try updating an existing value to a valid new value + try { + EamDb.getInstance().updateDbInfo(name1, value2); + assertTrue("dbInfo value failed to update to expected value", value2.equals(EamDb.getInstance().getDbInfo(name1))); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Try updating an existing value to null + try { + EamDb.getInstance().updateDbInfo(name1, null); + Assert.fail("updateDbInfo did not throw expected exception from null value"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Try updating a null name + // This seems like SQLite would throw an exception, but it does not + try { + EamDb.getInstance().updateDbInfo(null, value1); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Try updating the value for a non-existant name + try { + EamDb.getInstance().updateDbInfo(name1, null); + Assert.fail("updateDbInfo did not throw expected exception from non-existent name"); + } catch (EamDbException ex) { + // This is the expected behavior + } + } + } From 2dfa6a25f03f237db606c4647fe8136c764a7d75 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 29 Jan 2018 11:50:40 -0500 Subject: [PATCH 22/52] Wrote data sources tests --- .../datamodel/AbstractSqlEamDb.java | 4 + .../datamodel/SqliteEamDb.java | 2 + .../datamodel/CentralRepoDatamodelTest.java | 163 +++++++++++++++--- 3 files changed, 144 insertions(+), 25 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index c5b9af62a6..07937128c1 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -448,6 +448,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public CorrelationDataSource getDataSource(CorrelationCase correlationCase, String dataSourceDeviceId) throws EamDbException { + if(correlationCase == null) { + throw new EamDbException("CorrelationCase argument is null"); + } + Connection conn = connect(); CorrelationDataSource eamDataSourceResult = null; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index 13c4fb00a7..d9d1ea2fa3 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -22,6 +22,7 @@ import java.io.File; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; +import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -165,6 +166,7 @@ public class SqliteEamDb extends AbstractSqlEamDb { connectionPool.setMaxIdle(-1); connectionPool.setMaxWaitMillis(1000); connectionPool.setValidationQuery(dbSettings.getValidationQuery()); + connectionPool.setConnectionInitSqls(Arrays.asList("PRAGMA foreign_keys = ON")); } /** diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 489f651e23..5d0237376f 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -153,35 +153,148 @@ public class CentralRepoDatamodelTest extends TestCase { FileUtils.deleteDirectory(testDirectory.toFile()); } catch (EamDbException | CaseActionException | IOException ex) { - //} catch (EamDbException | CaseActionException ex) { + //} catch (EamDbException | CaseActionException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } assertFalse("Error deleting test directory " + testDirectory.toString(), testDirectory.toFile().exists()); } + public void testDataSources() { + final String dataSourceAname = "dataSourceA"; + final String dataSourceAid = "dataSourceA_deviceID"; + CorrelationDataSource dataSourceA; + CorrelationDataSource dataSourceB; + + // Test creating a data source with valid case, name, and ID + try { + dataSourceA = new CorrelationDataSource(case2.getID(), dataSourceAid, dataSourceAname); + EamDb.getInstance().newDataSource(dataSourceA); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test creating a data source with the same case, name, and ID + try { + CorrelationDataSource temp = new CorrelationDataSource(case2.getID(), dataSourceAid, dataSourceAname); + EamDb.getInstance().newDataSource(temp); + Assert.fail("newDataSource did not throw exception from duplicate data source"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test creating a data source with the same name and ID but different case + try { + dataSourceB = new CorrelationDataSource(case1.getID(), dataSourceAid, dataSourceAname); + EamDb.getInstance().newDataSource(dataSourceB); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test creating a data source with an invalid case ID + try { + CorrelationDataSource temp = new CorrelationDataSource(5000, "tempID", "tempName"); + EamDb.getInstance().newDataSource(temp); + Assert.fail("newDataSource did not throw exception from invalid case ID"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test creating a data source with null device ID + try { + CorrelationDataSource temp = new CorrelationDataSource(case2.getID(), null, "tempName"); + EamDb.getInstance().newDataSource(temp); + Assert.fail("newDataSource did not throw exception from null device ID"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test creating a data source with null device ID + try { + CorrelationDataSource temp = new CorrelationDataSource(case2.getID(), "tempID", null); + EamDb.getInstance().newDataSource(temp); + Assert.fail("newDataSource did not throw exception from null name"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting a data source with valid case and ID + try { + CorrelationDataSource temp = EamDb.getInstance().getDataSource(case2, dataSourceAid); + assertTrue("Failed to get data source", temp != null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting a data source with non-existent ID + try { + CorrelationDataSource temp = EamDb.getInstance().getDataSource(case2, "badID"); + assertTrue("getDataSource returned non-null value for non-existent data source", temp == null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting a data source with a null case + try { + CorrelationDataSource temp = EamDb.getInstance().getDataSource(null, dataSourceAid); + Assert.fail("getDataSource did not throw exception from null case"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting a data source with null ID + try { + CorrelationDataSource temp = EamDb.getInstance().getDataSource(case2, null); + assertTrue("getDataSource returned non-null value for null data source", temp == null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting the list of data sources + // There should be three data sources, and we'll check for the expected device IDs + try { + List dataSources = EamDb.getInstance().getDataSources(); + List devIdList + = dataSources.stream().map(c -> c.getDeviceID()).collect(Collectors.toList()); + assertTrue("getDataSources returned unexpected number of data sources", dataSources.size() == 4); + assertTrue("getDataSources is missing expected data sources", + devIdList.contains(dataSourceAid) + && devIdList.contains(dataSource1fromCase1.getDeviceID()) + && devIdList.contains(dataSource2fromCase1.getDeviceID())); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test the data source count + try { + assertTrue("getCountUniqueDataSources returned unexpected number of data sources", + EamDb.getInstance().getCountUniqueDataSources() == 4); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + /** * Test method for the methods related to the cases table - * newCase(CorrelationCase eamCase) tests: - * - Test valid data - * - Test null UUID - * - Test null case name - * - Test repeated UUID - * newCase(Case autopsyCase) tests: - * - Test valid data - * - Test null autopsyCase - * updateCase(CorrelationCase eamCase) tests: - * - Test with valid data, checking all fields - * - Test null eamCase - * getCase(Case autopsyCase) tests: - * - Test ?? - * getCaseByUUID(String caseUUID) getCases() - * - Test with UUID that is in the database - * - Test with UUID that is not in the database - * - Test with null UUID - * bulkInsertCases(List cases) - * - Test on a list of cases larger than the bulk insert threshold. - * - Test on a null list + * newCase(CorrelationCase eamCase) tests: - Test valid data - Test null + * UUID - Test null case name - Test repeated UUID newCase(Case autopsyCase) + * tests: - Test valid data - Test null autopsyCase + * updateCase(CorrelationCase eamCase) tests: - Test with valid data, + * checking all fields - Test null eamCase getCase(Case autopsyCase) tests: + * - Test with current Autopsy case getCaseByUUID(String caseUUID) + * getCases() - Test with UUID that is in the database - Test with UUID that + * is not in the database - Test with null UUID + * bulkInsertCases(List cases) - Test on a list of cases + * larger than the bulk insert threshold. - Test on a null list */ public void testCases() { final String caseAname = "caseA"; @@ -301,15 +414,15 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting a case from an Autopsy case try { CorrelationCase tempCase = EamDb.getInstance().getCase(Case.getCurrentCase()); assertTrue("getCase returned null for current Autopsy case", tempCase != null); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); - } + } // Test getting a case by UUID try { @@ -376,7 +489,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test bulk case insert with null list try { EamDb.getInstance().bulkInsertCases(null); From 36766e2d51de10128aee2e27e7d9682eda51f0dc Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Mon, 29 Jan 2018 14:16:08 -0500 Subject: [PATCH 23/52] 3366: Edit Details button should only be visible when Details tab selected. --- .../sleuthkit/autopsy/casemodule/CaseInformationPanel.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java index b03a17920e..f0f7326222 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java @@ -61,6 +61,11 @@ class CaseInformationPanel extends javax.swing.JPanel { @Override public void stateChanged(ChangeEvent e) { tabbedPane.getSelectedComponent().setSize(tabbedPane.getSelectedComponent().getPreferredSize()); + if (tabbedPane.getSelectedComponent() instanceof CasePropertiesPanel) { + editDetailsButton.setVisible(true); + } else { + editDetailsButton.setVisible(false); + } } }); } From 78cb915b386896d4798dece39b12d3cee26ab0a5 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Mon, 29 Jan 2018 14:17:48 -0500 Subject: [PATCH 24/52] 3366: Update the copyright to current year. --- .../org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java index f0f7326222..2a460d5c46 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); From e502fedd9bc2dffc9b42bc523bf702dfb27c01a4 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 29 Jan 2018 14:40:48 -0500 Subject: [PATCH 25/52] Partway through reference set tests --- .../datamodel/AbstractSqlEamDb.java | 24 +- .../datamodel/CentralRepoDatamodelTest.java | 268 +++++++++++++++++- 2 files changed, 288 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 07937128c1..3003b28a4a 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -1617,6 +1617,18 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException { + if(eamGlobalSet == null){ + throw new EamDbException("EamGlobalSet argument is null"); + } + + if(eamGlobalSet.getFileKnownStatus() == null){ + throw new EamDbException("File known status on the EamGlobalSet is null"); + } + + if(eamGlobalSet.getType() == null){ + throw new EamDbException("Type on the EamGlobalSet is null"); + } + Connection conn = connect(); PreparedStatement preparedStatement1 = null; @@ -1678,8 +1690,11 @@ public abstract class AbstractSqlEamDb implements EamDb { preparedStatement1 = conn.prepareStatement(sql1); preparedStatement1.setInt(1, referenceSetID); resultSet = preparedStatement1.executeQuery(); - resultSet.next(); - return getEamGlobalSetFromResultSet(resultSet); + if(resultSet.next()) { + return getEamGlobalSetFromResultSet(resultSet); + } else { + return null; + } } catch (SQLException ex) { throw new EamDbException("Error getting reference set by id.", ex); // NON-NLS @@ -1701,6 +1716,11 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public List getAllReferenceSets(CorrelationAttribute.Type correlationType) throws EamDbException { + + if(correlationType == null){ + throw new EamDbException("Correlation type is null"); + } + List results = new ArrayList<>(); Connection conn = connect(); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 5d0237376f..f23421fdb9 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -24,6 +24,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.CaseActionException; import org.sleuthkit.autopsy.casemodule.CaseDetails; import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.datamodel.TskData; /** * @@ -150,6 +151,13 @@ public class CentralRepoDatamodelTest extends TestCase { try { EamDb.getInstance().shutdownConnections(); Case.closeCurrentCase(); + + // This seems to help in allowing the Autopsy case to be deleted + try{ + Thread.sleep(2000); + } catch (Exception ex){ + + } FileUtils.deleteDirectory(testDirectory.toFile()); } catch (EamDbException | CaseActionException | IOException ex) { @@ -159,7 +167,263 @@ public class CentralRepoDatamodelTest extends TestCase { } assertFalse("Error deleting test directory " + testDirectory.toString(), testDirectory.toFile().exists()); } - + + /** + * Test method for the methods related to reference sets + */ + public void testReferenceSets() { + String set1name = "referenceSet1"; + String set1version = "1.0"; + EamGlobalSet set1; + int set1id; + String set2name = "referenceSet2"; + EamGlobalSet set2; + int set2id; + EamGlobalSet set3; + int set3id; + + // Store the file type object to save time + CorrelationAttribute.Type fileType; + try{ + fileType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); + assertTrue("In testReferenceSets, getCorrelationTypeById(FILES_TYPE_ID) returned null", fileType != null); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test creating a notable reference set + try { + set1 = new EamGlobalSet(org1.getOrgID(), set1name, set1version, TskData.FileKnown.BAD, false, fileType); + set1id = EamDb.getInstance().newReferenceSet(set1); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test creating a known reference set + try { + set2 = new EamGlobalSet(org2.getOrgID(), set2name, "", TskData.FileKnown.KNOWN, false, fileType); + set2id = EamDb.getInstance().newReferenceSet(set2); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test creating a reference set with the same name and version + try { + EamGlobalSet temp = new EamGlobalSet(org1.getOrgID(), set1name, "1.0", TskData.FileKnown.BAD, false, fileType); + EamDb.getInstance().newReferenceSet(temp); + Assert.fail("newReferenceSet failed to throw exception from duplicate name/version pair"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test creating a reference set with the same name but different version + try { + set3 = new EamGlobalSet(org1.getOrgID(), set1name, "2.0", TskData.FileKnown.BAD, false, fileType); + set3id = EamDb.getInstance().newReferenceSet(set3); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test creating a reference set with invalid org ID + try { + EamGlobalSet temp = new EamGlobalSet(5000, "tempName", "", TskData.FileKnown.BAD, false, fileType); + EamDb.getInstance().newReferenceSet(temp); + Assert.fail("newReferenceSet failed to throw exception from invalid org ID"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test creating a reference set with null name + try { + EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), null, "", TskData.FileKnown.BAD, false, fileType); + EamDb.getInstance().newReferenceSet(temp); + Assert.fail("newReferenceSet failed to throw exception from null name"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test creating a reference set with null version + try { + EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), "tempName", null, TskData.FileKnown.BAD, false, fileType); + EamDb.getInstance().newReferenceSet(temp); + Assert.fail("newReferenceSet failed to throw exception from null version"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test creating a reference set with null file known status + try { + EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), "tempName", "", null, false, fileType); + EamDb.getInstance().newReferenceSet(temp); + Assert.fail("newReferenceSet failed to throw exception from null file known status"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test creating a reference set with null file type + try { + EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), "tempName", "", TskData.FileKnown.BAD, false, null); + EamDb.getInstance().newReferenceSet(temp); + Assert.fail("newReferenceSet failed to throw exception from null file type"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test validation with a valid reference set + try { + assertTrue("referenceSetIsValid returned false for valid reference set", EamDb.getInstance().referenceSetIsValid(set1id, set1name, set1version)); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test validation with an invalid reference set + try { + assertFalse("referenceSetIsValid returned true for invalid reference set", EamDb.getInstance().referenceSetIsValid(5000, set1name, set1version)); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test validation with a null name + try { + assertFalse("referenceSetIsValid returned true with null name", EamDb.getInstance().referenceSetIsValid(set1id, null, set1version)); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test validation with a null version + try { + assertFalse("referenceSetIsValid returned true with null version", EamDb.getInstance().referenceSetIsValid(set1id, set1name, null)); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test existence with a valid reference set + try { + assertTrue("referenceSetExists returned false for valid reference set", EamDb.getInstance().referenceSetExists(set1name, set1version)); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test existence with an invalid reference set + try { + assertFalse("referenceSetExists returned true for invalid reference set", EamDb.getInstance().referenceSetExists(set1name, "5.5")); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test existence with null name + try { + assertFalse("referenceSetExists returned true for null name", EamDb.getInstance().referenceSetExists(null, "1.0")); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test existence with null version + try { + assertFalse("referenceSetExists returned true for null version", EamDb.getInstance().referenceSetExists(set1name, null)); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting global set with valid ID + try { + EamGlobalSet temp = EamDb.getInstance().getReferenceSetByID(set1id); + assertTrue("getReferenceSetByID returned null for valid ID", temp != null); + assertTrue("getReferenceSetByID returned set with incorrect name and/or version", + set1name.equals(temp.getSetName()) && set1version.equals(temp.getVersion())); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting global set with invalid ID + try { + EamGlobalSet temp = EamDb.getInstance().getReferenceSetByID(1234); + assertTrue("getReferenceSetByID returned non-null result for invalid ID", temp == null); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting all file reference sets + try { + List referenceSets = EamDb.getInstance().getAllReferenceSets(fileType); + assertTrue("getAllReferenceSets(FILES) returned unexpected number", referenceSets.size() == 3); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting all email reference sets + try { + List referenceSets = EamDb.getInstance().getAllReferenceSets(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.EMAIL_TYPE_ID)); + assertTrue("getAllReferenceSets(EMAIL) returned unexpected number", referenceSets.isEmpty()); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test null argument to getAllReferenceSets + try { + EamDb.getInstance().getAllReferenceSets(null); + Assert.fail("getAllReferenceSets failed to throw exception from null type argument"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test deleting an existing reference set + // First: create a new reference set, check that it's in the database, and get the number of reference sets + // Second: delete the reference set, check that it is no longer in the database, and the total number of sets decreased by one + try { + EamGlobalSet setToDelete = new EamGlobalSet(org1.getOrgID(), "deleteThis", "deleteThisVersion", TskData.FileKnown.BAD, false, fileType); + int setToDeleteID = EamDb.getInstance().newReferenceSet(setToDelete); + assertTrue("setToDelete wasn't found in database", EamDb.getInstance().referenceSetIsValid(setToDeleteID, setToDelete.getSetName(), setToDelete.getVersion())); + int currentCount = EamDb.getInstance().getAllReferenceSets(fileType).size(); + + + + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + } + + /** + * Test method for the methods related to the data sources table + * newDataSource(CorrelationDataSource eamDataSource) tests: + * - Test with valid data + * - Test with duplicate data + * - Test with duplicate device ID and name but different case + * - Test with invalid case ID + * - Test with null device ID + * - Test with null name + * getDataSource(CorrelationCase correlationCase, String dataSourceDeviceId) tests: + * - Test with valid data + * - Test with non-existent data + * - Test with null correlationCase + * - Test with null device ID + * List getDataSources()tests: + * - Test that the count and device IDs are as expected + * Long getCountUniqueDataSources() tests: + * - Test that the result is as expected + */ public void testDataSources() { final String dataSourceAname = "dataSourceA"; final String dataSourceAid = "dataSourceA_deviceID"; @@ -213,7 +477,7 @@ public class CentralRepoDatamodelTest extends TestCase { // This is the expected behavior } - // Test creating a data source with null device ID + // Test creating a data source with null name try { CorrelationDataSource temp = new CorrelationDataSource(case2.getID(), "tempID", null); EamDb.getInstance().newDataSource(temp); From 338334f62936c2d3ea30979d7076f5b39388d2cc Mon Sep 17 00:00:00 2001 From: Raman Date: Tue, 30 Jan 2018 09:50:25 -0500 Subject: [PATCH 26/52] 3415: Show SQLite table contents Resize columns based on data from top 20 rows --- .../contentviewers/SQLiteTableView.java | 59 +++++++++++++++---- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java index ad1117f0a0..7ca873e13c 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.BorderLayout; +import java.awt.Component; import java.util.List; import java.util.Map; import java.util.Objects; @@ -26,6 +27,8 @@ import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.ScrollPaneConstants; +import javax.swing.SwingWorker; +import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumnModel; import org.netbeans.swing.etable.ETableColumn; import org.netbeans.swing.etable.ETableColumnModel; @@ -70,18 +73,14 @@ class SQLiteTableView extends JPanel implements ExplorerManager.Provider { */ void setupTable(List> tableRows) { - explorerManager.setRootContext(new AbstractNode(Children.create(new SQLiteTableRowFactory(tableRows), true))); - + if (Objects.isNull(tableRows) || tableRows.isEmpty()) { outlineView.setPropertyColumns(); -// return; } else { + // Set up the column names Map row = tableRows.get(0); - - // Get the columns setup with respect to names and sortability String[] propStrings = new String[row.size() * 2]; - int i = 0; for (Map.Entry col : row.entrySet()) { String colName = col.getKey(); @@ -93,19 +92,55 @@ class SQLiteTableView extends JPanel implements ExplorerManager.Provider { outlineView.setPropertyColumns(propStrings); } - // TBD: Set width based on actual data in the top N rows?? - // TBD: Can't seem to get the horizontal scrollbar working - for (int col = 0; col< outline.getModel().getColumnCount(); col++) { - outline.getColumnModel().getColumn(col).setMinWidth(50); - } - // Hide the 'Nodes' column TableColumnModel columnModel = outline.getColumnModel(); ETableColumn column = (ETableColumn) columnModel.getColumn(0); ((ETableColumnModel) columnModel).setColumnHidden(column, true); + // Set the Nodes for the ExplorerManager. + // The Swingworker ensures that setColumnWidths() is called after all nodes have been created. + new SwingWorker() { + @Override + protected Boolean doInBackground() throws Exception { + + explorerManager.setRootContext(new AbstractNode(Children.create(new SQLiteTableRowFactory(tableRows), true))); + return false; + } + + @Override + protected void done() { + super.done(); + + setColumnWidths(); + } + }.execute(); + } + private void setColumnWidths() { + int margin = 4; + int padding = 8; + + // find the maximum width needed to fit the values for the first N rows, at most + final int rows = Math.min(20, outline.getRowCount()); + for (int col = 1; col < outline.getColumnCount(); col++) { + int columnWidthLimit = 500; + int columnWidth = 50; + + for (int row = 0; row < rows; row++) { + TableCellRenderer renderer = outline.getCellRenderer(row, col); + Component comp = outline.prepareRenderer(renderer, row, col); + + columnWidth = Math.max(comp.getPreferredSize().width, columnWidth); + } + + columnWidth += 2 * margin + padding; // add margin and regular padding + columnWidth = Math.min(columnWidth, columnWidthLimit); + outline.getColumnModel().getColumn(col).setPreferredWidth(columnWidth); + } + } + + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always From 196a13ddb37ce453bc9a325143f9681914267366 Mon Sep 17 00:00:00 2001 From: rishwanth Date: Tue, 30 Jan 2018 12:10:55 -0500 Subject: [PATCH 27/52] removed xdock jvm.option for linux and window build --- build.xml | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/build.xml b/build.xml index 4eaa7df1c8..d044f68f06 100644 --- a/build.xml +++ b/build.xml @@ -32,7 +32,10 @@ - + + + + @@ -82,7 +85,13 @@ - + + + + + + + @@ -91,8 +100,17 @@ + - + + + + + + + + + From 1089c1b2052b7da76fcdf79878a82cde3c777641 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Tue, 30 Jan 2018 16:41:40 -0500 Subject: [PATCH 28/52] 3499: List of rulesets to test. --- ruleset.xml | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/ruleset.xml b/ruleset.xml index d4f2f075fc..41e2756faf 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -1,13 +1,38 @@ - + xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd"> - Ruleset used by Autopsy + Ruleset used by Autopsy + + + + + + + + + + + + + + + + + + + + + + + + + + From d80a0a468d9da83c9f62b2274ceed10441586326 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Tue, 30 Jan 2018 16:54:28 -0500 Subject: [PATCH 29/52] 3499: Fix spelling. --- ruleset.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruleset.xml b/ruleset.xml index 41e2756faf..2b4e66b821 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -24,7 +24,7 @@ - + From 23c5e5be62195f448294cb7e25a4b7f2c283ec2c Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 31 Jan 2018 08:48:04 -0500 Subject: [PATCH 30/52] Finished reference set tests --- .../datamodel/AbstractSqlEamDb.java | 3 + .../datamodel/CentralRepoDatamodelTest.java | 489 ++++++++++-------- 2 files changed, 284 insertions(+), 208 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 3003b28a4a..48a7f34a6e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -1541,6 +1541,9 @@ public abstract class AbstractSqlEamDb implements EamDb { public EamOrganization getReferenceSetOrganization(int referenceSetID) throws EamDbException { EamGlobalSet globalSet = getReferenceSetByID(referenceSetID); + if(globalSet == null) { + throw new EamDbException("Reference set with ID " + referenceSetID + " not found"); + } return (getOrganizationByID(globalSet.getOrgID())); } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index f23421fdb9..2aafcf0679 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -71,16 +71,7 @@ public class CentralRepoDatamodelTest extends TestCase { assertTrue("Unable to create test directory", testDirectory.toFile().exists()); // Save the current central repo settings - propertiesMap = ModuleSettings.getConfigSettings(PROPERTIES_FILE); - - // Set up an Autopsy case for testing - try { - Case.createAsCurrentCase(Case.CaseType.SINGLE_USER_CASE, testDirectory.toString(), new CaseDetails("CentralRepoDatamodelTestCase")); - } catch (CaseActionException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - assertTrue("Failed to create test case", testDirectory.toFile().exists()); + propertiesMap = ModuleSettings.getConfigSettings(PROPERTIES_FILE); try { dbSettingsSqlite.setDbName(CR_DB_NAME); @@ -150,14 +141,8 @@ public class CentralRepoDatamodelTest extends TestCase { // Close and delete the test case and central repo db try { EamDb.getInstance().shutdownConnections(); - Case.closeCurrentCase(); - - // This seems to help in allowing the Autopsy case to be deleted - try{ - Thread.sleep(2000); - } catch (Exception ex){ - - } + Case.closeCurrentCase(); // There shouldn't be a case open, but it's fine to call this anyway + FileUtils.deleteDirectory(testDirectory.toFile()); } catch (EamDbException | CaseActionException | IOException ex) { @@ -169,7 +154,40 @@ public class CentralRepoDatamodelTest extends TestCase { } /** - * Test method for the methods related to reference sets + * Test method for the methods related to reference sets (does not include instance testing) + * newReferenceSet(EamGlobalSet eamGlobalSet) tests: + * - Test creating notable reference set + * - Test creating known reference set + * - Test creating duplicate reference set + * - Test creating almost duplicate reference set + * - Test with invalid org ID + * - Test with null name + * - Test with null version + * - Test with null known status + * - Test with null file type + * referenceSetIsValid(int referenceSetID, String referenceSetName, String version) tests: + * - Test on existing reference set + * - Test on invalid reference set + * - Test with null name + * - Test with null version + * referenceSetExists(String referenceSetName, String version) tests: + * - Test on existing reference set + * - Test on invalid reference set + * - Test with null name + * - Test with null version + * getReferenceSetByID(int globalSetID) tests: + * - Test with valid ID + * - Test with invalid ID + * getAllReferenceSets(CorrelationAttribute.Type correlationType) tests: + * - Test getting all file sets + * - Test getting all email sets + * - Test with null type parameter + * deleteReferenceSet(int referenceSetID) tests: + * - Test on valid reference set ID + * - Test on invalid reference set ID + * getReferenceSetOrganization(int referenceSetID) tests: + * - Test on valid reference set ID + * - Test on invalid reference set ID */ public void testReferenceSets() { String set1name = "referenceSet1"; @@ -396,13 +414,44 @@ public class CentralRepoDatamodelTest extends TestCase { assertTrue("setToDelete wasn't found in database", EamDb.getInstance().referenceSetIsValid(setToDeleteID, setToDelete.getSetName(), setToDelete.getVersion())); int currentCount = EamDb.getInstance().getAllReferenceSets(fileType).size(); - + EamDb.getInstance().deleteReferenceSet(setToDeleteID); + assertFalse("Deleted reference set was found in database", EamDb.getInstance().referenceSetIsValid(setToDeleteID, setToDelete.getSetName(), setToDelete.getVersion())); + assertTrue("Unexpected number of reference sets in database after deletion", currentCount - 1 == EamDb.getInstance().getAllReferenceSets(fileType).size()); } catch (EamDbException ex){ Exceptions.printStackTrace(ex); Assert.fail(ex); } + // Test deleting a non-existent reference set + // The expectation is that nothing will happen + try { + int currentCount = EamDb.getInstance().getAllReferenceSets(fileType).size(); + EamDb.getInstance().deleteReferenceSet(1234); + assertTrue("Number of reference sets changed after deleting non-existent set", currentCount == EamDb.getInstance().getAllReferenceSets(fileType).size()); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting reference set organization for valid ID with org set + try { + EamOrganization org = EamDb.getInstance().getReferenceSetOrganization(set1id); + assertTrue("getReferenceSetOrganization returned null for valid set", org != null); + assertTrue("getReferenceSetOrganization returned the incorrect organization", org.getOrgID() == org1.getOrgID()); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting reference set organization for non-existent reference set + try { + EamOrganization org = EamDb.getInstance().getReferenceSetOrganization(4567); + Assert.fail("getReferenceSetOrganization failed to throw exception for invalid reference set ID"); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } } /** @@ -565,201 +614,225 @@ public class CentralRepoDatamodelTest extends TestCase { final String caseAuuid = "caseA_uuid"; CorrelationCase caseA; CorrelationCase caseB; - - // Test creating a case with valid name and uuid + try { - caseA = new CorrelationCase(caseAuuid, caseAname); - caseA = EamDb.getInstance().newCase(caseA); - assertTrue("Failed to create case", caseA != null); - } catch (EamDbException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - return; - } + // Set up an Autopsy case for testing + try { + Case.createAsCurrentCase(Case.CaseType.SINGLE_USER_CASE, testDirectory.toString(), new CaseDetails("CentralRepoDatamodelTestCase")); + } catch (CaseActionException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + assertTrue("Failed to create test case", testDirectory.toFile().exists()); - // Test null uuid - try { - CorrelationCase tempCase = new CorrelationCase(null, "nullUuidCase"); - tempCase = EamDb.getInstance().newCase(tempCase); - Assert.fail("newCase did not throw expected exception from null uuid"); - } catch (EamDbException ex) { - // This is the expected behavior - } - - // Test null name - try { - CorrelationCase tempCase = new CorrelationCase("nullCaseUuid", null); - tempCase = EamDb.getInstance().newCase(tempCase); - Assert.fail("newCase did not throw expected exception from null name"); - } catch (EamDbException ex) { - // This is the expected behavior - } - - // Test creating a case with an already used UUID - // This should just return the existing case object. Check that the total - // number of cases does not increase. - try { - int nCases = EamDb.getInstance().getCases().size(); - CorrelationCase tempCase = new CorrelationCase(caseAuuid, "newCaseWithSameUUID"); - tempCase = EamDb.getInstance().newCase(tempCase); - assertTrue("newCase returned null for existing UUID", tempCase != null); - assertTrue("newCase created a new case for an already existing UUID", nCases == EamDb.getInstance().getCases().size()); - } catch (EamDbException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - - // Test creating a case from an Autopsy case - // The case may already be in the database - the result is the same either way - try { - caseB = EamDb.getInstance().newCase(Case.getCurrentCase()); - assertTrue("Failed to create correlation case from Autopsy case", caseB != null); - } catch (EamDbException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - return; - } - - // Test null Autopsy case - try { - Case nullCase = null; - CorrelationCase tempCase = EamDb.getInstance().newCase(nullCase); - Assert.fail("newCase did not throw expected exception from null case"); - } catch (EamDbException ex) { - // This is the expected behavior - } - - // Test update case - // Will update the fields of an existing case object, save it, and then - // pull a new copy out of the database - try { - assertTrue(caseA != null); - String caseNumber = "12-34-56"; - String creationDate = "01/12/2018"; - String displayName = "Test Case"; - String examinerEmail = "john@sample.com"; - String examinerName = "John Doe"; - String examinerPhone = "123-555-4567"; - String notes = "Notes"; - - caseA.setCaseNumber(caseNumber); - caseA.setCreationDate(creationDate); - caseA.setDisplayName(displayName); - caseA.setExaminerEmail(examinerEmail); - caseA.setExaminerName(examinerName); - caseA.setExaminerPhone(examinerPhone); - caseA.setNotes(notes); - caseA.setOrg(org1); - - EamDb.getInstance().updateCase(caseA); - - // Retrievex a new copy of the case from the database to check that the - // fields were properly updated - CorrelationCase updatedCase = EamDb.getInstance().getCaseByUUID(caseA.getCaseUUID()); - - assertTrue("updateCase failed to update case number", caseNumber.equals(updatedCase.getCaseNumber())); - assertTrue("updateCase failed to update creation date", creationDate.equals(updatedCase.getCreationDate())); - assertTrue("updateCase failed to update display name", displayName.equals(updatedCase.getDisplayName())); - assertTrue("updateCase failed to update examiner email", examinerEmail.equals(updatedCase.getExaminerEmail())); - assertTrue("updateCase failed to update examiner name", examinerName.equals(updatedCase.getExaminerName())); - assertTrue("updateCase failed to update examiner phone number", examinerPhone.equals(updatedCase.getExaminerPhone())); - assertTrue("updateCase failed to update notes", notes.equals(updatedCase.getNotes())); - assertTrue("updateCase failed to update org (org is null)", updatedCase.getOrg() != null); - assertTrue("updateCase failed to update org (org ID is wrong)", org1.getOrgID() == updatedCase.getOrg().getOrgID()); - } catch (EamDbException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - - // Test update case with null case - try { - EamDb.getInstance().updateCase(null); - Assert.fail("updateCase did not throw expected exception from null case"); - } catch (EamDbException ex) { - // This is the expected behavior - } - - // Test getting a case from an Autopsy case - try { - CorrelationCase tempCase = EamDb.getInstance().getCase(Case.getCurrentCase()); - assertTrue("getCase returned null for current Autopsy case", tempCase != null); - } catch (EamDbException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - - // Test getting a case by UUID - try { - CorrelationCase tempCase = EamDb.getInstance().getCaseByUUID(caseAuuid); - assertTrue("Failed to get case by UUID", tempCase != null); - } catch (EamDbException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - - // Test getting a case with a non-existent UUID - try { - CorrelationCase tempCase = EamDb.getInstance().getCaseByUUID("badUUID"); - assertTrue("getCaseByUUID returned non-null case for non-existent UUID", tempCase == null); - } catch (EamDbException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - - // Test getting a case with null UUID - try { - CorrelationCase tempCase = EamDb.getInstance().getCaseByUUID(null); - assertTrue("getCaseByUUID returned non-null case for null UUID", tempCase == null); - } catch (EamDbException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - - // Test getting the list of cases - // The test is to make sure the three cases we know are in the database are in the list - try { - List caseList = EamDb.getInstance().getCases(); - List uuidList - = caseList.stream().map(c -> c.getCaseUUID()).collect(Collectors.toList()); - assertTrue("getCases is missing data for existing cases", uuidList.contains(case1.getCaseUUID()) - && uuidList.contains(case2.getCaseUUID()) && (uuidList.contains(caseA.getCaseUUID())) - && uuidList.contains(caseB.getCaseUUID())); - } catch (EamDbException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } - - // Test bulk case insert - try { - // Create a list of correlation cases. Make enough that the bulk threshold should be hit once. - List cases = new ArrayList<>(); - String bulkTestUuid = "bulkTestUUID_"; - String bulkTestName = "bulkTestName_"; - for (int i = 0; i < dbSettingsSqlite.getBulkThreshold() * 1.5; i++) { - String name = bulkTestUuid + String.valueOf(i); - String uuid = bulkTestName + String.valueOf(i); - cases.add(new CorrelationCase(uuid, name)); + // Test creating a case with valid name and uuid + try { + caseA = new CorrelationCase(caseAuuid, caseAname); + caseA = EamDb.getInstance().newCase(caseA); + assertTrue("Failed to create case", caseA != null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; } - // Get the current case count - int nCases = EamDb.getInstance().getCases().size(); + // Test null uuid + try { + CorrelationCase tempCase = new CorrelationCase(null, "nullUuidCase"); + tempCase = EamDb.getInstance().newCase(tempCase); + Assert.fail("newCase did not throw expected exception from null uuid"); + } catch (EamDbException ex) { + // This is the expected behavior + } - // Insert the big list of cases - EamDb.getInstance().bulkInsertCases(cases); + // Test null name + try { + CorrelationCase tempCase = new CorrelationCase("nullCaseUuid", null); + tempCase = EamDb.getInstance().newCase(tempCase); + Assert.fail("newCase did not throw expected exception from null name"); + } catch (EamDbException ex) { + // This is the expected behavior + } - // Check that the case count is what is expected - assertTrue("bulkInsertCases did not insert the expected number of cases", nCases + cases.size() == EamDb.getInstance().getCases().size()); - } catch (EamDbException ex) { - Exceptions.printStackTrace(ex); - Assert.fail(ex); - } + // Test creating a case with an already used UUID + // This should just return the existing case object. Check that the total + // number of cases does not increase. + try { + int nCases = EamDb.getInstance().getCases().size(); + CorrelationCase tempCase = new CorrelationCase(caseAuuid, "newCaseWithSameUUID"); + tempCase = EamDb.getInstance().newCase(tempCase); + assertTrue("newCase returned null for existing UUID", tempCase != null); + assertTrue("newCase created a new case for an already existing UUID", nCases == EamDb.getInstance().getCases().size()); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } - // Test bulk case insert with null list - try { - EamDb.getInstance().bulkInsertCases(null); - Assert.fail("bulkInsertCases did not throw expected exception from null list"); - } catch (EamDbException ex) { - // This is the expected behavior + // Test creating a case from an Autopsy case + // The case may already be in the database - the result is the same either way + try { + caseB = EamDb.getInstance().newCase(Case.getCurrentCase()); + assertTrue("Failed to create correlation case from Autopsy case", caseB != null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test null Autopsy case + try { + Case nullCase = null; + CorrelationCase tempCase = EamDb.getInstance().newCase(nullCase); + Assert.fail("newCase did not throw expected exception from null case"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test update case + // Will update the fields of an existing case object, save it, and then + // pull a new copy out of the database + try { + assertTrue(caseA != null); + String caseNumber = "12-34-56"; + String creationDate = "01/12/2018"; + String displayName = "Test Case"; + String examinerEmail = "john@sample.com"; + String examinerName = "John Doe"; + String examinerPhone = "123-555-4567"; + String notes = "Notes"; + + caseA.setCaseNumber(caseNumber); + caseA.setCreationDate(creationDate); + caseA.setDisplayName(displayName); + caseA.setExaminerEmail(examinerEmail); + caseA.setExaminerName(examinerName); + caseA.setExaminerPhone(examinerPhone); + caseA.setNotes(notes); + caseA.setOrg(org1); + + EamDb.getInstance().updateCase(caseA); + + // Retrievex a new copy of the case from the database to check that the + // fields were properly updated + CorrelationCase updatedCase = EamDb.getInstance().getCaseByUUID(caseA.getCaseUUID()); + + assertTrue("updateCase failed to update case number", caseNumber.equals(updatedCase.getCaseNumber())); + assertTrue("updateCase failed to update creation date", creationDate.equals(updatedCase.getCreationDate())); + assertTrue("updateCase failed to update display name", displayName.equals(updatedCase.getDisplayName())); + assertTrue("updateCase failed to update examiner email", examinerEmail.equals(updatedCase.getExaminerEmail())); + assertTrue("updateCase failed to update examiner name", examinerName.equals(updatedCase.getExaminerName())); + assertTrue("updateCase failed to update examiner phone number", examinerPhone.equals(updatedCase.getExaminerPhone())); + assertTrue("updateCase failed to update notes", notes.equals(updatedCase.getNotes())); + assertTrue("updateCase failed to update org (org is null)", updatedCase.getOrg() != null); + assertTrue("updateCase failed to update org (org ID is wrong)", org1.getOrgID() == updatedCase.getOrg().getOrgID()); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test update case with null case + try { + EamDb.getInstance().updateCase(null); + Assert.fail("updateCase did not throw expected exception from null case"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting a case from an Autopsy case + try { + CorrelationCase tempCase = EamDb.getInstance().getCase(Case.getCurrentCase()); + assertTrue("getCase returned null for current Autopsy case", tempCase != null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting a case by UUID + try { + CorrelationCase tempCase = EamDb.getInstance().getCaseByUUID(caseAuuid); + assertTrue("Failed to get case by UUID", tempCase != null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting a case with a non-existent UUID + try { + CorrelationCase tempCase = EamDb.getInstance().getCaseByUUID("badUUID"); + assertTrue("getCaseByUUID returned non-null case for non-existent UUID", tempCase == null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting a case with null UUID + try { + CorrelationCase tempCase = EamDb.getInstance().getCaseByUUID(null); + assertTrue("getCaseByUUID returned non-null case for null UUID", tempCase == null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting the list of cases + // The test is to make sure the three cases we know are in the database are in the list + try { + List caseList = EamDb.getInstance().getCases(); + List uuidList + = caseList.stream().map(c -> c.getCaseUUID()).collect(Collectors.toList()); + assertTrue("getCases is missing data for existing cases", uuidList.contains(case1.getCaseUUID()) + && uuidList.contains(case2.getCaseUUID()) && (uuidList.contains(caseA.getCaseUUID())) + && uuidList.contains(caseB.getCaseUUID())); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test bulk case insert + try { + // Create a list of correlation cases. Make enough that the bulk threshold should be hit once. + List cases = new ArrayList<>(); + String bulkTestUuid = "bulkTestUUID_"; + String bulkTestName = "bulkTestName_"; + for (int i = 0; i < dbSettingsSqlite.getBulkThreshold() * 1.5; i++) { + String name = bulkTestUuid + String.valueOf(i); + String uuid = bulkTestName + String.valueOf(i); + cases.add(new CorrelationCase(uuid, name)); + } + + // Get the current case count + int nCases = EamDb.getInstance().getCases().size(); + + // Insert the big list of cases + EamDb.getInstance().bulkInsertCases(cases); + + // Check that the case count is what is expected + assertTrue("bulkInsertCases did not insert the expected number of cases", nCases + cases.size() == EamDb.getInstance().getCases().size()); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test bulk case insert with null list + try { + EamDb.getInstance().bulkInsertCases(null); + Assert.fail("bulkInsertCases did not throw expected exception from null list"); + } catch (EamDbException ex) { + // This is the expected behavior + } + } finally { + try { + Case.closeCurrentCase(); + // This seems to help in allowing the Autopsy case to be deleted + try{ + Thread.sleep(2000); + } catch (Exception ex){ + + } + } catch (CaseActionException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } } } From 6e35b3d2142cff098615630e2e725c8b8ca2c69f Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 31 Jan 2018 13:42:35 -0500 Subject: [PATCH 31/52] Finished reference set testing --- .../datamodel/AbstractSqlEamDb.java | 29 +- .../datamodel/EamGlobalFileInstance.java | 15 +- .../modules/hashdatabase/HashDbManager.java | 13 +- .../datamodel/CentralRepoDatamodelTest.java | 396 +++++++++++++++++- 4 files changed, 426 insertions(+), 27 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 48a7f34a6e..e3b61fbece 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -1394,6 +1394,9 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public boolean isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) throws EamDbException { + if(aType == null) { + throw new EamDbException("null correlation type"); + } // TEMP: Only support file correlation type if (aType.getId() != CorrelationAttribute.FILES_TYPE_ID) { @@ -1758,6 +1761,13 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public void addReferenceInstance(EamGlobalFileInstance eamGlobalFileInstance, CorrelationAttribute.Type correlationType) throws EamDbException { + if(eamGlobalFileInstance.getKnownStatus() == null){ + throw new EamDbException("known status of EamGlobalFileInstance is null"); + } + if(correlationType == null){ + throw new EamDbException("Correlation type is null"); + } + Connection conn = connect(); PreparedStatement preparedStatement = null; @@ -1821,6 +1831,13 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public void bulkInsertReferenceTypeEntries(Set globalInstances, CorrelationAttribute.Type contentType) throws EamDbException { + if(contentType == null) { + throw new EamDbException("Null correlation type"); + } + if(globalInstances == null) { + throw new EamDbException("Null set of EamGlobalFileInstance"); + } + Connection conn = connect(); PreparedStatement bulkPs = null; @@ -1834,6 +1851,10 @@ public abstract class AbstractSqlEamDb implements EamDb { bulkPs = conn.prepareStatement(String.format(sql, EamDbUtil.correlationTypeToReferenceTableName(contentType))); for (EamGlobalFileInstance globalInstance : globalInstances) { + if(globalInstance.getKnownStatus() == null){ + throw new EamDbException("EamGlobalFileInstance with value " + globalInstance.getMD5Hash() + " has null known status"); + } + bulkPs.setInt(1, globalInstance.getGlobalSetID()); bulkPs.setString(2, globalInstance.getMD5Hash()); bulkPs.setByte(3, globalInstance.getKnownStatus().getFileKnownValue()); @@ -1843,7 +1864,7 @@ public abstract class AbstractSqlEamDb implements EamDb { bulkPs.executeBatch(); conn.commit(); - } catch (SQLException ex) { + } catch (SQLException | EamDbException ex) { try { conn.rollback(); } catch (SQLException ex2) { @@ -1868,6 +1889,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public List getReferenceInstancesByTypeValue(CorrelationAttribute.Type aType, String aValue) throws EamDbException { + if(aType == null) { + throw new EamDbException("correlation type is null"); + } + Connection conn = connect(); List globalFileInstances = new ArrayList<>(); @@ -2251,7 +2276,7 @@ public abstract class AbstractSqlEamDb implements EamDb { return eamGlobalSet; } - private EamGlobalFileInstance getEamGlobalFileInstanceFromResultSet(ResultSet resultSet) throws SQLException { + private EamGlobalFileInstance getEamGlobalFileInstanceFromResultSet(ResultSet resultSet) throws SQLException, EamDbException { if (null == resultSet) { return null; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java index 87d974f353..3c538e67c8 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java @@ -36,7 +36,7 @@ public class EamGlobalFileInstance { int globalSetID, String MD5Hash, TskData.FileKnown knownStatus, - String comment) { + String comment) throws EamDbException { this(-1, globalSetID, MD5Hash, knownStatus, comment); } @@ -45,7 +45,13 @@ public class EamGlobalFileInstance { int globalSetID, String MD5Hash, TskData.FileKnown knownStatus, - String comment) { + String comment) throws EamDbException { + if(MD5Hash == null){ + throw new EamDbException("null MD5 hash"); + } + if(knownStatus == null){ + throw new EamDbException("null known status"); + } this.instanceID = instanceID; this.globalSetID = globalSetID; // Normalize hashes by lower casing @@ -111,7 +117,10 @@ public class EamGlobalFileInstance { /** * @param MD5Hash the MD5Hash to set */ - public void setMD5Hash(String MD5Hash) { + public void setMD5Hash(String MD5Hash) throws EamDbException { + if(MD5Hash == null){ + throw new EamDbException("null MD5 hash"); + } // Normalize hashes by lower casing this.MD5Hash = MD5Hash.toLowerCase(); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index c032bdc83e..09aec0256f 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -1232,9 +1232,10 @@ public class HashDbManager implements PropertyChangeListener { } else { type = TskData.FileKnown.KNOWN; } - EamGlobalFileInstance fileInstance = new EamGlobalFileInstance(referenceSetID, file.getMd5Hash(), - type, comment); + try{ + EamGlobalFileInstance fileInstance = new EamGlobalFileInstance(referenceSetID, file.getMd5Hash(), + type, comment); EamDb.getInstance().addReferenceInstance(fileInstance,EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID)); } catch (EamDbException ex){ throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex); @@ -1259,8 +1260,12 @@ public class HashDbManager implements PropertyChangeListener { type = TskData.FileKnown.BAD; } else { type = TskData.FileKnown.KNOWN; - } - globalFileInstances.add(new EamGlobalFileInstance(referenceSetID, hashEntry.getMd5Hash(), type, hashEntry.getComment())); + } + try { + globalFileInstances.add(new EamGlobalFileInstance(referenceSetID, hashEntry.getMd5Hash(), type, hashEntry.getComment())); + } catch (EamDbException ex){ + throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex); + } } try{ diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 2aafcf0679..cd0a0322a4 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -9,11 +9,12 @@ import java.io.IOException; import java.util.Map; import java.util.List; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Set; +import java.util.HashSet; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Collectors; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; import junit.framework.Test; import junit.framework.TestCase; import org.apache.commons.io.FileUtils; @@ -25,6 +26,8 @@ import org.sleuthkit.autopsy.casemodule.CaseActionException; import org.sleuthkit.autopsy.casemodule.CaseDetails; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.datamodel.TskData; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; /** * @@ -33,7 +36,8 @@ public class CentralRepoDatamodelTest extends TestCase { private static final String PROPERTIES_FILE = "CentralRepository"; private static final String CR_DB_NAME = "testcentralrepo.db"; - private static final Path testDirectory = Paths.get(System.getProperty("java.io.tmpdir"), "CentralRepoDatamodelTest"); + //private static final Path testDirectory = Paths.get(System.getProperty("java.io.tmpdir"), "CentralRepoDatamodelTest"); + private static final Path testDirectory = Paths.get("C:", "Work", "CRDatamodelTest"); SqliteEamDbSettings dbSettingsSqlite; private CorrelationCase case1; @@ -42,6 +46,7 @@ public class CentralRepoDatamodelTest extends TestCase { private CorrelationDataSource dataSource2fromCase1; private EamOrganization org1; private EamOrganization org2; + CorrelationAttribute.Type fileType; private Map propertiesMap = null; @@ -124,6 +129,10 @@ public class CentralRepoDatamodelTest extends TestCase { org2 = new EamOrganization("org2"); org2.setOrgID((int) EamDb.getInstance().newOrganization(org2)); + + // Store the file type object for later use + fileType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); + assertTrue("getCorrelationTypeById(FILES_TYPE_ID) returned null", fileType != null); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); @@ -141,20 +150,382 @@ public class CentralRepoDatamodelTest extends TestCase { // Close and delete the test case and central repo db try { EamDb.getInstance().shutdownConnections(); - Case.closeCurrentCase(); // There shouldn't be a case open, but it's fine to call this anyway FileUtils.deleteDirectory(testDirectory.toFile()); - } catch (EamDbException | CaseActionException | IOException ex) { - //} catch (EamDbException | CaseActionException ex) { + } catch (EamDbException | IOException ex) { + // } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } assertFalse("Error deleting test directory " + testDirectory.toString(), testDirectory.toFile().exists()); } + /** + * Tests for adding / retrieving reference instances + * Only the files type is currently implemented + * addReferenceInstance(EamGlobalFileInstance eamGlobalFileInstance, CorrelationAttribute.Type correlationType) tests: + * - Test adding multiple valid entries + * - Test invalid reference set ID + * - Test null hash (EamGlobalFileInstance constructor) + * - Test null known status (EamGlobalFileInstance constructor) + * - Test null correlation type + * bulkInsertReferenceTypeEntries(Set globalInstances, CorrelationAttribute.Type contentType) tests: + * - Test with large valid list + * - Test with null list + * - Test with invalid reference set ID + * - Test with null correlation type + * getReferenceInstancesByTypeValue(CorrelationAttribute.Type aType, String aValue) tests: + * - Test with valid entries + * - Test with non-existent value + * - Test with invalid type + * - Test with null type + * - Test with null value + * isFileHashInReferenceSet(String hash, int referenceSetID)tests: + * - Test existing hash/ID + * - Test non-existent (but valid) hash/ID + * - Test invalid ID + * - Test null hash + * isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) tests: + * - Test existing value/ID + * - Test non-existent (but valid) value/ID + * - Test invalid ID + * - Test null value + * - Test invalid type ID + * isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) tests: + * - Test notable value + * - Test known value + * - Test non-existent value + * - Test null value + * - Test null type + * - Test invalid type + */ + public void testReferenceSetInstances(){ + + // After the two initial testing blocks, the reference sets should contain: + // notableSet1 - notableHash1, inAllSetsHash + // notableSet2 - inAllSetsHash + // knownSet1 - knownHash1, inAllSetsHash + EamGlobalSet notableSet1; + int notableSet1id; + EamGlobalSet notableSet2; + int notableSet2id; + EamGlobalSet knownSet1; + int knownSet1id; + + String notableHash1 = "d46feecd663c41648dbf690d9343cf4b"; + String knownHash1 = "39c844daee70485143da4ff926601b5b"; + String inAllSetsHash = "6449b39bb23c42879fa0c243726e27f7"; + + CorrelationAttribute.Type emailType; + + // Store the email type object for later use + try{ + emailType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.EMAIL_TYPE_ID); + assertTrue("getCorrelationTypeById(EMAIL_TYPE_ID) returned null", emailType != null); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Set up a few reference sets + try { + notableSet1 = new EamGlobalSet(org1.getOrgID(), "notable set 1", "1.0", TskData.FileKnown.BAD, false, fileType); + notableSet1id = EamDb.getInstance().newReferenceSet(notableSet1); + notableSet2 = new EamGlobalSet(org1.getOrgID(), "notable set 2", "2.4", TskData.FileKnown.BAD, false, fileType); + notableSet2id = EamDb.getInstance().newReferenceSet(notableSet2); + knownSet1 = new EamGlobalSet(org1.getOrgID(), "known set 1", "5.5.4", TskData.FileKnown.KNOWN, false, fileType); + knownSet1id = EamDb.getInstance().newReferenceSet(knownSet1); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test adding file instances with valid data + try { + EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, inAllSetsHash, TskData.FileKnown.BAD, "comment1"); + EamDb.getInstance().addReferenceInstance(temp, fileType); + + temp = new EamGlobalFileInstance(notableSet2id, inAllSetsHash, TskData.FileKnown.BAD, "comment2"); + EamDb.getInstance().addReferenceInstance(temp, fileType); + + temp = new EamGlobalFileInstance(knownSet1id, inAllSetsHash, TskData.FileKnown.KNOWN, "comment3"); + EamDb.getInstance().addReferenceInstance(temp, fileType); + + temp = new EamGlobalFileInstance(notableSet1id, notableHash1, TskData.FileKnown.BAD, "comment4"); + EamDb.getInstance().addReferenceInstance(temp, fileType); + + temp = new EamGlobalFileInstance(knownSet1id, knownHash1, TskData.FileKnown.KNOWN, "comment5"); + EamDb.getInstance().addReferenceInstance(temp, fileType); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test adding file instance with invalid reference set ID + try { + EamGlobalFileInstance temp = new EamGlobalFileInstance(2345, inAllSetsHash, TskData.FileKnown.BAD, "comment"); + EamDb.getInstance().addReferenceInstance(temp, fileType); + Assert.fail("addReferenceInstance failed to throw exception for invalid ID"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test creating file instance with null hash + // Since it isn't possible to get a null hash into the EamGlobalFileInstance, skip trying to + // call addReferenceInstance and just test the EamGlobalFileInstance constructor + try { + EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, null, TskData.FileKnown.BAD, "comment"); + Assert.fail("EamGlobalFileInstance failed to throw exception for null hash"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test adding file instance with null known status + // Since it isn't possible to get a null known status into the EamGlobalFileInstance, skip trying to + // call addReferenceInstance and just test the EamGlobalFileInstance constructor + try { + EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, inAllSetsHash, null, "comment"); + Assert.fail("EamGlobalFileInstance failed to throw exception for null type"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test adding file instance with null correlation type + try { + EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, inAllSetsHash, TskData.FileKnown.BAD, "comment"); + EamDb.getInstance().addReferenceInstance(temp, null); + Assert.fail("addReferenceInstance failed to throw exception for null type"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test bulk insert with large valid set + try { + // Create a list of global file instances. Make enough that the bulk threshold should be hit once. + Set instances = new HashSet<>(); + String bulkTestHash = "bulktesthash_"; + for (int i = 0; i < dbSettingsSqlite.getBulkThreshold() * 1.5; i++) { + String hash = bulkTestHash + String.valueOf(i); + instances.add(new EamGlobalFileInstance(notableSet2id, hash, TskData.FileKnown.BAD, null)); + } + + // Insert the list + EamDb.getInstance().bulkInsertReferenceTypeEntries(instances, fileType); + + // There's no way to get a count of the number of entries in the database, so just do a spot check + if(dbSettingsSqlite.getBulkThreshold() > 10){ + String hash = bulkTestHash + "10"; + assertTrue("Sample bulk insert instance not found", EamDb.getInstance().isFileHashInReferenceSet(hash, notableSet2id)); + } + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test bulk add file instance with null list + try { + EamDb.getInstance().bulkInsertReferenceTypeEntries(null, fileType); + Assert.fail("bulkInsertReferenceTypeEntries failed to throw exception for null list"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test bulk add file instance with invalid reference set ID + try { + Set tempSet = new HashSet<>(Arrays.asList(new EamGlobalFileInstance(2345, inAllSetsHash, TskData.FileKnown.BAD, "comment"))); + EamDb.getInstance().bulkInsertReferenceTypeEntries(tempSet, fileType); + Assert.fail("bulkInsertReferenceTypeEntries failed to throw exception for invalid ID"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test bulk add file instance with null correlation type + try { + Set tempSet = new HashSet<>(Arrays.asList(new EamGlobalFileInstance(notableSet1id, inAllSetsHash, TskData.FileKnown.BAD, "comment"))); + EamDb.getInstance().bulkInsertReferenceTypeEntries(tempSet, null); + Assert.fail("bulkInsertReferenceTypeEntries failed to throw exception for null type"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test getting reference instances with valid data + try { + List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(fileType, inAllSetsHash); + assertTrue("getReferenceInstancesByTypeValue returned " + temp.size() + " instances - expected 3", temp.size() == 3); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting reference instances with non-existent data + try { + List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(fileType, "testHash"); + assertTrue("getReferenceInstancesByTypeValue returned " + temp.size() + " instances for non-existent value - expected 0", temp.isEmpty()); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting reference instances an invalid type (the email table is not yet implemented) + try { + List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(emailType, inAllSetsHash); + Assert.fail("getReferenceInstancesByTypeValue failed to throw exception for invalid table"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test getting reference instances with null type + try { + List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(null, inAllSetsHash); + Assert.fail("getReferenceInstancesByTypeValue failed to throw exception for null type"); + }catch (EamDbException ex){ + // This is the expected behavior + } + + // Test getting reference instances with null value + try { + List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(fileType, null); + assertTrue("getReferenceInstancesByTypeValue returned non-empty list given null value", temp.isEmpty()); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test checking existing hash/ID + try { + assertTrue("isFileHashInReferenceSet returned false for valid data", EamDb.getInstance().isFileHashInReferenceSet(knownHash1, knownSet1id)); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test checking non-existent (but valid) hash/ID + try { + assertFalse("isFileHashInReferenceSet returned true for non-existent data", EamDb.getInstance().isFileHashInReferenceSet(knownHash1, notableSet1id)); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test checking invalid reference set ID + try { + assertFalse("isFileHashInReferenceSet returned true for invalid data", EamDb.getInstance().isFileHashInReferenceSet(knownHash1, 5678)); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test checking null hash + try { + assertFalse("isFileHashInReferenceSet returned true for null hash", EamDb.getInstance().isFileHashInReferenceSet(null, knownSet1id)); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test checking existing hash/ID + try { + assertTrue("isValueInReferenceSet returned false for valid data", + EamDb.getInstance().isValueInReferenceSet(knownHash1, knownSet1id, fileType.getId())); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test checking non-existent (but valid) hash/ID + try { + assertFalse("isValueInReferenceSet returned true for non-existent data", + EamDb.getInstance().isValueInReferenceSet(knownHash1, notableSet1id, fileType.getId())); + }catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test checking invalid reference set ID + try { + assertFalse("isValueInReferenceSet returned true for invalid data", + EamDb.getInstance().isValueInReferenceSet(knownHash1, 5678, fileType.getId())); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test checking null hash + try { + assertFalse("isValueInReferenceSet returned true for null value", + EamDb.getInstance().isValueInReferenceSet(null, knownSet1id, fileType.getId())); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test checking invalid type + try { + EamDb.getInstance().isValueInReferenceSet(knownHash1, knownSet1id, emailType.getId()); + Assert.fail("isValueInReferenceSet failed to throw exception for invalid type"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test known bad with notable data + try { + assertTrue("isArtifactKnownBadByReference returned false for notable value", + EamDb.getInstance().isArtifactKnownBadByReference(fileType, notableHash1)); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test known bad with known data + try { + assertFalse("isArtifactKnownBadByReference returned true for known value", + EamDb.getInstance().isArtifactKnownBadByReference(fileType, knownHash1)); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test known bad with non-existent data + try { + assertFalse("isArtifactKnownBadByReference returned true for non-existent value", + EamDb.getInstance().isArtifactKnownBadByReference(fileType, "abcdef")); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test known bad with null hash + try { + assertFalse("isArtifactKnownBadByReference returned true for null value", + EamDb.getInstance().isArtifactKnownBadByReference(fileType, null)); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test known bad with null type + try { + EamDb.getInstance().isArtifactKnownBadByReference(null, knownHash1); + Assert.fail("isArtifactKnownBadByReference failed to throw exception from null type"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test known bad with invalid type + try { + assertFalse("isArtifactKnownBadByReference returned true for invalid type", EamDb.getInstance().isArtifactKnownBadByReference(emailType, null)); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + /** * Test method for the methods related to reference sets (does not include instance testing) + * Only the files type is currently implemented * newReferenceSet(EamGlobalSet eamGlobalSet) tests: * - Test creating notable reference set * - Test creating known reference set @@ -200,16 +571,6 @@ public class CentralRepoDatamodelTest extends TestCase { EamGlobalSet set3; int set3id; - // Store the file type object to save time - CorrelationAttribute.Type fileType; - try{ - fileType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); - assertTrue("In testReferenceSets, getCorrelationTypeById(FILES_TYPE_ID) returned null", fileType != null); - } catch (EamDbException ex){ - Exceptions.printStackTrace(ex); - Assert.fail(ex); - return; - } // Test creating a notable reference set try { @@ -449,8 +810,7 @@ public class CentralRepoDatamodelTest extends TestCase { EamOrganization org = EamDb.getInstance().getReferenceSetOrganization(4567); Assert.fail("getReferenceSetOrganization failed to throw exception for invalid reference set ID"); } catch (EamDbException ex){ - Exceptions.printStackTrace(ex); - Assert.fail(ex); + // This is the expected behavior } } From 36c4e509726343a572eec51d550e76445abf0a3d Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 31 Jan 2018 14:48:00 -0500 Subject: [PATCH 32/52] Organizations testing almost complete --- .../datamodel/AbstractSqlEamDb.java | 8 + .../datamodel/CentralRepoDatamodelTest.java | 156 ++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index e3b61fbece..b8942b1b8d 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -1439,6 +1439,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public long newOrganization(EamOrganization eamOrg) throws EamDbException { + if(eamOrg == null) { + throw new EamDbException("EamOrganization is null"); + } + Connection conn = connect(); ResultSet generatedKeys = null; PreparedStatement preparedStatement = null; @@ -1560,6 +1564,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public void updateOrganization(EamOrganization updatedOrganization) throws EamDbException { + if(updatedOrganization == null) { + throw new EamDbException("null updatedOrganization"); + } + Connection conn = connect(); PreparedStatement preparedStatement = null; String sql = "UPDATE organizations SET org_name = ?, poc_name = ?, poc_email = ?, poc_phone = ? WHERE id = ?"; diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index cd0a0322a4..403181f916 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -161,6 +161,162 @@ public class CentralRepoDatamodelTest extends TestCase { assertFalse("Error deleting test directory " + testDirectory.toString(), testDirectory.toFile().exists()); } + /** + * + */ + public void testOrganizations() { + + EamOrganization orgA; + String orgAname = "orgA"; + EamOrganization orgB; + String orgBname = "orgB"; + String orgBpocName = "pocName"; + String orgBpocEmail = "pocEmail"; + String orgBpocPhone = "pocPhone"; + + // Test adding a basic organization + try{ + orgA = new EamOrganization(orgAname); + orgA.setOrgID((int) EamDb.getInstance().newOrganization(orgA)); + assertTrue("Organization ID is still -1 after adding to db", orgA.getOrgID() != -1); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test adding an organization with additional fields + try{ + orgB = new EamOrganization(orgBname, orgBpocName, orgBpocEmail, orgBpocPhone); + orgB.setOrgID((int) EamDb.getInstance().newOrganization(orgB)); + assertTrue("Organization ID is still -1 after adding to db", orgB.getOrgID() != -1); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test adding a duplicate organization + try{ + EamOrganization temp = new EamOrganization(orgAname); + EamDb.getInstance().newOrganization(temp); + Assert.fail("newOrganization failed to throw exception for duplicate org name"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test adding null organization + try{ + EamDb.getInstance().newOrganization(null); + Assert.fail("newOrganization failed to throw exception for null org"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test adding organization with null name + try{ + EamOrganization temp = new EamOrganization(null); + EamDb.getInstance().newOrganization(temp); + Assert.fail("newOrganization failed to throw exception for null name"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test getting organizations + // We expect five - the default org, two from setUp, and two from this method + try{ + List orgs = EamDb.getInstance().getOrganizations(); + assertTrue("getOrganizations returned null list", orgs != null); + assertTrue("getOrganizations returned " + orgs.size() + " orgs - expected 5", orgs.size() == 5); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting org with valid ID + try{ + EamOrganization temp = EamDb.getInstance().getOrganizationByID(orgB.getOrgID()); + assertTrue("getOrganizationByID returned null for valid ID", temp != null); + assertTrue("getOrganizationByID returned unexpected name for organization", orgBname.equals(temp.getName())); + assertTrue("getOrganizationByID returned unexpected poc name for organization", orgBpocName.equals(temp.getPocName())); + assertTrue("getOrganizationByID returned unexpected poc email for organization", orgBpocEmail.equals(temp.getPocEmail())); + assertTrue("getOrganizationByID returned unexpected poc phone for organization", orgBpocPhone.equals(temp.getPocPhone())); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting org with invalid ID + try{ + EamOrganization temp = EamDb.getInstance().getOrganizationByID(12345); + Assert.fail("getOrganizationByID failed to throw exception for invalid ID"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test updating valid org + try{ + String newName = "newOrgName"; + String newPocName = "newPocName"; + String newPocEmail = "newPocEmail"; + String newPocPhone = "newPocPhone"; + orgA.setName(newName); + orgA.setPocName(newPocName); + orgA.setPocEmail(newPocEmail); + orgA.setPocPhone(newPocPhone); + + EamDb.getInstance().updateOrganization(orgA); + + EamOrganization copyOfA = EamDb.getInstance().getOrganizationByID(orgA.getOrgID()); + + assertTrue("getOrganizationByID returned null for valid ID", copyOfA != null); + assertTrue("updateOrganization failed to update org name", newName.equals(copyOfA.getName())); + assertTrue("updateOrganization failed to update poc name", newPocName.equals(copyOfA.getPocName())); + assertTrue("updateOrganization failed to update poc email", newPocEmail.equals(copyOfA.getPocEmail())); + assertTrue("updateOrganization failed to update poc phone", newPocPhone.equals(copyOfA.getPocPhone())); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test updating invalid org + // Shouldn't do anything + try{ + EamOrganization temp = new EamOrganization("invalidOrg"); + temp.setOrgID(3434); + EamDb.getInstance().updateOrganization(temp); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test updating null org + try{ + EamDb.getInstance().updateOrganization(null); + Assert.fail("updateOrganization failed to throw exception for null org"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test updating org to null name + try{ + EamOrganization copyOfA = EamDb.getInstance().getOrganizationByID(orgA.getOrgID()); + copyOfA.setName(null); + EamDb.getInstance().updateOrganization(copyOfA); + Assert.fail("updateOrganization failed to throw exception for null name"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test deleting existing org that isn't in use + + // Test deleting existing org that is in use + + // Test deleting non-existent org + + // Test deleting null org + } + /** * Tests for adding / retrieving reference instances * Only the files type is currently implemented From c6ab090fe66f1c8f2d1c647abf56a23c7be0966d Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 1 Feb 2018 08:31:07 -0500 Subject: [PATCH 33/52] Finished organizations --- .../datamodel/AbstractSqlEamDb.java | 4 ++ .../datamodel/CentralRepoDatamodelTest.java | 64 ++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index b8942b1b8d..0a2d91fd02 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -1592,6 +1592,10 @@ public abstract class AbstractSqlEamDb implements EamDb { "AbstractSqlEamDb.deleteOrganization.errorDeleting.message=Error executing query when attempting to delete organization by id."}) @Override public void deleteOrganization(EamOrganization organizationToDelete) throws EamDbException { + if(organizationToDelete == null) { + throw new EamDbException("Organization to delete is null"); + } + Connection conn = connect(); PreparedStatement checkIfUsedStatement = null; ResultSet resultSet = null; diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 403181f916..f887c5cb02 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -162,7 +162,28 @@ public class CentralRepoDatamodelTest extends TestCase { } /** - * + * Test the methods related to organizations + * newOrganization(EamOrganization eamOrg) tests: + * - Test with just org name + * - Test with org name and poc info + * - Test adding duplicate org + * - Test adding null org + * - Test adding org with null name + * getOrganizations() tests: + * - Test getting the list of orgs +* getOrganizationByID(int orgID) tests: +* - Test with valid ID +* - Test with invalid ID +* updateOrganization(EamOrganization updatedOrganization) tests: +* - Test updating valid org +* - Test updating invalid org +* - Test updating null org +* - Test updating org to null name +* deleteOrganization(EamOrganization organizationToDelete) tests: +* - Test deleting org that isn't in use +* - Test deleting org that is in use +* - Test deleting invalid org +* - Test deleting null org */ public void testOrganizations() { @@ -309,12 +330,53 @@ public class CentralRepoDatamodelTest extends TestCase { } // Test deleting existing org that isn't in use + try{ + EamOrganization orgToDelete = new EamOrganization("deleteThis"); + orgToDelete.setOrgID((int)EamDb.getInstance().newOrganization(orgToDelete)); + int orgCount = EamDb.getInstance().getOrganizations().size(); + + EamDb.getInstance().deleteOrganization(orgToDelete); + assertTrue("getOrganizations returned unexpected count after deletion", orgCount - 1 == EamDb.getInstance().getOrganizations().size()); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } // Test deleting existing org that is in use + try{ + // Make a new org + EamOrganization inUseOrg = new EamOrganization("inUseOrg"); + inUseOrg.setOrgID((int)EamDb.getInstance().newOrganization(inUseOrg)); + + // Make a reference set that uses it + EamGlobalSet tempSet = new EamGlobalSet(inUseOrg.getOrgID(), "inUseOrgTest", "1.0", TskData.FileKnown.BAD, false, fileType); + EamDb.getInstance().newReferenceSet(tempSet); + + // It should now throw an exception if we try to delete it + EamDb.getInstance().deleteOrganization(inUseOrg); + Assert.fail("deleteOrganization failed to throw exception for in use organization"); + } catch (EamDbException ex){ + // This is the expected behavior + } // Test deleting non-existent org + // Should do nothing + try{ + EamOrganization temp = new EamOrganization("temp"); + temp.setOrgID(9876); + EamDb.getInstance().deleteOrganization(temp); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } // Test deleting null org + try{ + EamDb.getInstance().deleteOrganization(null); + Assert.fail("deleteOrganization failed to throw exception for null organization"); + } catch (EamDbException ex){ + // This is the expected behavior + } } /** From 205f8e820ce2a64883d9458eec26a7e7aa06f194 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 1 Feb 2018 09:17:08 -0500 Subject: [PATCH 34/52] Starting type tests --- .../datamodel/CorrelationAttribute.java | 6 +-- .../datamodel/CentralRepoDatamodelTest.java | 52 +++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java index 39968d7922..57bafc4ff2 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java @@ -181,7 +181,7 @@ public class CorrelationAttribute implements Serializable { * Must start with a lowercase letter and only contain * lowercase letters, numbers, and '_' characters. * @param supported Is this Type currently supported - * @param enabled Is this Type currentl enabled. + * @param enabled Is this Type currently enabled. */ public Type(int id, String displayName, String dbTableName, Boolean supported, Boolean enabled) throws EamDbException { this.id = id; @@ -195,7 +195,7 @@ public class CorrelationAttribute implements Serializable { } /** - * Constructior for custom types where we do not know the Type ID until + * Constructor 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. * @@ -204,7 +204,7 @@ public class CorrelationAttribute implements Serializable { * Must start with a lowercase letter and only contain * lowercase letters, numbers, and '_' characters. * @param supported Is this Type currently supported - * @param enabled Is this Type currentl enabled. + * @param enabled Is this Type currently enabled. */ public Type(String displayName, String dbTableName, Boolean supported, Boolean enabled) throws EamDbException { this(-1, displayName, dbTableName, supported, enabled); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index f887c5cb02..a66a3476ad 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -28,6 +28,8 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.datamodel.TskData; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; /** * @@ -161,6 +163,56 @@ public class CentralRepoDatamodelTest extends TestCase { assertFalse("Error deleting test directory " + testDirectory.toString(), testDirectory.toFile().exists()); } + /** + * newCorrelationType(CorrelationAttribute.Type newType) +getDefinedCorrelationTypes() +getEnabledCorrelationTypes() +getSupportedCorrelationTypes() +* getCorrelationTypeById(int typeId) +updateCorrelationType(CorrelationAttribute.Type aType) + */ + public void testCorrelationTypes() { + + CorrelationAttribute.Type customType; + + // Test new type with valid data + try{ + customType = new CorrelationAttribute.Type("customType", "custom_type", false, false); + customType.setId(EamDb.getInstance().newCorrelationType(customType)); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test new type with duplicate data + try{ + CorrelationAttribute.Type temp = new CorrelationAttribute.Type("customType", "custom_type", false, false); + EamDb.getInstance().newCorrelationType(temp); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test new type with null name + try{ + CorrelationAttribute.Type temp = new CorrelationAttribute.Type(null, "temp_type", false, false); + EamDb.getInstance().newCorrelationType(temp); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test new type with null db name + try{ + CorrelationAttribute.Type temp = new CorrelationAttribute.Type("temp", null, false, false); + EamDb.getInstance().newCorrelationType(temp); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } + /** * Test the methods related to organizations * newOrganization(EamOrganization eamOrg) tests: From 806d7a5bd914e89bf42a5acfb8a32e3aa1ee133b Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Thu, 1 Feb 2018 10:56:16 -0500 Subject: [PATCH 35/52] 3470: Add comments for the Excel Cell size. --- Core/src/org/sleuthkit/autopsy/report/ReportExcel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java index 81045dc5b1..9158790ad6 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java @@ -34,7 +34,7 @@ class ReportExcel implements TableReportModule { private static final Logger logger = Logger.getLogger(ReportExcel.class.getName()); private static ReportExcel instance; - private static final int EXCEL_CELL_MAXIMUM_SIZE = 36767; + private static final int EXCEL_CELL_MAXIMUM_SIZE = 36767; //Specified at:https://poi.apache.org/apidocs/org/apache/poi/ss/SpreadsheetVersion.html private Workbook wb; private Sheet sheet; From d825b36ef2fa2d8581c3d5d6ef58f8f112e2f42e Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 1 Feb 2018 11:27:15 -0500 Subject: [PATCH 36/52] Finished org testing --- .../datamodel/AbstractSqlEamDb.java | 17 +- .../datamodel/CorrelationAttribute.java | 3 + .../datamodel/CentralRepoDatamodelTest.java | 154 ++++++++++++++++-- 3 files changed, 156 insertions(+), 18 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 0a2d91fd02..bb8393034f 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -1325,7 +1325,7 @@ public abstract class AbstractSqlEamDb implements EamDb { @Override public boolean referenceSetIsValid(int referenceSetID, String setName, String version) throws EamDbException { EamGlobalSet refSet = this.getReferenceSetByID(referenceSetID); - if (refSet == null) { + if(refSet == null) { return false; } @@ -1941,6 +1941,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public int newCorrelationType(CorrelationAttribute.Type newType) throws EamDbException { + if (newType == null) { + throw new EamDbException("null correlation type"); + } + Connection conn = connect(); PreparedStatement preparedStatement = null; @@ -1955,7 +1959,7 @@ public abstract class AbstractSqlEamDb implements EamDb { } 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=?"; + querySql = "SELECT * FROM correlation_types WHERE display_name=? AND db_table_name=?"; try { preparedStatement = conn.prepareStatement(insertSql); @@ -2145,9 +2149,12 @@ public abstract class AbstractSqlEamDb implements EamDb { preparedStatement = conn.prepareStatement(sql); preparedStatement.setInt(1, typeId); resultSet = preparedStatement.executeQuery(); - resultSet.next(); - aType = getCorrelationTypeFromResultSet(resultSet); - return aType; + if(resultSet.next()) { + aType = getCorrelationTypeFromResultSet(resultSet); + return aType; + } else { + throw new EamDbException("Failed to find entry for correlation type ID = " + typeId); + } } catch (SQLException ex) { throw new EamDbException("Error getting correlation type by id.", ex); // NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java index 57bafc4ff2..3a18932aa2 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java @@ -184,6 +184,9 @@ public class CorrelationAttribute implements Serializable { * @param enabled Is this Type currently enabled. */ public Type(int id, String displayName, String dbTableName, Boolean supported, Boolean enabled) throws EamDbException { + if(dbTableName == null) { + throw new EamDbException("dbTableName is null"); + } this.id = id; this.displayName = displayName; this.dbTableName = dbTableName; diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index a66a3476ad..5b639cec14 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -164,20 +164,37 @@ public class CentralRepoDatamodelTest extends TestCase { } /** - * newCorrelationType(CorrelationAttribute.Type newType) -getDefinedCorrelationTypes() -getEnabledCorrelationTypes() -getSupportedCorrelationTypes() -* getCorrelationTypeById(int typeId) -updateCorrelationType(CorrelationAttribute.Type aType) + * Test methods related to correlation types + * newCorrelationType(CorrelationAttribute.Type newType) tests: + * - Test with valid data + * - Test with duplicate data + * - Test with null name + * - Test with null db name + * - Test with null type + * getDefinedCorrelationTypes() tests: + * - Test that the expected number are returned + * getEnabledCorrelationTypes() tests: + * - Test that the expected number are returned + * getSupportedCorrelationTypes() tests: + * - Test that the expected number are returned + * getCorrelationTypeById(int typeId) tests: + * - Test with valid ID + * - Test with invalid ID + * updateCorrelationType(CorrelationAttribute.Type aType) tests: + * - Test with existing type + * - Test with non-existent type + * - Test updating to null name + * - Test with null type */ public void testCorrelationTypes() { CorrelationAttribute.Type customType; + String customTypeName = "customType"; + String customTypeDb = "custom_type"; // Test new type with valid data try{ - customType = new CorrelationAttribute.Type("customType", "custom_type", false, false); + customType = new CorrelationAttribute.Type(customTypeName, customTypeDb, false, false); customType.setId(EamDb.getInstance().newCorrelationType(customType)); } catch (EamDbException ex){ Exceptions.printStackTrace(ex); @@ -187,30 +204,141 @@ updateCorrelationType(CorrelationAttribute.Type aType) // Test new type with duplicate data try{ - CorrelationAttribute.Type temp = new CorrelationAttribute.Type("customType", "custom_type", false, false); + CorrelationAttribute.Type temp = new CorrelationAttribute.Type(customTypeName, customTypeDb, false, false); EamDb.getInstance().newCorrelationType(temp); + Assert.fail("newCorrelationType failed to throw exception for duplicate name/db table"); } catch (EamDbException ex){ - Exceptions.printStackTrace(ex); - Assert.fail(ex); + // This is the expected behavior } // Test new type with null name try{ CorrelationAttribute.Type temp = new CorrelationAttribute.Type(null, "temp_type", false, false); EamDb.getInstance().newCorrelationType(temp); + Assert.fail("newCorrelationType failed to throw exception for null name table"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test new type with null db name + // The constructor should fail in this case + try{ + CorrelationAttribute.Type temp = new CorrelationAttribute.Type("temp", null, false, false); + Assert.fail("CorrelationAttribute.Type failed to throw exception for null db table name"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test new type with null type + try{ + EamDb.getInstance().newCorrelationType(null); + Assert.fail("newCorrelationType failed to throw exception for null type"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test getting all correlation types + try{ + List types = EamDb.getInstance().getDefinedCorrelationTypes(); + + // We expect 6 total - 5 default and the custom one made earlier + assertTrue("getDefinedCorrelationTypes returned " + types.size() + " entries - expected 6", types.size() == 6); } catch (EamDbException ex){ Exceptions.printStackTrace(ex); Assert.fail(ex); } - // Test new type with null db name + // Test getting enabled correlation types try{ - CorrelationAttribute.Type temp = new CorrelationAttribute.Type("temp", null, false, false); - EamDb.getInstance().newCorrelationType(temp); + List types = EamDb.getInstance().getEnabledCorrelationTypes(); + + // We expect 5 - the custom type is disabled + assertTrue("getDefinedCorrelationTypes returned " + types.size() + " enabled entries - expected 5", types.size() == 5); } catch (EamDbException ex){ Exceptions.printStackTrace(ex); Assert.fail(ex); } + + // Test getting supported correlation types + try{ + List types = EamDb.getInstance().getSupportedCorrelationTypes(); + + // We expect 5 - the custom type is not supported + assertTrue("getDefinedCorrelationTypes returned " + types.size() + " supported entries - expected 5", types.size() == 5); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting the type with a valid ID + try{ + CorrelationAttribute.Type temp = EamDb.getInstance().getCorrelationTypeById(customType.getId()); + assertTrue("getCorrelationTypeById returned type with unexpected name " + temp.getDisplayName(), customTypeName.equals(temp.getDisplayName())); + assertTrue("getCorrelationTypeById returned type with unexpected db table name " + temp.getDbTableName(), customTypeDb.equals(temp.getDbTableName())); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting the type with a invalid ID + try{ + CorrelationAttribute.Type temp = EamDb.getInstance().getCorrelationTypeById(5555); + Assert.fail("getCorrelationTypeById failed to throw exception for invalid ID"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test updating a valid type + try{ + String newName = "newName"; + String newDbTable = "new_db_table"; + customType.setDisplayName(newName); + customType.setDbTableName(newDbTable); + customType.setEnabled(true); // These were originally false + customType.setSupported(true); + + EamDb.getInstance().updateCorrelationType(customType); + + // Get a fresh copy from the database + CorrelationAttribute.Type temp = EamDb.getInstance().getCorrelationTypeById(customType.getId()); + + assertTrue("updateCorrelationType failed to update name", newName.equals(temp.getDisplayName())); + assertTrue("updateCorrelationType failed to update db table name", newDbTable.equals(temp.getDbTableName())); + assertTrue("updateCorrelationType failed to update enabled status", temp.isEnabled()); + assertTrue("updateCorrelationType failed to update supported status", temp.isSupported()); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test updating a type with an invalid ID + // Nothing should happen + try{ + CorrelationAttribute.Type temp= new CorrelationAttribute.Type(customTypeName, customTypeDb, false, false); + temp.setId(12345); + EamDb.getInstance().updateCorrelationType(temp); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test updating a type to a null name + try{ + customType.setDisplayName(null); + EamDb.getInstance().updateCorrelationType(customType); + Assert.fail("updateCorrelationType failed to throw exception for null name"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test updating a null type + try{ + customType.setDisplayName(null); + EamDb.getInstance().updateCorrelationType(customType); + Assert.fail("updateCorrelationType failed to throw exception for null type"); + } catch (EamDbException ex){ + // This is the expected behavior + } } /** From 1c5ecb3487e4316368f7c973347f9871e3becb81 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 1 Feb 2018 11:47:46 -0500 Subject: [PATCH 37/52] mark temp code --- .../datamodel/CentralRepoDatamodelTest.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 5b639cec14..035db25e6f 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -28,8 +28,6 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.datamodel.TskData; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; /** * @@ -39,7 +37,7 @@ public class CentralRepoDatamodelTest extends TestCase { private static final String PROPERTIES_FILE = "CentralRepository"; private static final String CR_DB_NAME = "testcentralrepo.db"; //private static final Path testDirectory = Paths.get(System.getProperty("java.io.tmpdir"), "CentralRepoDatamodelTest"); - private static final Path testDirectory = Paths.get("C:", "Work", "CRDatamodelTest"); + private static final Path testDirectory = Paths.get("C:", "Work", "CRDatamodelTest"); // TEMP EASIER FOR TESTING SqliteEamDbSettings dbSettingsSqlite; private CorrelationCase case1; @@ -156,13 +154,20 @@ public class CentralRepoDatamodelTest extends TestCase { FileUtils.deleteDirectory(testDirectory.toFile()); } catch (EamDbException | IOException ex) { - // } catch (EamDbException ex) { + // } catch (EamDbException ex) { // TEMP FOR LOOKING AT DB Exceptions.printStackTrace(ex); Assert.fail(ex); } assertFalse("Error deleting test directory " + testDirectory.toString(), testDirectory.toFile().exists()); } + /** + * Test the module settings + */ + public void testSettings(){ + // Maybe + } + /** * Test methods related to correlation types * newCorrelationType(CorrelationAttribute.Type newType) tests: From 85e5a8c56234cfc19950cdbb81708207a883c898 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Thu, 1 Feb 2018 13:41:17 -0500 Subject: [PATCH 38/52] 3499: A full Ruleset list. --- ruleset.xml | 283 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 255 insertions(+), 28 deletions(-) diff --git a/ruleset.xml b/ruleset.xml index 2b4e66b821..c85bbe4dcd 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -6,33 +6,260 @@ Ruleset used by Autopsy - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From a302b753afc8880b41fba633a59aa4734e78840b Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Thu, 1 Feb 2018 16:00:12 -0500 Subject: [PATCH 39/52] 3499: Fix typo. --- ruleset.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruleset.xml b/ruleset.xml index c85bbe4dcd..3576173d64 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -184,7 +184,7 @@ - + From 481bec66c11f780db1417fee5fb094e0f09b3387 Mon Sep 17 00:00:00 2001 From: Raman Date: Thu, 1 Feb 2018 17:08:09 -0500 Subject: [PATCH 40/52] Address review comments --- .../autopsy/contentviewers/SQLiteViewer.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java index d5b5afdb68..627d30e87c 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java @@ -40,6 +40,7 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JComboBox; import javax.swing.SwingWorker; +import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils; @@ -457,7 +458,7 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { return resultSetToArrayList(resultSet); } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Failed to get data for table.", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Failed to get data for table " + tableName, ex); //NON-NLS } //NON-NLS return null; @@ -479,7 +480,7 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { selectedTableView.setupTable(Collections.emptyList()); } } catch (InterruptedException | ExecutionException ex) { - LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Unexpected exception while reading table " + tableName, ex); //NON-NLS } } }; @@ -487,26 +488,27 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer { worker.execute(); } + @NbBundle.Messages("SQLiteViewer.BlobNotShown.message=BLOB Data not shown") private ArrayList> resultSetToArrayList(ResultSet rs) throws SQLException { - ResultSetMetaData md = rs.getMetaData(); - int columns = md.getColumnCount(); - ArrayList> arraylist = new ArrayList<>(); + ResultSetMetaData metaData = rs.getMetaData(); + int columns = metaData.getColumnCount(); + ArrayList> rowlist = new ArrayList<>(); while (rs.next()) { Map row = new LinkedHashMap<>(columns); for (int i = 1; i <= columns; ++i) { if (rs.getObject(i) == null) { - row.put(md.getColumnName(i), ""); + row.put(metaData.getColumnName(i), ""); } else { - if (md.getColumnTypeName(i).compareToIgnoreCase("blob") == 0) { - row.put(md.getColumnName(i), "BLOB Data not shown..."); + if (metaData.getColumnTypeName(i).compareToIgnoreCase("blob") == 0) { + row.put(metaData.getColumnName(i), Bundle.SQLiteViewer_BlobNotShown_message()); } else { - row.put(md.getColumnName(i), rs.getObject(i)); + row.put(metaData.getColumnName(i), rs.getObject(i)); } } } - arraylist.add(row); + rowlist.add(row); } - return arraylist; + return rowlist; } } From dda0e03e7f1f327dd39ca32cdda642a03778b8fa Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 2 Feb 2018 12:02:00 -0500 Subject: [PATCH 41/52] 3402 compare nodes themeselves instead of node names for view file in directory --- .../org/sleuthkit/autopsy/directorytree/ViewContextAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java index 95c5f50c23..792252605a 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java @@ -202,7 +202,7 @@ public class ViewContextAction extends AbstractAction { undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(content)); TreeView treeView = treeViewTopComponent.getTree(); treeView.expandNode(parentTreeViewNode); - if (treeViewTopComponent.getSelectedNode().getDisplayName().equals(parentTreeViewNode.getDisplayName())) { + if (treeViewTopComponent.getSelectedNode().equals(parentTreeViewNode)) { //In the case where our tree view already has the destination directory selected //due to an optimization in the ExplorerManager.setExploredContextAndSelection method //the property change we listen for to call DirectoryTreeTopComponent.respondSelection From eeaa0bd0b142c132e500d8b035f9705398a5d1f5 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 2 Feb 2018 13:02:49 -0500 Subject: [PATCH 42/52] Partway through artifact tests --- .../DataContentViewerOtherCases.java | 16 +- .../datamodel/AbstractSqlEamDb.java | 43 +- .../datamodel/CorrelationAttribute.java | 7 +- .../CorrelationAttributeInstance.java | 14 +- .../datamodel/EamArtifactUtil.java | 3 +- .../datamodel/CentralRepoDatamodelTest.java | 368 +++++++++++++++++- 6 files changed, 417 insertions(+), 34 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index ad642a9cbc..c098112efa 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -489,12 +489,16 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D corAttrInstances.addAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId)); corAttrInstances.forEach((corAttrInstance) -> { - CorrelationAttribute newCeArtifact = new CorrelationAttribute( - corAttr.getCorrelationType(), - corAttr.getCorrelationValue() - ); - newCeArtifact.addInstance(corAttrInstance); - tableModel.addEamArtifact(newCeArtifact); + try { + CorrelationAttribute newCeArtifact = new CorrelationAttribute( + corAttr.getCorrelationType(), + corAttr.getCorrelationValue() + ); + newCeArtifact.addInstance(corAttrInstance); + tableModel.addEamArtifact(newCeArtifact); + } catch (EamDbException ex){ + LOGGER.log(Level.SEVERE, "Error creating correlation attribute", ex); + } }); } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index bb8393034f..a26c0e2a3b 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -521,6 +521,16 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public void addArtifact(CorrelationAttribute eamArtifact) throws EamDbException { + if(eamArtifact == null) { + throw new EamDbException("CorrelationAttribute is null"); + } + if(eamArtifact.getCorrelationType() == null) { + throw new EamDbException("Correlation type is null"); + } + if(eamArtifact.getCorrelationValue() == null) { + throw new EamDbException("Correlation value is null"); + } + Connection conn = connect(); List eamInstances = eamArtifact.getInstances(); @@ -534,11 +544,21 @@ public abstract class AbstractSqlEamDb implements EamDb { 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=? AND case_id=? LIMIT 1), ?, ?, ?, ?)"); - + try { preparedStatement = conn.prepareStatement(sql.toString()); for (CorrelationAttributeInstance eamInstance : eamInstances) { if (!eamArtifact.getCorrelationValue().isEmpty()) { + if(eamInstance.getCorrelationCase() == null) { + throw new EamDbException("CorrelationAttributeInstance has null case"); + } + if(eamInstance.getCorrelationDataSource() == null) { + throw new EamDbException("CorrelationAttributeInstance has null data source"); + } + if(eamInstance.getKnownStatus() == null) { + throw new EamDbException("CorrelationAttributeInstance has null known status"); + } + preparedStatement.setString(1, eamInstance.getCorrelationCase().getCaseUUID()); preparedStatement.setString(2, eamInstance.getCorrelationDataSource().getDeviceID()); preparedStatement.setInt(3, eamInstance.getCorrelationDataSource().getCaseID()); @@ -575,6 +595,9 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public List getArtifactInstancesByTypeValue(CorrelationAttribute.Type aType, String value) throws EamDbException { + if(aType == null) { + throw new EamDbException("Correlation type is null"); + } Connection conn = connect(); List artifactInstances = new ArrayList<>(); @@ -627,6 +650,12 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public List getArtifactInstancesByPath(CorrelationAttribute.Type aType, String filePath) throws EamDbException { + if(aType == null) { + throw new EamDbException("Correlation type is null"); + } + if(filePath == null) { + throw new EamDbException("Correlation value is null"); + } Connection conn = connect(); List artifactInstances = new ArrayList<>(); @@ -649,7 +678,7 @@ public abstract class AbstractSqlEamDb implements EamDb { try { preparedStatement = conn.prepareStatement(sql.toString()); - preparedStatement.setString(1, filePath); + preparedStatement.setString(1, filePath.toLowerCase()); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { artifactInstance = getEamArtifactInstanceFromResultSet(resultSet); @@ -678,6 +707,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public Long getCountArtifactInstancesByTypeValue(CorrelationAttribute.Type aType, String value) throws EamDbException { + if(aType == null) { + throw new EamDbException("Correlation type is null"); + } + Connection conn = connect(); Long instanceCount = 0L; @@ -2210,8 +2243,8 @@ public abstract class AbstractSqlEamDb implements EamDb { } CorrelationDataSource eamDataSource = new CorrelationDataSource( - resultSet.getInt("id"), resultSet.getInt("case_id"), + resultSet.getInt("id"), resultSet.getString("device_id"), resultSet.getString("name") ); @@ -2245,13 +2278,13 @@ public abstract class AbstractSqlEamDb implements EamDb { * * @throws SQLException when an expected column name is not in the resultSet */ - private CorrelationAttributeInstance getEamArtifactInstanceFromResultSet(ResultSet resultSet) throws SQLException { + private CorrelationAttributeInstance getEamArtifactInstanceFromResultSet(ResultSet resultSet) throws SQLException, EamDbException { if (null == resultSet) { return null; } CorrelationAttributeInstance eamArtifactInstance = new CorrelationAttributeInstance( new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), resultSet.getString("case_name")), - new CorrelationDataSource(-1, resultSet.getInt("case_id"), resultSet.getString("device_id"), resultSet.getString("name")), + new CorrelationDataSource(resultSet.getInt("case_id"), -1, resultSet.getString("device_id"), resultSet.getString("name")), resultSet.getString("file_path"), resultSet.getString("comment"), TskData.FileKnown.valueOf(resultSet.getByte("known_status")) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java index 3a18932aa2..427bbc97bb 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttribute.java @@ -28,7 +28,7 @@ import org.openide.util.NbBundle.Messages; /** * Represents a type and value pair that can be used for correlation. * CorrelationAttributeInstances store information about the actual - * occurences of the attribute. + * occurrences of the attribute. */ public class CorrelationAttribute implements Serializable { @@ -66,7 +66,10 @@ public class CorrelationAttribute implements Serializable { return DEFAULT_CORRELATION_TYPES; } - public CorrelationAttribute(Type correlationType, String correlationValue) { + public CorrelationAttribute(Type correlationType, String correlationValue) throws EamDbException { + if(correlationValue == null) { + throw new EamDbException ("Correlation value is null"); + } this.ID = ""; this.correlationType = correlationType; // Lower-case all values to normalize and improve correlation hits, going forward make sure this makes sense for all correlation types diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java index f75364c580..5ca99abc7a 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java @@ -46,7 +46,7 @@ public class CorrelationAttributeInstance implements Serializable { public CorrelationAttributeInstance( CorrelationCase eamCase, CorrelationDataSource eamDataSource - ) { + ) throws EamDbException { this(-1, eamCase, eamDataSource, "", null, TskData.FileKnown.UNKNOWN); } @@ -54,7 +54,7 @@ public class CorrelationAttributeInstance implements Serializable { CorrelationCase eamCase, CorrelationDataSource eamDataSource, String filePath - ) { + ) throws EamDbException { this(-1, eamCase, eamDataSource, filePath, null, TskData.FileKnown.UNKNOWN); } @@ -63,7 +63,7 @@ public class CorrelationAttributeInstance implements Serializable { CorrelationDataSource eamDataSource, String filePath, String comment - ) { + ) throws EamDbException { this(-1, eamCase, eamDataSource, filePath, comment, TskData.FileKnown.UNKNOWN); } @@ -73,7 +73,7 @@ public class CorrelationAttributeInstance implements Serializable { String filePath, String comment, TskData.FileKnown knownStatus - ) { + ) throws EamDbException { this(-1, eamCase, eamDataSource, filePath, comment, knownStatus); } @@ -84,7 +84,11 @@ public class CorrelationAttributeInstance implements Serializable { String filePath, String comment, TskData.FileKnown knownStatus - ) { + ) throws EamDbException { + if(filePath == null) { + throw new EamDbException("file path is null"); + } + this.ID = ID; this.correlationCase = eamCase; this.correlationDataSource = eamDataSource; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java index 171444fa42..c0810b52d3 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java @@ -135,7 +135,8 @@ public class EamArtifactUtil { * @return the new EamArtifact, or null if one was not created because * bbArtifact did not contain the needed data */ - private static CorrelationAttribute getCorrelationAttributeFromBlackboardArtifact(CorrelationAttribute.Type correlationType, BlackboardArtifact bbArtifact) { + private static CorrelationAttribute getCorrelationAttributeFromBlackboardArtifact(CorrelationAttribute.Type correlationType, + BlackboardArtifact bbArtifact) throws EamDbException { String value = null; int artifactTypeID = bbArtifact.getArtifactTypeID(); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 035db25e6f..f6587d1412 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -1,7 +1,20 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Central Repository + * + * Copyright 2018 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; @@ -44,6 +57,7 @@ public class CentralRepoDatamodelTest extends TestCase { private CorrelationCase case2; private CorrelationDataSource dataSource1fromCase1; private CorrelationDataSource dataSource2fromCase1; + private CorrelationDataSource dataSource1fromCase2; private EamOrganization org1; private EamOrganization org2; CorrelationAttribute.Type fileType; @@ -123,6 +137,11 @@ public class CentralRepoDatamodelTest extends TestCase { EamDb.getInstance().newDataSource(dataSource2fromCase1); dataSource2fromCase1 = EamDb.getInstance().getDataSource(case1, dataSource2fromCase1.getDeviceID()); assertTrue("Failed to create test object dataSource2fromCase1", dataSource2fromCase1 != null); + + dataSource1fromCase2 = new CorrelationDataSource(case2.getID(), "dataSource3_deviceID", "dataSource3"); + EamDb.getInstance().newDataSource(dataSource1fromCase2); + dataSource1fromCase2 = EamDb.getInstance().getDataSource(case2, dataSource1fromCase2.getDeviceID()); + assertTrue("Failed to create test object dataSource1fromCase2", dataSource1fromCase2 != null); org1 = new EamOrganization("org1"); org1.setOrgID((int) EamDb.getInstance().newOrganization(org1)); @@ -154,7 +173,7 @@ public class CentralRepoDatamodelTest extends TestCase { FileUtils.deleteDirectory(testDirectory.toFile()); } catch (EamDbException | IOException ex) { - // } catch (EamDbException ex) { // TEMP FOR LOOKING AT DB + // } catch (EamDbException ex) { // TEMP FOR LOOKING AT DB Exceptions.printStackTrace(ex); Assert.fail(ex); } @@ -168,6 +187,324 @@ public class CentralRepoDatamodelTest extends TestCase { // Maybe } + /** + * Test methods related to artifacts + */ + public void testArtifacts() { + + String inAllDataSourcesHash = "6cddb0e31787b79cfdcc0676b98a71ce"; + String inAllDataSourcesPath = "C:\\files\\path0.txt"; + String inDataSource1twiceHash = "b2f5ff47436671b6e533d8dc3614845d"; + String inDataSource1twicePath1 = "C:\\files\\path1.txt"; + String inDataSource1twicePath2 = "C:\\files\\path2.txt"; + String onlyInDataSource3Hash = "2af54305f183778d87de0c70c591fae4"; + String onlyInDataSource3Path = "C:\\files\\path3.txt"; + + // These will all go in dataSource1fromCase1 + String emailValue = "test@gmail.com"; + String emailPath = "C:\\files\\emailPath.txt"; + String phoneValue = "202-555-1234"; + String phonePath = "C:\\files\\phonePath.txt"; + String domainValue = "www.mozilla.com"; + String domainPath = "C:\\files\\domainPath.txt"; + String devIdValue = "94B21234"; + String devIdPath = "C:\\files\\devIdPath.txt"; + + // Test adding attribute with one instance + try{ + CorrelationAttribute attr = new CorrelationAttribute(fileType, onlyInDataSource3Hash); + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case2, dataSource1fromCase2, onlyInDataSource3Path); + attr.addInstance(inst); + EamDb.getInstance().addArtifact(attr); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test adding attribute with an instance in each data source + try{ + CorrelationAttribute attr = new CorrelationAttribute(fileType, inAllDataSourcesHash); + CorrelationAttributeInstance inst1 = new CorrelationAttributeInstance(case1, dataSource1fromCase1, inAllDataSourcesPath); + attr.addInstance(inst1); + CorrelationAttributeInstance inst2 = new CorrelationAttributeInstance(case1, dataSource2fromCase1, inAllDataSourcesPath); + attr.addInstance(inst2); + CorrelationAttributeInstance inst3 = new CorrelationAttributeInstance(case2, dataSource1fromCase2, inAllDataSourcesPath); + attr.addInstance(inst3); + EamDb.getInstance().addArtifact(attr); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test adding attribute with two instances in one data source + try{ + CorrelationAttribute attr = new CorrelationAttribute(fileType, inDataSource1twiceHash); + CorrelationAttributeInstance inst1 = new CorrelationAttributeInstance(case1, dataSource1fromCase1, inDataSource1twicePath1); + attr.addInstance(inst1); + CorrelationAttributeInstance inst2 = new CorrelationAttributeInstance(case1, dataSource1fromCase1, inDataSource1twicePath2); + attr.addInstance(inst2); + EamDb.getInstance().addArtifact(attr); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test adding the other types + // Test adding an email artifact + try{ + CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.EMAIL_TYPE_ID), + emailValue); + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, emailPath); + attr.addInstance(inst); + EamDb.getInstance().addArtifact(attr); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test adding a phone artifact + try{ + CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.PHONE_TYPE_ID), + phoneValue); + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, phonePath); + attr.addInstance(inst); + EamDb.getInstance().addArtifact(attr); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test adding a domain artifact + try{ + CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.DOMAIN_TYPE_ID), + domainValue); + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, domainPath); + attr.addInstance(inst); + EamDb.getInstance().addArtifact(attr); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test adding a device ID artifact + try{ + CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.USBID_TYPE_ID), + devIdValue); + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, devIdPath); + attr.addInstance(inst); + EamDb.getInstance().addArtifact(attr); + } catch (EamDbException ex){ + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test CorrelationAttributeInstance failure cases + + // Create an attribute to use in the next few tests + CorrelationAttribute failAttr; + try { + failAttr = new CorrelationAttribute(fileType, "badInstances"); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Test adding instance with null case + try{ + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(null, dataSource1fromCase2, "badPath"); + failAttr.addInstance(inst); + EamDb.getInstance().addArtifact(failAttr); + Assert.fail("addArtifact failed to throw exception for null case"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test adding instance with invalid case ID + try{ + CorrelationCase badCase = new CorrelationCase("badCaseUuid", "badCaseName"); + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(badCase, dataSource1fromCase2, "badPath"); + failAttr.addInstance(inst); + EamDb.getInstance().addArtifact(failAttr); + Assert.fail("addArtifact failed to throw exception for invalid case"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test adding instance with null data source + try{ + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, null, "badPath"); + failAttr.addInstance(inst); + EamDb.getInstance().addArtifact(failAttr); + Assert.fail("addArtifact failed to throw exception for null data source"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test adding instance with invalid data source ID + try{ + CorrelationDataSource badDS = new CorrelationDataSource(case1.getID(), "badDSUuid", "badDSName"); + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, badDS, "badPath"); + failAttr.addInstance(inst); + EamDb.getInstance().addArtifact(failAttr); + Assert.fail("addArtifact failed to throw exception for invalid data source"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test adding instance with null path + // This will fail in the CorrelationAttributeInstance constructor + try{ + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, null); + Assert.fail("CorrelationAttributeInstance failed to throw exception for null path"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test adding instance with null known status + try{ + CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, null, "comment", null); + failAttr.addInstance(inst); + EamDb.getInstance().addArtifact(failAttr); + Assert.fail("addArtifact failed to throw exception for null known status"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test CorrelationAttribute failure cases + + // Test null type + try{ + CorrelationAttribute attr = new CorrelationAttribute(null, "badInstances"); + EamDb.getInstance().addArtifact(attr); + Assert.fail("addArtifact failed to throw exception for null type"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test null value + // This will fail in the CorrelationAttribute constructor + try{ + CorrelationAttribute attr = new CorrelationAttribute(fileType, null); + Assert.fail("addArtifact failed to throw exception for null value"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + // Test getting instances with expected resuls + try { + List instances = EamDb.getInstance().getArtifactInstancesByTypeValue(fileType, inAllDataSourcesHash); + assertTrue("getArtifactInstancesByTypeValue returned " + instances.size() + " results - expected 3", instances.size() == 3); + + // This test works because all the instances of this hash were set to the same path + for(CorrelationAttributeInstance inst:instances) { + assertTrue("getArtifactInstancesByTypeValue returned instance with unexpected path " + inst.getFilePath(), + inAllDataSourcesPath.equalsIgnoreCase(inst.getFilePath())); + } + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting instances expecting no results + try { + List instances = EamDb.getInstance().getArtifactInstancesByTypeValue( + EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.EMAIL_TYPE_ID), inAllDataSourcesHash); + assertTrue("getArtifactInstancesByTypeValue returned " + instances.size() + " results - expected 0", instances.isEmpty()); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting instances with null type + try { + List instances = EamDb.getInstance().getArtifactInstancesByTypeValue(null, inAllDataSourcesHash); + Assert.fail("getArtifactInstancesByTypeValue failed to throw exception for null type"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting instances with null value + // Should just return nothing + try { + List instances = EamDb.getInstance().getArtifactInstancesByTypeValue(fileType, null); + assertTrue("getArtifactInstancesByTypeValue returned non-empty list for null value", instances.isEmpty()); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting instances with path that should produce results + try { + List instances = EamDb.getInstance().getArtifactInstancesByPath(fileType, inAllDataSourcesPath); + assertTrue("getArtifactInstancesByPath returned " + instances.size() + " objects - expected 3", instances.size() == 3); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting instances with path that should not produce results + try { + List instances = EamDb.getInstance().getArtifactInstancesByPath(fileType, "xyz"); + assertTrue("getArtifactInstancesByPath returned " + instances.size() + " objects - expected 0", instances.isEmpty()); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting instances with null type + try { + List instances = EamDb.getInstance().getArtifactInstancesByPath(null, inAllDataSourcesPath); + Assert.fail("getArtifactInstancesByPath failed to throw exception for null type"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting instances with null value + try { + List instances = EamDb.getInstance().getArtifactInstancesByPath(fileType, null); + Assert.fail("getArtifactInstancesByPath failed to throw exception for null value"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting instance count with path that should produce results + try { + long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, inAllDataSourcesPath); + assertTrue("getCountArtifactInstancesByTypeValue returned " + count + " - expected 3", count == 3); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting instance count with path that should not produce results + try { + long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, "xyz"); + assertTrue("getCountArtifactInstancesByTypeValue returned " + count + " - expected 0", count == 0); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting instance count with null type + try { + long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(null, inAllDataSourcesPath); + Assert.fail("getCountArtifactInstancesByTypeValue failed to throw exception for null type"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting instance count with null value + try { + long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, null); + Assert.fail("getCountArtifactInstancesByTypeValue failed to throw exception for null value"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + + } + /** * Test methods related to correlation types * newCorrelationType(CorrelationAttribute.Type newType) tests: @@ -191,7 +528,7 @@ public class CentralRepoDatamodelTest extends TestCase { * - Test updating to null name * - Test with null type */ - public void testCorrelationTypes() { + public void atestCorrelationTypes() { CorrelationAttribute.Type customType; String customTypeName = "customType"; @@ -370,7 +707,7 @@ public class CentralRepoDatamodelTest extends TestCase { * - Test deleting invalid org * - Test deleting null org */ - public void testOrganizations() { + public void atestOrganizations() { EamOrganization orgA; String orgAname = "orgA"; @@ -603,7 +940,7 @@ public class CentralRepoDatamodelTest extends TestCase { * - Test null type * - Test invalid type */ - public void testReferenceSetInstances(){ + public void atestReferenceSetInstances(){ // After the two initial testing blocks, the reference sets should contain: // notableSet1 - notableHash1, inAllSetsHash @@ -963,7 +1300,7 @@ public class CentralRepoDatamodelTest extends TestCase { * - Test on valid reference set ID * - Test on invalid reference set ID */ - public void testReferenceSets() { + public void atestReferenceSets() { String set1name = "referenceSet1"; String set1version = "1.0"; EamGlobalSet set1; @@ -1236,7 +1573,7 @@ public class CentralRepoDatamodelTest extends TestCase { * Long getCountUniqueDataSources() tests: * - Test that the result is as expected */ - public void testDataSources() { + public void atestDataSources() { final String dataSourceAname = "dataSourceA"; final String dataSourceAid = "dataSourceA_deviceID"; CorrelationDataSource dataSourceA; @@ -1334,16 +1671,17 @@ public class CentralRepoDatamodelTest extends TestCase { } // Test getting the list of data sources - // There should be three data sources, and we'll check for the expected device IDs + // There should be five data sources, and we'll check for the expected device IDs try { List dataSources = EamDb.getInstance().getDataSources(); List devIdList = dataSources.stream().map(c -> c.getDeviceID()).collect(Collectors.toList()); - assertTrue("getDataSources returned unexpected number of data sources", dataSources.size() == 4); + assertTrue("getDataSources returned unexpected number of data sources", dataSources.size() == 5); assertTrue("getDataSources is missing expected data sources", devIdList.contains(dataSourceAid) && devIdList.contains(dataSource1fromCase1.getDeviceID()) - && devIdList.contains(dataSource2fromCase1.getDeviceID())); + && devIdList.contains(dataSource2fromCase1.getDeviceID()) + && devIdList.contains(dataSource1fromCase2.getDeviceID())); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); @@ -1352,7 +1690,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test the data source count try { assertTrue("getCountUniqueDataSources returned unexpected number of data sources", - EamDb.getInstance().getCountUniqueDataSources() == 4); + EamDb.getInstance().getCountUniqueDataSources() == 5); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); @@ -1372,7 +1710,7 @@ public class CentralRepoDatamodelTest extends TestCase { * bulkInsertCases(List cases) - Test on a list of cases * larger than the bulk insert threshold. - Test on a null list */ - public void testCases() { + public void atestCases() { final String caseAname = "caseA"; final String caseAuuid = "caseA_uuid"; CorrelationCase caseA; @@ -1609,7 +1947,7 @@ public class CentralRepoDatamodelTest extends TestCase { * to null value - Test updating null name - Test updating non-existing name * to new value */ - public void testDbInfo() { + public void atestDbInfo() { final String name1 = "testName1"; final String name2 = "testName2"; final String name3 = "testName3"; From 699995fd638551ed45203faf664aa05e4f93ec6d Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 2 Feb 2018 14:07:29 -0500 Subject: [PATCH 43/52] disabled some rulesets from initial commit --- ruleset.xml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/ruleset.xml b/ruleset.xml index 3576173d64..6ff40194e3 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -53,10 +53,18 @@ - - + + + + + + + + @@ -122,7 +131,9 @@ - + @@ -182,7 +193,8 @@ - + @@ -258,7 +270,8 @@ - + From 3aedf68dd29c04f4555bc079a605b344a6e548c0 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 2 Feb 2018 14:31:10 -0500 Subject: [PATCH 44/52] more pmd changes --- ruleset.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ruleset.xml b/ruleset.xml index 6ff40194e3..9c8f7e34c2 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -92,7 +92,8 @@ - + @@ -176,7 +177,8 @@ - + From 5d0cb87f5fab1693272d9ddeb22428a9ed41009a Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 2 Feb 2018 16:33:55 -0500 Subject: [PATCH 45/52] Artifact testing partially done. --- .../datamodel/AbstractSqlEamDb.java | 16 +- .../datamodel/CentralRepoDatamodelTest.java | 237 +++++++++++++++++- 2 files changed, 245 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index a26c0e2a3b..1517466116 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -710,6 +710,9 @@ public abstract class AbstractSqlEamDb implements EamDb { if(aType == null) { throw new EamDbException("Correlation type is null"); } + if(value == null) { + throw new EamDbException("Correlation value is null"); + } Connection conn = connect(); @@ -725,7 +728,7 @@ public abstract class AbstractSqlEamDb implements EamDb { try { preparedStatement = conn.prepareStatement(sql.toString()); - preparedStatement.setString(1, value); + preparedStatement.setString(1, value.toLowerCase()); resultSet = preparedStatement.executeQuery(); resultSet.next(); instanceCount = resultSet.getLong(1); @@ -742,6 +745,9 @@ public abstract class AbstractSqlEamDb implements EamDb { @Override public int getFrequencyPercentage(CorrelationAttribute corAttr) throws EamDbException { + if (corAttr == null) { + throw new EamDbException("Correlation attribute is null"); + } Double uniqueTypeValueTuples = getCountUniqueCaseDataSourceTuplesHavingTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue()).doubleValue(); Double uniqueCaseDataSourceTuples = getCountUniqueDataSources().doubleValue(); Double commonalityPercentage = uniqueTypeValueTuples / uniqueCaseDataSourceTuples * 100; @@ -760,6 +766,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttribute.Type aType, String value) throws EamDbException { + if(aType == null) { + throw new EamDbException("Correlation type is null"); + } + Connection conn = connect(); Long instanceCount = 0L; @@ -881,6 +891,10 @@ public abstract class AbstractSqlEamDb implements EamDb { @Override public void prepareBulkArtifact(CorrelationAttribute eamArtifact) throws EamDbException { + if(eamArtifact.getCorrelationType() == null) { + throw new EamDbException("Correlation type is null"); + } + synchronized (bulkArtifacts) { bulkArtifacts.get(eamArtifact.getCorrelationType().getDbTableName()).add(eamArtifact); bulkArtifactsCount++; diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index f6587d1412..e0177f12f0 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -173,7 +173,7 @@ public class CentralRepoDatamodelTest extends TestCase { FileUtils.deleteDirectory(testDirectory.toFile()); } catch (EamDbException | IOException ex) { - // } catch (EamDbException ex) { // TEMP FOR LOOKING AT DB + // } catch (EamDbException ex) { // TEMP FOR LOOKING AT DB Exceptions.printStackTrace(ex); Assert.fail(ex); } @@ -183,10 +183,97 @@ public class CentralRepoDatamodelTest extends TestCase { /** * Test the module settings */ - public void testSettings(){ + public void atestSettings(){ // Maybe } + /** + * Test the methods associated with bulk artifacts + * First test the normal use case of a large number of valid artifacts getting added + * Next test the error conditions: + * + */ + public void testBulkArtifacts() { + + // Test bulk artifacts + // Steps: + // - Make a list of artifacts roughly half the threshold size + // - Call prepareBulkArtifact on all of them + // - Verify that nothing has been written to the database + // - Make a list of artifacts equal to the threshold size + // - Call prepareBulkArtifact on all of them + // - Verify that the bulk threshold number of them were written to the database + // - Call bulkInsertArtifacts to insert the remainder + // - Verify that the database now has all the artifacts + try { + // Make sure there are no artifacts in the database to start + long originalArtifactCount = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), dataSource1fromCase1.getDeviceID()); + assertTrue("getCountArtifactInstancesByCaseDataSource returned non-zero count", originalArtifactCount == 0); + + // Create the first list, which will have (bulkThreshold / 2) entries + List list1 = new ArrayList<>(); + for(int i = 0; i < dbSettingsSqlite.getBulkThreshold() / 2;i++) { + String value = "bulkInsertValue1_" + String.valueOf(i); + String path = "C:\\bulkInsertPath1\\file" + String.valueOf(i); + + CorrelationAttribute attr = new CorrelationAttribute(fileType, value); + attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase1, path)); + list1.add(attr); + } + + // Queue up the current list. There should not be enough to trigger the insert + for(CorrelationAttribute attr:list1){ + EamDb.getInstance().prepareBulkArtifact(attr); + } + + // Check that nothing has been written yet + assertTrue("Artifacts written to database before threshold was reached", + originalArtifactCount == EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), dataSource1fromCase1.getDeviceID())); + + // Make a second list with length equal to bulkThreshold + List list2 = new ArrayList<>(); + for(int i = 0; i < dbSettingsSqlite.getBulkThreshold();i++) { + String value = "bulkInsertValue2_" + String.valueOf(i); + String path = "C:\\bulkInsertPath2\\file" + String.valueOf(i); + + CorrelationAttribute attr = new CorrelationAttribute(fileType, value); + attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase1, path)); + list2.add(attr); + } + + // Queue up the current list. This will trigger an insert partway through + for(CorrelationAttribute attr:list2){ + EamDb.getInstance().prepareBulkArtifact(attr); + } + + // There should now be bulkThreshold artifacts in the database + long count = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), dataSource1fromCase1.getDeviceID()); + assertTrue("Artifact count " + count + " does not match bulkThreshold " + dbSettingsSqlite.getBulkThreshold(), count == dbSettingsSqlite.getBulkThreshold()); + + // Now call bulkInsertArtifacts() to insert the rest of queue + EamDb.getInstance().bulkInsertArtifacts(); + count = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), dataSource1fromCase1.getDeviceID()); + int expectedCount = list1.size() + list2.size(); + assertTrue("Artifact count " + count + " does not match expected count " + expectedCount, count == expectedCount); + + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test preparing artifact with null type + try{ + CorrelationAttribute attr = new CorrelationAttribute(null, "value"); + EamDb.getInstance().prepareBulkArtifact(attr); + Assert.fail("prepareBulkArtifact failed to throw exception for null type"); + } catch (EamDbException ex){ + // This is the expected behavior + } + + + + } + /** * Test methods related to artifacts */ @@ -210,6 +297,17 @@ public class CentralRepoDatamodelTest extends TestCase { String devIdValue = "94B21234"; String devIdPath = "C:\\files\\devIdPath.txt"; + // Store the email type + CorrelationAttribute.Type emailType; + + try { + emailType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.EMAIL_TYPE_ID); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + // Test adding attribute with one instance try{ CorrelationAttribute attr = new CorrelationAttribute(fileType, onlyInDataSource3Hash); @@ -252,8 +350,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test adding the other types // Test adding an email artifact try{ - CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.EMAIL_TYPE_ID), - emailValue); + CorrelationAttribute attr = new CorrelationAttribute(emailType, emailValue); CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, emailPath); attr.addInstance(inst); EamDb.getInstance().addArtifact(attr); @@ -409,7 +506,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instances expecting no results try { List instances = EamDb.getInstance().getArtifactInstancesByTypeValue( - EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.EMAIL_TYPE_ID), inAllDataSourcesHash); + emailType, inAllDataSourcesHash); assertTrue("getArtifactInstancesByTypeValue returned " + instances.size() + " results - expected 0", instances.isEmpty()); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); @@ -470,7 +567,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instance count with path that should produce results try { - long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, inAllDataSourcesPath); + long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, inAllDataSourcesHash); assertTrue("getCountArtifactInstancesByTypeValue returned " + count + " - expected 3", count == 3); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); @@ -488,7 +585,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instance count with null type try { - long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(null, inAllDataSourcesPath); + long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(null, inAllDataSourcesHash); Assert.fail("getCountArtifactInstancesByTypeValue failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior @@ -502,7 +599,133 @@ public class CentralRepoDatamodelTest extends TestCase { // This is the expected behavior } + // Test getting frequency of value that is in all three data sources + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, inAllDataSourcesHash); + int freq = EamDb.getInstance().getFrequencyPercentage(attr); + assertTrue("getFrequencyPercentage returned " + freq + " - expected 100", freq == 100); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + // Test getting frequency of value that appears twice in a single data source + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, inDataSource1twiceHash); + int freq = EamDb.getInstance().getFrequencyPercentage(attr); + assertTrue("getFrequencyPercentage returned " + freq + " - expected 33", freq == 33); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting frequency of non-file type + try { + CorrelationAttribute attr = new CorrelationAttribute(emailType, emailValue); + int freq = EamDb.getInstance().getFrequencyPercentage(attr); + assertTrue("getFrequencyPercentage returned " + freq + " - expected 33", freq == 33); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting frequency of non-existent value + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, "randomValue"); + int freq = EamDb.getInstance().getFrequencyPercentage(attr); + assertTrue("getFrequencyPercentage returned " + freq + " - expected 0", freq == 0); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting frequency with null type + try { + CorrelationAttribute attr = new CorrelationAttribute(null, "randomValue"); + int freq = EamDb.getInstance().getFrequencyPercentage(attr); + Assert.fail("getFrequencyPercentage failed to throw exception for null type"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting frequency with null attribute + try { + int freq = EamDb.getInstance().getFrequencyPercentage(null); + Assert.fail("getFrequencyPercentage failed to throw exception for null attribute"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting count for dataSource1fromCase1 (includes all types) + try { + long count = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), dataSource1fromCase1.getDeviceID()); + assertTrue("getCountArtifactInstancesByCaseDataSource returned " + count + " - expected 7", count == 7); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting count with null case UUID + try { + long count = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(null, dataSource1fromCase1.getDeviceID()); + assertTrue("getCountArtifactInstancesByCaseDataSource returned " + count + " - expected 0", count == 0); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting count with null data source ID + try { + long count = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), null); + assertTrue("getCountArtifactInstancesByCaseDataSource returned " + count + " - expected 0", count == 0); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting data source count for entry that is in all three + try { + long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, inAllDataSourcesHash); + assertTrue("getCountUniqueCaseDataSourceTuplesHavingTypeValue returned " + count + " - expected 3", count == 3); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting data source count for entry that is in one data source twice + try { + long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, inDataSource1twiceHash); + assertTrue("getCountUniqueCaseDataSourceTuplesHavingTypeValue returned " + count + " - expected 1", count == 1); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting data source count for entry that is not in any data sources + try { + long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, "abcdef"); + assertTrue("getCountUniqueCaseDataSourceTuplesHavingTypeValue returned " + count + " - expected 0", count == 0); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting data source count for null type + try { + long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(null, "abcdef"); + Assert.fail("getCountUniqueCaseDataSourceTuplesHavingTypeValue failed to throw exception for null type"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting data source count for null value + try { + long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, null); + assertTrue("getCountUniqueCaseDataSourceTuplesHavingTypeValue returned " + count + " - expected 0", count == 0); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } } /** From 3bfe08ccf918240ea6826f68bd4e8279eaeb45df Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 6 Feb 2018 14:14:29 -0500 Subject: [PATCH 46/52] Finished notable artifact tests --- .../datamodel/AbstractSqlEamDb.java | 40 +- .../datamodel/CentralRepoDatamodelTest.java | 1463 ++++++++++------- 2 files changed, 949 insertions(+), 554 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 1517466116..18af7f6c81 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -948,6 +948,17 @@ public abstract class AbstractSqlEamDb implements EamDb { for (CorrelationAttributeInstance eamInstance : eamInstances) { if (!eamArtifact.getCorrelationValue().isEmpty()) { + + if(eamInstance.getCorrelationCase() == null) { + throw new EamDbException("Correlation attribute instance has null case"); + } + if(eamInstance.getCorrelationDataSource() == null) { + throw new EamDbException("Correlation attribute instance has null data source"); + } + if(eamInstance.getKnownStatus()== null) { + throw new EamDbException("Correlation attribute instance has null known known status"); + } + bulkPs.setString(1, eamInstance.getCorrelationCase().getCaseUUID()); bulkPs.setString(2, eamInstance.getCorrelationDataSource().getDeviceID()); bulkPs.setInt(3, eamInstance.getCorrelationDataSource().getCaseID()); @@ -1071,15 +1082,28 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public void setArtifactInstanceKnownStatus(CorrelationAttribute eamArtifact, TskData.FileKnown knownStatus) throws EamDbException { + if(eamArtifact == null) { + throw new EamDbException("Correlation attribute is null"); + } + if(knownStatus == null) { + throw new EamDbException("Known status is null"); + } if (1 != eamArtifact.getInstances().size()) { throw new EamDbException("Error: Artifact must have exactly one (1) Artifact Instance to set as notable."); // NON-NLS } - Connection conn = connect(); - List eamInstances = eamArtifact.getInstances(); CorrelationAttributeInstance eamInstance = eamInstances.get(0); + if(eamInstance.getCorrelationCase() == null) { + throw new EamDbException("Correlation case is null"); + } + if(eamInstance.getCorrelationDataSource() == null) { + throw new EamDbException("Correlation data source is null"); + } + + Connection conn = connect(); + PreparedStatement preparedUpdate = null; PreparedStatement preparedQuery = null; ResultSet resultSet = null; @@ -1162,6 +1186,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public List getArtifactInstancesKnownBad(CorrelationAttribute.Type aType, String value) throws EamDbException { + if(aType == null) { + throw new EamDbException("Correlation type is null"); + } + Connection conn = connect(); List artifactInstances = new ArrayList<>(); @@ -1212,6 +1240,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public Long getCountArtifactInstancesKnownBad(CorrelationAttribute.Type aType, String value) throws EamDbException { + if(aType == null) { + throw new EamDbException("Correlation type is null"); + } + Connection conn = connect(); Long badInstances = 0L; @@ -1256,6 +1288,10 @@ public abstract class AbstractSqlEamDb implements EamDb { */ @Override public List getListCasesHavingArtifactInstancesKnownBad(CorrelationAttribute.Type aType, String value) throws EamDbException { + if(aType == null) { + throw new EamDbException("Correlation type is null"); + } + Connection conn = connect(); Collection caseNames = new LinkedHashSet<>(); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index e0177f12f0..b2e05d8694 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -49,8 +49,7 @@ public class CentralRepoDatamodelTest extends TestCase { private static final String PROPERTIES_FILE = "CentralRepository"; private static final String CR_DB_NAME = "testcentralrepo.db"; - //private static final Path testDirectory = Paths.get(System.getProperty("java.io.tmpdir"), "CentralRepoDatamodelTest"); - private static final Path testDirectory = Paths.get("C:", "Work", "CRDatamodelTest"); // TEMP EASIER FOR TESTING + private static final Path testDirectory = Paths.get(System.getProperty("java.io.tmpdir"), "CentralRepoDatamodelTest"); SqliteEamDbSettings dbSettingsSqlite; private CorrelationCase case1; @@ -90,7 +89,7 @@ public class CentralRepoDatamodelTest extends TestCase { assertTrue("Unable to create test directory", testDirectory.toFile().exists()); // Save the current central repo settings - propertiesMap = ModuleSettings.getConfigSettings(PROPERTIES_FILE); + propertiesMap = ModuleSettings.getConfigSettings(PROPERTIES_FILE); try { dbSettingsSqlite.setDbName(CR_DB_NAME); @@ -137,7 +136,7 @@ public class CentralRepoDatamodelTest extends TestCase { EamDb.getInstance().newDataSource(dataSource2fromCase1); dataSource2fromCase1 = EamDb.getInstance().getDataSource(case1, dataSource2fromCase1.getDeviceID()); assertTrue("Failed to create test object dataSource2fromCase1", dataSource2fromCase1 != null); - + dataSource1fromCase2 = new CorrelationDataSource(case2.getID(), "dataSource3_deviceID", "dataSource3"); EamDb.getInstance().newDataSource(dataSource1fromCase2); dataSource1fromCase2 = EamDb.getInstance().getDataSource(case2, dataSource1fromCase2.getDeviceID()); @@ -148,7 +147,7 @@ public class CentralRepoDatamodelTest extends TestCase { org2 = new EamOrganization("org2"); org2.setOrgID((int) EamDb.getInstance().newOrganization(org2)); - + // Store the file type object for later use fileType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); assertTrue("getCorrelationTypeById(FILES_TYPE_ID) returned null", fileType != null); @@ -169,33 +168,291 @@ public class CentralRepoDatamodelTest extends TestCase { // Close and delete the test case and central repo db try { EamDb.getInstance().shutdownConnections(); - FileUtils.deleteDirectory(testDirectory.toFile()); - } catch (EamDbException | IOException ex) { - // } catch (EamDbException ex) { // TEMP FOR LOOKING AT DB Exceptions.printStackTrace(ex); Assert.fail(ex); } assertFalse("Error deleting test directory " + testDirectory.toString(), testDirectory.toFile().exists()); } - + /** - * Test the module settings + * Test the notable status of artifacts + * addArtifact(CorrelationAttribute eamArtifact) tests: + * - Test that two artifacts created with BAD status still have it when fetched from the database + * - Test that two artifacts created with BAD and KNOWN status still have the correct status when fetched from the database + * setArtifactInstanceKnownStatus(CorrelationAttribute eamArtifact, TskData.FileKnown knownStatus) tests: + * - Test updating status + * - Test updating artifact with two instances + * - Test updating null artifact + * - Test updating artifact with null known status + * - Test updating artifact with null case + * - Test updating artifact with null data source + * getArtifactInstancesKnownBad(CorrelationAttribute.Type aType, String value) tests: + * - Test getting two notable instances + * - Test getting notable instances where one instance is notable and the other is known + * - Test getting notable instances with null type + * - Test getting notable instances with null value + * getCountArtifactInstancesKnownBad(CorrelationAttribute.Type aType, String value) tests: + * - Test getting count of two notable instances + * - Test getting notable instance count where one instance is notable and the other is known + * - Test getting notable instance count with null type + * - Test getting notable instance count with null value + * getListCasesHavingArtifactInstancesKnownBad(CorrelationAttribute.Type aType, String value) tests: + * - Test getting cases with notable instances (all instances are notable) + * - Test getting cases with notable instances (only one instance is notable) + * - Test getting cases with null type + * - Test getting cases with null value */ - public void atestSettings(){ - // Maybe + public void testNotableArtifactStatus() { + + String notableHashInBothCases = "e34a8899ef6468b74f8a1048419ccc8b"; + String notableHashInOneCaseKnownOther = "d293f2f5cebcb427cde3bb95db5e1797"; + String hashToChangeToNotable = "23bd4ea37ec6304e75ac723527472a0f"; + + // Add two instances with notable status + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, notableHashInBothCases); + attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase1, "path1", + "", TskData.FileKnown.BAD)); + attr.addInstance(new CorrelationAttributeInstance(case2, dataSource1fromCase2, "path2", + "", TskData.FileKnown.BAD)); + EamDb.getInstance().addArtifact(attr); + + List attrs = EamDb.getInstance().getArtifactInstancesByTypeValue(fileType, notableHashInBothCases); + assertTrue("getArtifactInstancesByTypeValue returned " + attrs.size() + " values - expected 2", attrs.size() == 2); + for (CorrelationAttributeInstance a : attrs) { + assertTrue("Artifact did not have expected BAD status", a.getKnownStatus().equals(TskData.FileKnown.BAD)); + } + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Add two instances with one notable, one known + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, notableHashInOneCaseKnownOther); + attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase1, "path3", + "", TskData.FileKnown.BAD)); + attr.addInstance(new CorrelationAttributeInstance(case2, dataSource1fromCase2, "path4", + "", TskData.FileKnown.KNOWN)); + EamDb.getInstance().addArtifact(attr); + + List attrs = EamDb.getInstance().getArtifactInstancesByTypeValue(fileType, notableHashInOneCaseKnownOther); + assertTrue("getArtifactInstancesByTypeValue returned " + attrs.size() + " values - expected 2", attrs.size() == 2); + for (CorrelationAttributeInstance a : attrs) { + if (case1.getCaseUUID().equals(a.getCorrelationCase().getCaseUUID())) { + assertTrue("Artifact did not have expected BAD status", a.getKnownStatus().equals(TskData.FileKnown.BAD)); + } else if (case2.getCaseUUID().equals(a.getCorrelationCase().getCaseUUID())) { + assertTrue("Artifact did not have expected KNOWN status", a.getKnownStatus().equals(TskData.FileKnown.KNOWN)); + } else { + Assert.fail("getArtifactInstancesByTypeValue returned unexpected case"); + } + } + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Add an artifact and then update its status + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, hashToChangeToNotable); + attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase2, "path5", + "", TskData.FileKnown.KNOWN)); + EamDb.getInstance().addArtifact(attr); + + EamDb.getInstance().setArtifactInstanceKnownStatus(attr, TskData.FileKnown.BAD); + + List attrs = EamDb.getInstance().getArtifactInstancesByTypeValue(fileType, hashToChangeToNotable); + assertTrue("getArtifactInstancesByTypeValue returned " + attrs.size() + " values - expected 1", attrs.size() == 1); + assertTrue("Artifact status did not change to BAD", attrs.get(0).getKnownStatus().equals(TskData.FileKnown.BAD)); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return; + } + + // Try to update artifact with two CorrelationAttributeInstance instances + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, "badHash"); + attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase1, "badPath", + "", TskData.FileKnown.KNOWN)); + attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase2, "badPath", + "", TskData.FileKnown.KNOWN)); + + EamDb.getInstance().setArtifactInstanceKnownStatus(attr, TskData.FileKnown.BAD); + Assert.fail("setArtifactInstanceKnownStatus failed to throw exception for multiple Correlation Attribute Instances"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Try to update null artifact + try { + EamDb.getInstance().setArtifactInstanceKnownStatus(null, TskData.FileKnown.BAD); + Assert.fail("setArtifactInstanceKnownStatus failed to throw exception for null correlation attribute"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Try to update artifact with null known status + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, "badHash"); + attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase1, "badPath", + "", TskData.FileKnown.KNOWN)); + + EamDb.getInstance().setArtifactInstanceKnownStatus(attr, null); + Assert.fail("setArtifactInstanceKnownStatus failed to throw exception for null known status"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Try to update artifact with null case + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, "badHash"); + attr.addInstance(new CorrelationAttributeInstance(null, dataSource1fromCase1, "badPath", + "", TskData.FileKnown.KNOWN)); + + EamDb.getInstance().setArtifactInstanceKnownStatus(attr, TskData.FileKnown.BAD); + Assert.fail("setArtifactInstanceKnownStatus failed to throw exception for null case"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Try to update artifact with null data source + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, "badHash"); + attr.addInstance(new CorrelationAttributeInstance(case1, null, "badPath", + "", TskData.FileKnown.KNOWN)); + + EamDb.getInstance().setArtifactInstanceKnownStatus(attr, TskData.FileKnown.BAD); + Assert.fail("setArtifactInstanceKnownStatus failed to throw exception for null case"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting two notable instances + try { + List attrs = EamDb.getInstance().getArtifactInstancesKnownBad(fileType, notableHashInBothCases); + assertTrue("getArtifactInstancesKnownBad returned " + attrs.size() + " values - expected 2", attrs.size() == 2); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting notable instances where one instance is notable and the other is known + try { + List attrs = EamDb.getInstance().getArtifactInstancesKnownBad(fileType, notableHashInOneCaseKnownOther); + assertTrue("getArtifactInstancesKnownBad returned " + attrs.size() + " values - expected 1", attrs.size() == 1); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting notable instances with null type + try { + List attrs = EamDb.getInstance().getArtifactInstancesKnownBad(null, notableHashInOneCaseKnownOther); + Assert.fail("getArtifactInstancesKnownBad failed to throw exception for null type"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting notable instances with null value (should work fine) + try { + List attrs = EamDb.getInstance().getArtifactInstancesKnownBad(fileType, null); + assertTrue("getArtifactInstancesKnownBad returned " + attrs.size() + " values - expected ", attrs.size() == 0); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting count of two notable instances + try { + long count = EamDb.getInstance().getCountArtifactInstancesKnownBad(fileType, notableHashInBothCases); + assertTrue("getCountArtifactInstancesKnownBad returned " + count + " values - expected 2", count == 2); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting notable instance count where one instance is notable and the other is known + try { + long count = EamDb.getInstance().getCountArtifactInstancesKnownBad(fileType, notableHashInOneCaseKnownOther); + assertTrue("getCountArtifactInstancesKnownBad returned " + count + " values - expected 1", count == 1); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting notable instance count with null type + try { + EamDb.getInstance().getCountArtifactInstancesKnownBad(null, notableHashInOneCaseKnownOther); + Assert.fail("getCountArtifactInstancesKnownBad failed to throw exception for null type"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting notable instance count with null value (should work fine) + try { + long count = EamDb.getInstance().getCountArtifactInstancesKnownBad(fileType, null); + assertTrue("getCountArtifactInstancesKnownBad returned " + count + " values - expected ", count == 0); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting cases with notable instances (all instances are notable) + try { + List cases = EamDb.getInstance().getListCasesHavingArtifactInstancesKnownBad(fileType, notableHashInBothCases); + assertTrue("getListCasesHavingArtifactInstancesKnownBad returned " + cases.size() + " values - expected 2", cases.size() == 2); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting cases with notable instances (only one instance is notable) + try { + List cases = EamDb.getInstance().getListCasesHavingArtifactInstancesKnownBad(fileType, notableHashInOneCaseKnownOther); + assertTrue("getListCasesHavingArtifactInstancesKnownBad returned " + cases.size() + " values - expected 1", cases.size() == 1); + assertTrue("getListCasesHavingArtifactInstancesKnownBad returned unexpected case " + cases.get(0), case1.getDisplayName().equals(cases.get(0))); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + + // Test getting cases with null type + try { + EamDb.getInstance().getListCasesHavingArtifactInstancesKnownBad(null, notableHashInOneCaseKnownOther); + Assert.fail("getListCasesHavingArtifactInstancesKnownBad failed to throw exception for null type"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test getting cases with null value (should work fine) + try { + List cases = EamDb.getInstance().getListCasesHavingArtifactInstancesKnownBad(fileType, null); + assertTrue("getListCasesHavingArtifactInstancesKnownBad returned " + cases.size() + " values - expected ", cases.isEmpty()); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } } - + /** - * Test the methods associated with bulk artifacts - * First test the normal use case of a large number of valid artifacts getting added + * Test the methods associated with bulk artifacts (prepareBulkArtifact and + * bulkInsertArtifacts). + * First test the normal use case of a large number of valid artifacts getting added. * Next test the error conditions: - * + * - Test preparing artifact with null type + * - Test preparing artifact with null case + * - Test preparing artifact with null data source + * - Test preparing artifact with null path + * - Test preparing artifact with null known status */ public void testBulkArtifacts() { - - // Test bulk artifacts + + // Test normal addition of bulk artifacts // Steps: // - Make a list of artifacts roughly half the threshold size // - Call prepareBulkArtifact on all of them @@ -209,76 +466,164 @@ public class CentralRepoDatamodelTest extends TestCase { // Make sure there are no artifacts in the database to start long originalArtifactCount = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), dataSource1fromCase1.getDeviceID()); assertTrue("getCountArtifactInstancesByCaseDataSource returned non-zero count", originalArtifactCount == 0); - + // Create the first list, which will have (bulkThreshold / 2) entries List list1 = new ArrayList<>(); - for(int i = 0; i < dbSettingsSqlite.getBulkThreshold() / 2;i++) { + for (int i = 0; i < dbSettingsSqlite.getBulkThreshold() / 2; i++) { String value = "bulkInsertValue1_" + String.valueOf(i); String path = "C:\\bulkInsertPath1\\file" + String.valueOf(i); - + CorrelationAttribute attr = new CorrelationAttribute(fileType, value); attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase1, path)); list1.add(attr); } - + // Queue up the current list. There should not be enough to trigger the insert - for(CorrelationAttribute attr:list1){ + for (CorrelationAttribute attr : list1) { EamDb.getInstance().prepareBulkArtifact(attr); } - + // Check that nothing has been written yet - assertTrue("Artifacts written to database before threshold was reached", + assertTrue("Artifacts written to database before threshold was reached", originalArtifactCount == EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), dataSource1fromCase1.getDeviceID())); // Make a second list with length equal to bulkThreshold List list2 = new ArrayList<>(); - for(int i = 0; i < dbSettingsSqlite.getBulkThreshold();i++) { + for (int i = 0; i < dbSettingsSqlite.getBulkThreshold(); i++) { String value = "bulkInsertValue2_" + String.valueOf(i); String path = "C:\\bulkInsertPath2\\file" + String.valueOf(i); - + CorrelationAttribute attr = new CorrelationAttribute(fileType, value); attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase1, path)); list2.add(attr); } - + // Queue up the current list. This will trigger an insert partway through - for(CorrelationAttribute attr:list2){ + for (CorrelationAttribute attr : list2) { EamDb.getInstance().prepareBulkArtifact(attr); } - + // There should now be bulkThreshold artifacts in the database long count = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), dataSource1fromCase1.getDeviceID()); assertTrue("Artifact count " + count + " does not match bulkThreshold " + dbSettingsSqlite.getBulkThreshold(), count == dbSettingsSqlite.getBulkThreshold()); - + // Now call bulkInsertArtifacts() to insert the rest of queue EamDb.getInstance().bulkInsertArtifacts(); count = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), dataSource1fromCase1.getDeviceID()); int expectedCount = list1.size() + list2.size(); assertTrue("Artifact count " + count + " does not match expected count " + expectedCount, count == expectedCount); - + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test preparing artifact with null type - try{ + try { CorrelationAttribute attr = new CorrelationAttribute(null, "value"); EamDb.getInstance().prepareBulkArtifact(attr); Assert.fail("prepareBulkArtifact failed to throw exception for null type"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test preparing artifact with null case + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, "value"); + attr.addInstance(new CorrelationAttributeInstance(null, dataSource1fromCase1, "path")); + EamDb.getInstance().prepareBulkArtifact(attr); + EamDb.getInstance().bulkInsertArtifacts(); + Assert.fail("bulkInsertArtifacts failed to throw exception for null case"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test preparing artifact with null data source + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, "value"); + attr.addInstance(new CorrelationAttributeInstance(case1, null, "path")); + EamDb.getInstance().prepareBulkArtifact(attr); + EamDb.getInstance().bulkInsertArtifacts(); + Assert.fail("prepareBulkArtifact failed to throw exception for null data source"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test preparing artifact with null path + // CorrelationAttributeInstance will throw an exception + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, "value"); + attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase1, null)); + Assert.fail("CorrelationAttributeInstance failed to throw exception for null path"); + } catch (EamDbException ex) { + // This is the expected behavior + } + + // Test preparing artifact with null known status + try { + CorrelationAttribute attr = new CorrelationAttribute(fileType, "value"); + attr.addInstance(new CorrelationAttributeInstance(case1, dataSource1fromCase1, "path", "comment", null)); + EamDb.getInstance().prepareBulkArtifact(attr); + EamDb.getInstance().bulkInsertArtifacts(); + Assert.fail("prepareBulkArtifact failed to throw exception for null known status"); + } catch (EamDbException ex) { // This is the expected behavior } - - - } - + /** - * Test methods related to artifacts + * Test most methods related to artifacts + * addArtifact(CorrelationAttribute eamArtifact) tests: + * - Test adding artifact with one instance + * - Test adding artifact with one instance in each data source + * - Test adding artifact with two instances in the same data source + * - Test adding email artifact + * - Test adding phone artifact + * - Test adding domain artifact + * - Test adding device artifact + * - Test adding artifact with null case + * - Test adding artifact with invalid case ID + * - Test adding artifact with null data source + * - Test adding artifact with invalid data source ID + * - Test adding artifact with null path + * - Test adding artifact with null known status + * - Test adding artifact with null correlation type + * - Test adding artifact with null value + * getArtifactInstancesByTypeValue(CorrelationAttribute.Type aType, String value) tests: + * - Test getting three expected instances + * - Test getting no expected instances + * - Test with null type + * - Test with null value + * getArtifactInstancesByPath(CorrelationAttribute.Type aType, String filePath) tests: + * - Test with existing path + * - Test with non-existent path + * - Test with null type + * - Test with null path + * getCountArtifactInstancesByTypeValue(CorrelationAttribute.Type aType, String value) tests: + * - Test getting three expected instances + * - Test getting no expected instances + * - Test with null type + * - Test with null value + * getFrequencyPercentage(CorrelationAttribute corAttr) tests: + * - Test value in every data source + * - Test value in one data source twice + * - Test email + * - Test value in no data sources + * - Test with null type + * - Test with null attribute + * getCountArtifactInstancesByCaseDataSource(String caseUUID, String dataSourceID) tests: + * - Test data source with seven instances + * - Test with null case UUID + * - Test with null device ID + * getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttribute.Type aType, String value) tests: + * - Test value in every data source + * - Test value in one data source twice + * - Test value in no data sources + * - Test with null type + * - Test with null value */ public void testArtifacts() { - + String inAllDataSourcesHash = "6cddb0e31787b79cfdcc0676b98a71ce"; String inAllDataSourcesPath = "C:\\files\\path0.txt"; String inDataSource1twiceHash = "b2f5ff47436671b6e533d8dc3614845d"; @@ -286,7 +631,7 @@ public class CentralRepoDatamodelTest extends TestCase { String inDataSource1twicePath2 = "C:\\files\\path2.txt"; String onlyInDataSource3Hash = "2af54305f183778d87de0c70c591fae4"; String onlyInDataSource3Path = "C:\\files\\path3.txt"; - + // These will all go in dataSource1fromCase1 String emailValue = "test@gmail.com"; String emailPath = "C:\\files\\emailPath.txt"; @@ -296,10 +641,9 @@ public class CentralRepoDatamodelTest extends TestCase { String domainPath = "C:\\files\\domainPath.txt"; String devIdValue = "94B21234"; String devIdPath = "C:\\files\\devIdPath.txt"; - + // Store the email type CorrelationAttribute.Type emailType; - try { emailType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.EMAIL_TYPE_ID); } catch (EamDbException ex) { @@ -307,20 +651,20 @@ public class CentralRepoDatamodelTest extends TestCase { Assert.fail(ex); return; } - + // Test adding attribute with one instance - try{ + try { CorrelationAttribute attr = new CorrelationAttribute(fileType, onlyInDataSource3Hash); CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case2, dataSource1fromCase2, onlyInDataSource3Path); attr.addInstance(inst); EamDb.getInstance().addArtifact(attr); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test adding attribute with an instance in each data source - try{ + try { CorrelationAttribute attr = new CorrelationAttribute(fileType, inAllDataSourcesHash); CorrelationAttributeInstance inst1 = new CorrelationAttributeInstance(case1, dataSource1fromCase1, inAllDataSourcesPath); attr.addInstance(inst1); @@ -329,74 +673,73 @@ public class CentralRepoDatamodelTest extends TestCase { CorrelationAttributeInstance inst3 = new CorrelationAttributeInstance(case2, dataSource1fromCase2, inAllDataSourcesPath); attr.addInstance(inst3); EamDb.getInstance().addArtifact(attr); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test adding attribute with two instances in one data source - try{ + try { CorrelationAttribute attr = new CorrelationAttribute(fileType, inDataSource1twiceHash); CorrelationAttributeInstance inst1 = new CorrelationAttributeInstance(case1, dataSource1fromCase1, inDataSource1twicePath1); attr.addInstance(inst1); CorrelationAttributeInstance inst2 = new CorrelationAttributeInstance(case1, dataSource1fromCase1, inDataSource1twicePath2); attr.addInstance(inst2); EamDb.getInstance().addArtifact(attr); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test adding the other types // Test adding an email artifact - try{ + try { CorrelationAttribute attr = new CorrelationAttribute(emailType, emailValue); CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, emailPath); attr.addInstance(inst); EamDb.getInstance().addArtifact(attr); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test adding a phone artifact - try{ - CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.PHONE_TYPE_ID), + try { + CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.PHONE_TYPE_ID), phoneValue); CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, phonePath); attr.addInstance(inst); EamDb.getInstance().addArtifact(attr); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test adding a domain artifact - try{ - CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.DOMAIN_TYPE_ID), + try { + CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.DOMAIN_TYPE_ID), domainValue); CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, domainPath); attr.addInstance(inst); EamDb.getInstance().addArtifact(attr); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test adding a device ID artifact - try{ - CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.USBID_TYPE_ID), + try { + CorrelationAttribute attr = new CorrelationAttribute(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.USBID_TYPE_ID), devIdValue); CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, devIdPath); attr.addInstance(inst); EamDb.getInstance().addArtifact(attr); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test CorrelationAttributeInstance failure cases - // Create an attribute to use in the next few tests CorrelationAttribute failAttr; try { @@ -406,103 +749,102 @@ public class CentralRepoDatamodelTest extends TestCase { Assert.fail(ex); return; } - + // Test adding instance with null case - try{ + try { CorrelationAttributeInstance inst = new CorrelationAttributeInstance(null, dataSource1fromCase2, "badPath"); failAttr.addInstance(inst); EamDb.getInstance().addArtifact(failAttr); Assert.fail("addArtifact failed to throw exception for null case"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test adding instance with invalid case ID - try{ + try { CorrelationCase badCase = new CorrelationCase("badCaseUuid", "badCaseName"); CorrelationAttributeInstance inst = new CorrelationAttributeInstance(badCase, dataSource1fromCase2, "badPath"); failAttr.addInstance(inst); EamDb.getInstance().addArtifact(failAttr); Assert.fail("addArtifact failed to throw exception for invalid case"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test adding instance with null data source - try{ + try { CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, null, "badPath"); failAttr.addInstance(inst); EamDb.getInstance().addArtifact(failAttr); Assert.fail("addArtifact failed to throw exception for null data source"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test adding instance with invalid data source ID - try{ + try { CorrelationDataSource badDS = new CorrelationDataSource(case1.getID(), "badDSUuid", "badDSName"); CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, badDS, "badPath"); failAttr.addInstance(inst); EamDb.getInstance().addArtifact(failAttr); Assert.fail("addArtifact failed to throw exception for invalid data source"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test adding instance with null path // This will fail in the CorrelationAttributeInstance constructor - try{ + try { CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, null); Assert.fail("CorrelationAttributeInstance failed to throw exception for null path"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test adding instance with null known status - try{ + try { CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, null, "comment", null); failAttr.addInstance(inst); EamDb.getInstance().addArtifact(failAttr); Assert.fail("addArtifact failed to throw exception for null known status"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test CorrelationAttribute failure cases - // Test null type - try{ + try { CorrelationAttribute attr = new CorrelationAttribute(null, "badInstances"); EamDb.getInstance().addArtifact(attr); Assert.fail("addArtifact failed to throw exception for null type"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test null value // This will fail in the CorrelationAttribute constructor - try{ + try { CorrelationAttribute attr = new CorrelationAttribute(fileType, null); Assert.fail("addArtifact failed to throw exception for null value"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting instances with expected resuls try { List instances = EamDb.getInstance().getArtifactInstancesByTypeValue(fileType, inAllDataSourcesHash); assertTrue("getArtifactInstancesByTypeValue returned " + instances.size() + " results - expected 3", instances.size() == 3); - + // This test works because all the instances of this hash were set to the same path - for(CorrelationAttributeInstance inst:instances) { - assertTrue("getArtifactInstancesByTypeValue returned instance with unexpected path " + inst.getFilePath(), + for (CorrelationAttributeInstance inst : instances) { + assertTrue("getArtifactInstancesByTypeValue returned instance with unexpected path " + inst.getFilePath(), inAllDataSourcesPath.equalsIgnoreCase(inst.getFilePath())); } } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting instances expecting no results try { List instances = EamDb.getInstance().getArtifactInstancesByTypeValue( @@ -512,7 +854,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting instances with null type try { List instances = EamDb.getInstance().getArtifactInstancesByTypeValue(null, inAllDataSourcesHash); @@ -520,7 +862,7 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting instances with null value // Should just return nothing try { @@ -530,7 +872,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting instances with path that should produce results try { List instances = EamDb.getInstance().getArtifactInstancesByPath(fileType, inAllDataSourcesPath); @@ -539,7 +881,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting instances with path that should not produce results try { List instances = EamDb.getInstance().getArtifactInstancesByPath(fileType, "xyz"); @@ -548,7 +890,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting instances with null type try { List instances = EamDb.getInstance().getArtifactInstancesByPath(null, inAllDataSourcesPath); @@ -556,15 +898,15 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { // This is the expected behavior } - - // Test getting instances with null value + + // Test getting instances with null path try { List instances = EamDb.getInstance().getArtifactInstancesByPath(fileType, null); - Assert.fail("getArtifactInstancesByPath failed to throw exception for null value"); + Assert.fail("getArtifactInstancesByPath failed to throw exception for null path"); } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting instance count with path that should produce results try { long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, inAllDataSourcesHash); @@ -573,7 +915,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting instance count with path that should not produce results try { long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, "xyz"); @@ -582,7 +924,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting instance count with null type try { long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(null, inAllDataSourcesHash); @@ -590,7 +932,7 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting instance count with null value try { long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, null); @@ -598,7 +940,7 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting frequency of value that is in all three data sources try { CorrelationAttribute attr = new CorrelationAttribute(fileType, inAllDataSourcesHash); @@ -608,7 +950,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting frequency of value that appears twice in a single data source try { CorrelationAttribute attr = new CorrelationAttribute(fileType, inDataSource1twiceHash); @@ -618,7 +960,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting frequency of non-file type try { CorrelationAttribute attr = new CorrelationAttribute(emailType, emailValue); @@ -628,7 +970,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting frequency of non-existent value try { CorrelationAttribute attr = new CorrelationAttribute(fileType, "randomValue"); @@ -638,7 +980,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting frequency with null type try { CorrelationAttribute attr = new CorrelationAttribute(null, "randomValue"); @@ -647,7 +989,7 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting frequency with null attribute try { int freq = EamDb.getInstance().getFrequencyPercentage(null); @@ -655,7 +997,7 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting count for dataSource1fromCase1 (includes all types) try { long count = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), dataSource1fromCase1.getDeviceID()); @@ -664,7 +1006,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting count with null case UUID try { long count = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(null, dataSource1fromCase1.getDeviceID()); @@ -673,8 +1015,8 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - - // Test getting count with null data source ID + + // Test getting count with null device ID try { long count = EamDb.getInstance().getCountArtifactInstancesByCaseDataSource(case1.getCaseUUID(), null); assertTrue("getCountArtifactInstancesByCaseDataSource returned " + count + " - expected 0", count == 0); @@ -682,7 +1024,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting data source count for entry that is in all three try { long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, inAllDataSourcesHash); @@ -691,7 +1033,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting data source count for entry that is in one data source twice try { long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, inDataSource1twiceHash); @@ -700,7 +1042,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting data source count for entry that is not in any data sources try { long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, "abcdef"); @@ -709,7 +1051,7 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting data source count for null type try { long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(null, "abcdef"); @@ -717,7 +1059,7 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting data source count for null value try { long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, null); @@ -727,211 +1069,211 @@ public class CentralRepoDatamodelTest extends TestCase { Assert.fail(ex); } } - + /** * Test methods related to correlation types - * newCorrelationType(CorrelationAttribute.Type newType) tests: - * - Test with valid data - * - Test with duplicate data - * - Test with null name - * - Test with null db name + * newCorrelationType(CorrelationAttribute.Type newType) tests: + * - Test with valid data + * - Test with duplicate data + * - Test with null name + * - Test with null db name + * - Test with null type + * getDefinedCorrelationTypes() tests: + * - Test that the expected number are returned + * getEnabledCorrelationTypes() tests: + * - Test that the expected number are returned + * getSupportedCorrelationTypes() tests: + * - Test that the expected number are returned + * getCorrelationTypeById(int typeId) tests: + * - Test with valid ID + * - Test with invalid ID + * updateCorrelationType(CorrelationAttribute.Type aType) tests: + * - Test with existing type + * - Test with non-existent type + * - Test updating to null name * - Test with null type - * getDefinedCorrelationTypes() tests: - * - Test that the expected number are returned - * getEnabledCorrelationTypes() tests: - * - Test that the expected number are returned - * getSupportedCorrelationTypes() tests: - * - Test that the expected number are returned - * getCorrelationTypeById(int typeId) tests: - * - Test with valid ID - * - Test with invalid ID - * updateCorrelationType(CorrelationAttribute.Type aType) tests: - * - Test with existing type - * - Test with non-existent type - * - Test updating to null name - * - Test with null type */ - public void atestCorrelationTypes() { - + public void testCorrelationTypes() { + CorrelationAttribute.Type customType; String customTypeName = "customType"; String customTypeDb = "custom_type"; - + // Test new type with valid data - try{ + try { customType = new CorrelationAttribute.Type(customTypeName, customTypeDb, false, false); customType.setId(EamDb.getInstance().newCorrelationType(customType)); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); return; } - + // Test new type with duplicate data - try{ + try { CorrelationAttribute.Type temp = new CorrelationAttribute.Type(customTypeName, customTypeDb, false, false); EamDb.getInstance().newCorrelationType(temp); Assert.fail("newCorrelationType failed to throw exception for duplicate name/db table"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test new type with null name - try{ + try { CorrelationAttribute.Type temp = new CorrelationAttribute.Type(null, "temp_type", false, false); EamDb.getInstance().newCorrelationType(temp); Assert.fail("newCorrelationType failed to throw exception for null name table"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test new type with null db name // The constructor should fail in this case - try{ + try { CorrelationAttribute.Type temp = new CorrelationAttribute.Type("temp", null, false, false); Assert.fail("CorrelationAttribute.Type failed to throw exception for null db table name"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test new type with null type - try{ + try { EamDb.getInstance().newCorrelationType(null); Assert.fail("newCorrelationType failed to throw exception for null type"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting all correlation types - try{ + try { List types = EamDb.getInstance().getDefinedCorrelationTypes(); - + // We expect 6 total - 5 default and the custom one made earlier assertTrue("getDefinedCorrelationTypes returned " + types.size() + " entries - expected 6", types.size() == 6); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting enabled correlation types - try{ + try { List types = EamDb.getInstance().getEnabledCorrelationTypes(); - + // We expect 5 - the custom type is disabled assertTrue("getDefinedCorrelationTypes returned " + types.size() + " enabled entries - expected 5", types.size() == 5); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting supported correlation types - try{ + try { List types = EamDb.getInstance().getSupportedCorrelationTypes(); - + // We expect 5 - the custom type is not supported assertTrue("getDefinedCorrelationTypes returned " + types.size() + " supported entries - expected 5", types.size() == 5); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting the type with a valid ID - try{ + try { CorrelationAttribute.Type temp = EamDb.getInstance().getCorrelationTypeById(customType.getId()); assertTrue("getCorrelationTypeById returned type with unexpected name " + temp.getDisplayName(), customTypeName.equals(temp.getDisplayName())); assertTrue("getCorrelationTypeById returned type with unexpected db table name " + temp.getDbTableName(), customTypeDb.equals(temp.getDbTableName())); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting the type with a invalid ID - try{ + try { CorrelationAttribute.Type temp = EamDb.getInstance().getCorrelationTypeById(5555); Assert.fail("getCorrelationTypeById failed to throw exception for invalid ID"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } // Test updating a valid type - try{ + try { String newName = "newName"; String newDbTable = "new_db_table"; customType.setDisplayName(newName); customType.setDbTableName(newDbTable); customType.setEnabled(true); // These were originally false customType.setSupported(true); - + EamDb.getInstance().updateCorrelationType(customType); - + // Get a fresh copy from the database CorrelationAttribute.Type temp = EamDb.getInstance().getCorrelationTypeById(customType.getId()); - + assertTrue("updateCorrelationType failed to update name", newName.equals(temp.getDisplayName())); assertTrue("updateCorrelationType failed to update db table name", newDbTable.equals(temp.getDbTableName())); assertTrue("updateCorrelationType failed to update enabled status", temp.isEnabled()); assertTrue("updateCorrelationType failed to update supported status", temp.isSupported()); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test updating a type with an invalid ID // Nothing should happen - try{ - CorrelationAttribute.Type temp= new CorrelationAttribute.Type(customTypeName, customTypeDb, false, false); + try { + CorrelationAttribute.Type temp = new CorrelationAttribute.Type(customTypeName, customTypeDb, false, false); temp.setId(12345); EamDb.getInstance().updateCorrelationType(temp); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test updating a type to a null name - try{ + try { customType.setDisplayName(null); EamDb.getInstance().updateCorrelationType(customType); Assert.fail("updateCorrelationType failed to throw exception for null name"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test updating a null type - try{ + try { customType.setDisplayName(null); EamDb.getInstance().updateCorrelationType(customType); Assert.fail("updateCorrelationType failed to throw exception for null type"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } } - + /** - * Test the methods related to organizations + * Test the methods related to organizations * newOrganization(EamOrganization eamOrg) tests: * - Test with just org name - * - Test with org name and poc info - * - Test adding duplicate org - * - Test adding null org - * - Test adding org with null name - * getOrganizations() tests: - * - Test getting the list of orgs -* getOrganizationByID(int orgID) tests: -* - Test with valid ID -* - Test with invalid ID -* updateOrganization(EamOrganization updatedOrganization) tests: -* - Test updating valid org -* - Test updating invalid org -* - Test updating null org -* - Test updating org to null name -* deleteOrganization(EamOrganization organizationToDelete) tests: -* - Test deleting org that isn't in use -* - Test deleting org that is in use -* - Test deleting invalid org -* - Test deleting null org + * - Test with org name and poc info + * - Test adding duplicate org + * - Test adding null org + * - Test adding org with null name + * getOrganizations() tests: + * - Test getting the list of orgs + * getOrganizationByID(int orgID) tests: + * - Test with valid ID + * - Test with invalid ID + * updateOrganization(EamOrganization updatedOrganization) tests: + * - Test updating valid org + * - Test updating invalid org + * - Test updating null org + * - Test updating org to null name + * deleteOrganization(EamOrganization organizationToDelete) tests: + * - Test deleting org that isn't in use + * - Test deleting org that is in use + * - Test deleting invalid org + * - Test deleting null org */ - public void atestOrganizations() { - + public void testOrganizations() { + EamOrganization orgA; String orgAname = "orgA"; EamOrganization orgB; @@ -939,89 +1281,89 @@ public class CentralRepoDatamodelTest extends TestCase { String orgBpocName = "pocName"; String orgBpocEmail = "pocEmail"; String orgBpocPhone = "pocPhone"; - + // Test adding a basic organization - try{ + try { orgA = new EamOrganization(orgAname); orgA.setOrgID((int) EamDb.getInstance().newOrganization(orgA)); assertTrue("Organization ID is still -1 after adding to db", orgA.getOrgID() != -1); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); return; } - + // Test adding an organization with additional fields - try{ + try { orgB = new EamOrganization(orgBname, orgBpocName, orgBpocEmail, orgBpocPhone); orgB.setOrgID((int) EamDb.getInstance().newOrganization(orgB)); assertTrue("Organization ID is still -1 after adding to db", orgB.getOrgID() != -1); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); return; } - + // Test adding a duplicate organization - try{ + try { EamOrganization temp = new EamOrganization(orgAname); EamDb.getInstance().newOrganization(temp); Assert.fail("newOrganization failed to throw exception for duplicate org name"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test adding null organization - try{ + try { EamDb.getInstance().newOrganization(null); Assert.fail("newOrganization failed to throw exception for null org"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test adding organization with null name - try{ + try { EamOrganization temp = new EamOrganization(null); EamDb.getInstance().newOrganization(temp); Assert.fail("newOrganization failed to throw exception for null name"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting organizations // We expect five - the default org, two from setUp, and two from this method - try{ + try { List orgs = EamDb.getInstance().getOrganizations(); assertTrue("getOrganizations returned null list", orgs != null); assertTrue("getOrganizations returned " + orgs.size() + " orgs - expected 5", orgs.size() == 5); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting org with valid ID - try{ + try { EamOrganization temp = EamDb.getInstance().getOrganizationByID(orgB.getOrgID()); assertTrue("getOrganizationByID returned null for valid ID", temp != null); assertTrue("getOrganizationByID returned unexpected name for organization", orgBname.equals(temp.getName())); assertTrue("getOrganizationByID returned unexpected poc name for organization", orgBpocName.equals(temp.getPocName())); assertTrue("getOrganizationByID returned unexpected poc email for organization", orgBpocEmail.equals(temp.getPocEmail())); assertTrue("getOrganizationByID returned unexpected poc phone for organization", orgBpocPhone.equals(temp.getPocPhone())); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting org with invalid ID - try{ + try { EamOrganization temp = EamDb.getInstance().getOrganizationByID(12345); Assert.fail("getOrganizationByID failed to throw exception for invalid ID"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test updating valid org - try{ + try { String newName = "newOrgName"; String newPocName = "newPocName"; String newPocEmail = "newPocEmail"; @@ -1030,141 +1372,141 @@ public class CentralRepoDatamodelTest extends TestCase { orgA.setPocName(newPocName); orgA.setPocEmail(newPocEmail); orgA.setPocPhone(newPocPhone); - + EamDb.getInstance().updateOrganization(orgA); - + EamOrganization copyOfA = EamDb.getInstance().getOrganizationByID(orgA.getOrgID()); - + assertTrue("getOrganizationByID returned null for valid ID", copyOfA != null); assertTrue("updateOrganization failed to update org name", newName.equals(copyOfA.getName())); assertTrue("updateOrganization failed to update poc name", newPocName.equals(copyOfA.getPocName())); assertTrue("updateOrganization failed to update poc email", newPocEmail.equals(copyOfA.getPocEmail())); assertTrue("updateOrganization failed to update poc phone", newPocPhone.equals(copyOfA.getPocPhone())); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test updating invalid org // Shouldn't do anything - try{ + try { EamOrganization temp = new EamOrganization("invalidOrg"); temp.setOrgID(3434); EamDb.getInstance().updateOrganization(temp); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test updating null org - try{ + try { EamDb.getInstance().updateOrganization(null); Assert.fail("updateOrganization failed to throw exception for null org"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test updating org to null name - try{ + try { EamOrganization copyOfA = EamDb.getInstance().getOrganizationByID(orgA.getOrgID()); copyOfA.setName(null); EamDb.getInstance().updateOrganization(copyOfA); Assert.fail("updateOrganization failed to throw exception for null name"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test deleting existing org that isn't in use - try{ + try { EamOrganization orgToDelete = new EamOrganization("deleteThis"); - orgToDelete.setOrgID((int)EamDb.getInstance().newOrganization(orgToDelete)); + orgToDelete.setOrgID((int) EamDb.getInstance().newOrganization(orgToDelete)); int orgCount = EamDb.getInstance().getOrganizations().size(); - + EamDb.getInstance().deleteOrganization(orgToDelete); assertTrue("getOrganizations returned unexpected count after deletion", orgCount - 1 == EamDb.getInstance().getOrganizations().size()); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test deleting existing org that is in use - try{ + try { // Make a new org EamOrganization inUseOrg = new EamOrganization("inUseOrg"); - inUseOrg.setOrgID((int)EamDb.getInstance().newOrganization(inUseOrg)); - + inUseOrg.setOrgID((int) EamDb.getInstance().newOrganization(inUseOrg)); + // Make a reference set that uses it EamGlobalSet tempSet = new EamGlobalSet(inUseOrg.getOrgID(), "inUseOrgTest", "1.0", TskData.FileKnown.BAD, false, fileType); EamDb.getInstance().newReferenceSet(tempSet); - + // It should now throw an exception if we try to delete it EamDb.getInstance().deleteOrganization(inUseOrg); Assert.fail("deleteOrganization failed to throw exception for in use organization"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior - } - + } + // Test deleting non-existent org // Should do nothing - try{ + try { EamOrganization temp = new EamOrganization("temp"); temp.setOrgID(9876); EamDb.getInstance().deleteOrganization(temp); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); - } - + } + // Test deleting null org - try{ + try { EamDb.getInstance().deleteOrganization(null); Assert.fail("deleteOrganization failed to throw exception for null organization"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior - } + } } - + /** - * Tests for adding / retrieving reference instances - * Only the files type is currently implemented + * Tests for adding / retrieving reference instances + * Only the files type is currently implemented * addReferenceInstance(EamGlobalFileInstance eamGlobalFileInstance, CorrelationAttribute.Type correlationType) tests: - * - Test adding multiple valid entries - * - Test invalid reference set ID - * - Test null hash (EamGlobalFileInstance constructor) - * - Test null known status (EamGlobalFileInstance constructor) + * - Test adding multiple valid entries + * - Test invalid reference set ID + * - Test null hash (EamGlobalFileInstance constructor) + * - Test null known status (EamGlobalFileInstance constructor) * - Test null correlation type - * bulkInsertReferenceTypeEntries(Set globalInstances, CorrelationAttribute.Type contentType) tests: - * - Test with large valid list - * - Test with null list - * - Test with invalid reference set ID - * - Test with null correlation type - * getReferenceInstancesByTypeValue(CorrelationAttribute.Type aType, String aValue) tests: - * - Test with valid entries - * - Test with non-existent value - * - Test with invalid type - * - Test with null type - * - Test with null value - * isFileHashInReferenceSet(String hash, int referenceSetID)tests: - * - Test existing hash/ID - * - Test non-existent (but valid) hash/ID - * - Test invalid ID - * - Test null hash - * isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) tests: - * - Test existing value/ID - * - Test non-existent (but valid) value/ID - * - Test invalid ID - * - Test null value - * - Test invalid type ID - * isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) tests: - * - Test notable value - * - Test known value - * - Test non-existent value - * - Test null value - * - Test null type - * - Test invalid type + * bulkInsertReferenceTypeEntries(Set globalInstances, CorrelationAttribute.Type contentType) tests: + * - Test with large valid list + * - Test with null list + * - Test with invalid reference set ID + * - Test with null correlation type + * getReferenceInstancesByTypeValue(CorrelationAttribute.Type aType, String aValue) tests: + * - Test with valid entries + * - Test with non-existent value + * - Test with invalid type + * - Test with null type + * - Test with null value + * isFileHashInReferenceSet(String hash, int referenceSetID)tests: + * - Test existing hash/ID + * - Test non-existent (but valid) hash/ID + * - Test invalid ID + * - Test null hash + * isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) tests: + * - Test existing value/ID + * - Test non-existent (but valid) value/ID + * - Test invalid ID + * - Test null value + * - Test invalid type ID + * isArtifactKnownBadByReference(CorrelationAttribute.Type aType, String value) tests: + * - Test notable value + * - Test known value + * - Test non-existent value + * - Test null value + * - Test null type + * - Test invalid type */ - public void atestReferenceSetInstances(){ - + public void testReferenceSetInstances() { + // After the two initial testing blocks, the reference sets should contain: // notableSet1 - notableHash1, inAllSetsHash // notableSet2 - inAllSetsHash @@ -1175,23 +1517,23 @@ public class CentralRepoDatamodelTest extends TestCase { int notableSet2id; EamGlobalSet knownSet1; int knownSet1id; - - String notableHash1 = "d46feecd663c41648dbf690d9343cf4b"; - String knownHash1 = "39c844daee70485143da4ff926601b5b"; + + String notableHash1 = "d46feecd663c41648dbf690d9343cf4b"; + String knownHash1 = "39c844daee70485143da4ff926601b5b"; String inAllSetsHash = "6449b39bb23c42879fa0c243726e27f7"; - + CorrelationAttribute.Type emailType; - + // Store the email type object for later use - try{ + try { emailType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.EMAIL_TYPE_ID); assertTrue("getCorrelationTypeById(EMAIL_TYPE_ID) returned null", emailType != null); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); return; } - + // Set up a few reference sets try { notableSet1 = new EamGlobalSet(org1.getOrgID(), "notable set 1", "1.0", TskData.FileKnown.BAD, false, fileType); @@ -1200,71 +1542,71 @@ public class CentralRepoDatamodelTest extends TestCase { notableSet2id = EamDb.getInstance().newReferenceSet(notableSet2); knownSet1 = new EamGlobalSet(org1.getOrgID(), "known set 1", "5.5.4", TskData.FileKnown.KNOWN, false, fileType); knownSet1id = EamDb.getInstance().newReferenceSet(knownSet1); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); return; } - + // Test adding file instances with valid data try { EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, inAllSetsHash, TskData.FileKnown.BAD, "comment1"); EamDb.getInstance().addReferenceInstance(temp, fileType); - + temp = new EamGlobalFileInstance(notableSet2id, inAllSetsHash, TskData.FileKnown.BAD, "comment2"); EamDb.getInstance().addReferenceInstance(temp, fileType); - + temp = new EamGlobalFileInstance(knownSet1id, inAllSetsHash, TskData.FileKnown.KNOWN, "comment3"); EamDb.getInstance().addReferenceInstance(temp, fileType); - + temp = new EamGlobalFileInstance(notableSet1id, notableHash1, TskData.FileKnown.BAD, "comment4"); EamDb.getInstance().addReferenceInstance(temp, fileType); - + temp = new EamGlobalFileInstance(knownSet1id, knownHash1, TskData.FileKnown.KNOWN, "comment5"); - EamDb.getInstance().addReferenceInstance(temp, fileType); - }catch (EamDbException ex){ + EamDb.getInstance().addReferenceInstance(temp, fileType); + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test adding file instance with invalid reference set ID try { EamGlobalFileInstance temp = new EamGlobalFileInstance(2345, inAllSetsHash, TskData.FileKnown.BAD, "comment"); - EamDb.getInstance().addReferenceInstance(temp, fileType); + EamDb.getInstance().addReferenceInstance(temp, fileType); Assert.fail("addReferenceInstance failed to throw exception for invalid ID"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test creating file instance with null hash // Since it isn't possible to get a null hash into the EamGlobalFileInstance, skip trying to // call addReferenceInstance and just test the EamGlobalFileInstance constructor try { EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, null, TskData.FileKnown.BAD, "comment"); Assert.fail("EamGlobalFileInstance failed to throw exception for null hash"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test adding file instance with null known status // Since it isn't possible to get a null known status into the EamGlobalFileInstance, skip trying to // call addReferenceInstance and just test the EamGlobalFileInstance constructor try { - EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, inAllSetsHash, null, "comment"); + EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, inAllSetsHash, null, "comment"); Assert.fail("EamGlobalFileInstance failed to throw exception for null type"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test adding file instance with null correlation type try { EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, inAllSetsHash, TskData.FileKnown.BAD, "comment"); - EamDb.getInstance().addReferenceInstance(temp, null); + EamDb.getInstance().addReferenceInstance(temp, null); Assert.fail("addReferenceInstance failed to throw exception for null type"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test bulk insert with large valid set try { // Create a list of global file instances. Make enough that the bulk threshold should be hit once. @@ -1274,256 +1616,256 @@ public class CentralRepoDatamodelTest extends TestCase { String hash = bulkTestHash + String.valueOf(i); instances.add(new EamGlobalFileInstance(notableSet2id, hash, TskData.FileKnown.BAD, null)); } - + // Insert the list EamDb.getInstance().bulkInsertReferenceTypeEntries(instances, fileType); - + // There's no way to get a count of the number of entries in the database, so just do a spot check - if(dbSettingsSqlite.getBulkThreshold() > 10){ + if (dbSettingsSqlite.getBulkThreshold() > 10) { String hash = bulkTestHash + "10"; assertTrue("Sample bulk insert instance not found", EamDb.getInstance().isFileHashInReferenceSet(hash, notableSet2id)); } - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test bulk add file instance with null list try { - EamDb.getInstance().bulkInsertReferenceTypeEntries(null, fileType); + EamDb.getInstance().bulkInsertReferenceTypeEntries(null, fileType); Assert.fail("bulkInsertReferenceTypeEntries failed to throw exception for null list"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test bulk add file instance with invalid reference set ID try { Set tempSet = new HashSet<>(Arrays.asList(new EamGlobalFileInstance(2345, inAllSetsHash, TskData.FileKnown.BAD, "comment"))); EamDb.getInstance().bulkInsertReferenceTypeEntries(tempSet, fileType); Assert.fail("bulkInsertReferenceTypeEntries failed to throw exception for invalid ID"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test bulk add file instance with null correlation type try { Set tempSet = new HashSet<>(Arrays.asList(new EamGlobalFileInstance(notableSet1id, inAllSetsHash, TskData.FileKnown.BAD, "comment"))); - EamDb.getInstance().bulkInsertReferenceTypeEntries(tempSet, null); + EamDb.getInstance().bulkInsertReferenceTypeEntries(tempSet, null); Assert.fail("bulkInsertReferenceTypeEntries failed to throw exception for null type"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting reference instances with valid data try { List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(fileType, inAllSetsHash); assertTrue("getReferenceInstancesByTypeValue returned " + temp.size() + " instances - expected 3", temp.size() == 3); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting reference instances with non-existent data try { List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(fileType, "testHash"); assertTrue("getReferenceInstancesByTypeValue returned " + temp.size() + " instances for non-existent value - expected 0", temp.isEmpty()); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting reference instances an invalid type (the email table is not yet implemented) try { List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(emailType, inAllSetsHash); Assert.fail("getReferenceInstancesByTypeValue failed to throw exception for invalid table"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting reference instances with null type try { List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(null, inAllSetsHash); Assert.fail("getReferenceInstancesByTypeValue failed to throw exception for null type"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test getting reference instances with null value try { List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(fileType, null); assertTrue("getReferenceInstancesByTypeValue returned non-empty list given null value", temp.isEmpty()); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test checking existing hash/ID try { assertTrue("isFileHashInReferenceSet returned false for valid data", EamDb.getInstance().isFileHashInReferenceSet(knownHash1, knownSet1id)); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test checking non-existent (but valid) hash/ID try { assertFalse("isFileHashInReferenceSet returned true for non-existent data", EamDb.getInstance().isFileHashInReferenceSet(knownHash1, notableSet1id)); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test checking invalid reference set ID try { assertFalse("isFileHashInReferenceSet returned true for invalid data", EamDb.getInstance().isFileHashInReferenceSet(knownHash1, 5678)); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test checking null hash try { assertFalse("isFileHashInReferenceSet returned true for null hash", EamDb.getInstance().isFileHashInReferenceSet(null, knownSet1id)); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test checking existing hash/ID try { - assertTrue("isValueInReferenceSet returned false for valid data", + assertTrue("isValueInReferenceSet returned false for valid data", EamDb.getInstance().isValueInReferenceSet(knownHash1, knownSet1id, fileType.getId())); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test checking non-existent (but valid) hash/ID try { - assertFalse("isValueInReferenceSet returned true for non-existent data", + assertFalse("isValueInReferenceSet returned true for non-existent data", EamDb.getInstance().isValueInReferenceSet(knownHash1, notableSet1id, fileType.getId())); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test checking invalid reference set ID try { - assertFalse("isValueInReferenceSet returned true for invalid data", + assertFalse("isValueInReferenceSet returned true for invalid data", EamDb.getInstance().isValueInReferenceSet(knownHash1, 5678, fileType.getId())); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test checking null hash try { - assertFalse("isValueInReferenceSet returned true for null value", + assertFalse("isValueInReferenceSet returned true for null value", EamDb.getInstance().isValueInReferenceSet(null, knownSet1id, fileType.getId())); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test checking invalid type try { EamDb.getInstance().isValueInReferenceSet(knownHash1, knownSet1id, emailType.getId()); Assert.fail("isValueInReferenceSet failed to throw exception for invalid type"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test known bad with notable data try { - assertTrue("isArtifactKnownBadByReference returned false for notable value", + assertTrue("isArtifactKnownBadByReference returned false for notable value", EamDb.getInstance().isArtifactKnownBadByReference(fileType, notableHash1)); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test known bad with known data try { - assertFalse("isArtifactKnownBadByReference returned true for known value", + assertFalse("isArtifactKnownBadByReference returned true for known value", EamDb.getInstance().isArtifactKnownBadByReference(fileType, knownHash1)); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test known bad with non-existent data try { - assertFalse("isArtifactKnownBadByReference returned true for non-existent value", + assertFalse("isArtifactKnownBadByReference returned true for non-existent value", EamDb.getInstance().isArtifactKnownBadByReference(fileType, "abcdef")); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test known bad with null hash try { - assertFalse("isArtifactKnownBadByReference returned true for null value", + assertFalse("isArtifactKnownBadByReference returned true for null value", EamDb.getInstance().isArtifactKnownBadByReference(fileType, null)); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test known bad with null type try { EamDb.getInstance().isArtifactKnownBadByReference(null, knownHash1); Assert.fail("isArtifactKnownBadByReference failed to throw exception from null type"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test known bad with invalid type try { assertFalse("isArtifactKnownBadByReference returned true for invalid type", EamDb.getInstance().isArtifactKnownBadByReference(emailType, null)); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } } - + /** - * Test method for the methods related to reference sets (does not include instance testing) - * Only the files type is currently implemented - * newReferenceSet(EamGlobalSet eamGlobalSet) tests: - * - Test creating notable reference set - * - Test creating known reference set - * - Test creating duplicate reference set - * - Test creating almost duplicate reference set - * - Test with invalid org ID - * - Test with null name - * - Test with null version - * - Test with null known status + * Test method for the methods related to reference sets (does not include + * instance testing) Only the files type is currently implemented + * newReferenceSet(EamGlobalSet eamGlobalSet) tests: + * - Test creating notable reference set + * - Test creating known reference set + * - Test creating duplicate reference set + * - Test creating almost duplicate reference set + * - Test with invalid org ID + * - Test with null name + * - Test with null version + * - Test with null known status * - Test with null file type - * referenceSetIsValid(int referenceSetID, String referenceSetName, String version) tests: - * - Test on existing reference set - * - Test on invalid reference set - * - Test with null name - * - Test with null version - * referenceSetExists(String referenceSetName, String version) tests: - * - Test on existing reference set - * - Test on invalid reference set - * - Test with null name - * - Test with null version - * getReferenceSetByID(int globalSetID) tests: - * - Test with valid ID - * - Test with invalid ID - * getAllReferenceSets(CorrelationAttribute.Type correlationType) tests: - * - Test getting all file sets - * - Test getting all email sets - * - Test with null type parameter - * deleteReferenceSet(int referenceSetID) tests: - * - Test on valid reference set ID - * - Test on invalid reference set ID - * getReferenceSetOrganization(int referenceSetID) tests: - * - Test on valid reference set ID - * - Test on invalid reference set ID + * referenceSetIsValid(int referenceSetID, String referenceSetName, String version) tests: + * - Test on existing reference set + * - Test on invalid reference set + * - Test with null name + * - Test with null version + * referenceSetExists(String referenceSetName, String version) tests: + * - Test on existing reference set + * - Test on invalid reference set + * - Test with null name + * - Test with null version + * getReferenceSetByID(int globalSetID) tests: + * - Test with valid ID + * - Test with invalid ID + * getAllReferenceSets(CorrelationAttribute.Type correlationType) tests: + * - Test getting all file sets + * - Test getting all email sets + * - Test with null type parameter + * deleteReferenceSet(int referenceSetID) tests: + * - Test on valid reference set ID + * - Test on invalid reference set ID + * getReferenceSetOrganization(int referenceSetID) tests: + * - Test on valid reference set ID + * - Test on invalid reference set ID */ - public void atestReferenceSets() { + public void testReferenceSets() { String set1name = "referenceSet1"; String set1version = "1.0"; EamGlobalSet set1; @@ -1533,202 +1875,201 @@ public class CentralRepoDatamodelTest extends TestCase { int set2id; EamGlobalSet set3; int set3id; - - + // Test creating a notable reference set try { set1 = new EamGlobalSet(org1.getOrgID(), set1name, set1version, TskData.FileKnown.BAD, false, fileType); set1id = EamDb.getInstance().newReferenceSet(set1); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); return; } - + // Test creating a known reference set try { set2 = new EamGlobalSet(org2.getOrgID(), set2name, "", TskData.FileKnown.KNOWN, false, fileType); set2id = EamDb.getInstance().newReferenceSet(set2); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); return; } - + // Test creating a reference set with the same name and version try { EamGlobalSet temp = new EamGlobalSet(org1.getOrgID(), set1name, "1.0", TskData.FileKnown.BAD, false, fileType); EamDb.getInstance().newReferenceSet(temp); Assert.fail("newReferenceSet failed to throw exception from duplicate name/version pair"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test creating a reference set with the same name but different version try { set3 = new EamGlobalSet(org1.getOrgID(), set1name, "2.0", TskData.FileKnown.BAD, false, fileType); set3id = EamDb.getInstance().newReferenceSet(set3); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); return; } - + // Test creating a reference set with invalid org ID try { EamGlobalSet temp = new EamGlobalSet(5000, "tempName", "", TskData.FileKnown.BAD, false, fileType); EamDb.getInstance().newReferenceSet(temp); Assert.fail("newReferenceSet failed to throw exception from invalid org ID"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test creating a reference set with null name try { EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), null, "", TskData.FileKnown.BAD, false, fileType); EamDb.getInstance().newReferenceSet(temp); Assert.fail("newReferenceSet failed to throw exception from null name"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test creating a reference set with null version try { EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), "tempName", null, TskData.FileKnown.BAD, false, fileType); EamDb.getInstance().newReferenceSet(temp); Assert.fail("newReferenceSet failed to throw exception from null version"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test creating a reference set with null file known status try { EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), "tempName", "", null, false, fileType); EamDb.getInstance().newReferenceSet(temp); Assert.fail("newReferenceSet failed to throw exception from null file known status"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test creating a reference set with null file type try { EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), "tempName", "", TskData.FileKnown.BAD, false, null); EamDb.getInstance().newReferenceSet(temp); Assert.fail("newReferenceSet failed to throw exception from null file type"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior } - + // Test validation with a valid reference set try { assertTrue("referenceSetIsValid returned false for valid reference set", EamDb.getInstance().referenceSetIsValid(set1id, set1name, set1version)); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test validation with an invalid reference set try { assertFalse("referenceSetIsValid returned true for invalid reference set", EamDb.getInstance().referenceSetIsValid(5000, set1name, set1version)); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test validation with a null name try { assertFalse("referenceSetIsValid returned true with null name", EamDb.getInstance().referenceSetIsValid(set1id, null, set1version)); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test validation with a null version try { assertFalse("referenceSetIsValid returned true with null version", EamDb.getInstance().referenceSetIsValid(set1id, set1name, null)); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test existence with a valid reference set try { assertTrue("referenceSetExists returned false for valid reference set", EamDb.getInstance().referenceSetExists(set1name, set1version)); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test existence with an invalid reference set try { assertFalse("referenceSetExists returned true for invalid reference set", EamDb.getInstance().referenceSetExists(set1name, "5.5")); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test existence with null name try { assertFalse("referenceSetExists returned true for null name", EamDb.getInstance().referenceSetExists(null, "1.0")); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test existence with null version try { assertFalse("referenceSetExists returned true for null version", EamDb.getInstance().referenceSetExists(set1name, null)); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting global set with valid ID try { EamGlobalSet temp = EamDb.getInstance().getReferenceSetByID(set1id); assertTrue("getReferenceSetByID returned null for valid ID", temp != null); - assertTrue("getReferenceSetByID returned set with incorrect name and/or version", + assertTrue("getReferenceSetByID returned set with incorrect name and/or version", set1name.equals(temp.getSetName()) && set1version.equals(temp.getVersion())); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting global set with invalid ID try { EamGlobalSet temp = EamDb.getInstance().getReferenceSetByID(1234); assertTrue("getReferenceSetByID returned non-null result for invalid ID", temp == null); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting all file reference sets try { List referenceSets = EamDb.getInstance().getAllReferenceSets(fileType); assertTrue("getAllReferenceSets(FILES) returned unexpected number", referenceSets.size() == 3); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test getting all email reference sets try { List referenceSets = EamDb.getInstance().getAllReferenceSets(EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.EMAIL_TYPE_ID)); assertTrue("getAllReferenceSets(EMAIL) returned unexpected number", referenceSets.isEmpty()); - }catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); - } - + } + // Test null argument to getAllReferenceSets try { EamDb.getInstance().getAllReferenceSets(null); Assert.fail("getAllReferenceSets failed to throw exception from null type argument"); - }catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior - } - + } + // Test deleting an existing reference set // First: create a new reference set, check that it's in the database, and get the number of reference sets // Second: delete the reference set, check that it is no longer in the database, and the total number of sets decreased by one @@ -1737,66 +2078,66 @@ public class CentralRepoDatamodelTest extends TestCase { int setToDeleteID = EamDb.getInstance().newReferenceSet(setToDelete); assertTrue("setToDelete wasn't found in database", EamDb.getInstance().referenceSetIsValid(setToDeleteID, setToDelete.getSetName(), setToDelete.getVersion())); int currentCount = EamDb.getInstance().getAllReferenceSets(fileType).size(); - - EamDb.getInstance().deleteReferenceSet(setToDeleteID); + + EamDb.getInstance().deleteReferenceSet(setToDeleteID); assertFalse("Deleted reference set was found in database", EamDb.getInstance().referenceSetIsValid(setToDeleteID, setToDelete.getSetName(), setToDelete.getVersion())); assertTrue("Unexpected number of reference sets in database after deletion", currentCount - 1 == EamDb.getInstance().getAllReferenceSets(fileType).size()); - - } catch (EamDbException ex){ + + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); - } - + } + // Test deleting a non-existent reference set // The expectation is that nothing will happen try { - int currentCount = EamDb.getInstance().getAllReferenceSets(fileType).size(); - EamDb.getInstance().deleteReferenceSet(1234); - assertTrue("Number of reference sets changed after deleting non-existent set", currentCount == EamDb.getInstance().getAllReferenceSets(fileType).size()); - } catch (EamDbException ex){ + int currentCount = EamDb.getInstance().getAllReferenceSets(fileType).size(); + EamDb.getInstance().deleteReferenceSet(1234); + assertTrue("Number of reference sets changed after deleting non-existent set", currentCount == EamDb.getInstance().getAllReferenceSets(fileType).size()); + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); - } - + } + // Test getting reference set organization for valid ID with org set try { EamOrganization org = EamDb.getInstance().getReferenceSetOrganization(set1id); assertTrue("getReferenceSetOrganization returned null for valid set", org != null); assertTrue("getReferenceSetOrganization returned the incorrect organization", org.getOrgID() == org1.getOrgID()); - } catch (EamDbException ex){ + } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); - } - + } + // Test getting reference set organization for non-existent reference set try { EamOrganization org = EamDb.getInstance().getReferenceSetOrganization(4567); Assert.fail("getReferenceSetOrganization failed to throw exception for invalid reference set ID"); - } catch (EamDbException ex){ + } catch (EamDbException ex) { // This is the expected behavior - } + } } - + /** * Test method for the methods related to the data sources table - * newDataSource(CorrelationDataSource eamDataSource) tests: + * newDataSource(CorrelationDataSource eamDataSource) tests: + * - Test with valid data + * - Test with duplicate data + * - Test with duplicate device ID and name but different case + * - Test with invalid case ID + * - Test with null device ID + * - Test with null name + * getDataSource(CorrelationCase correlationCase, String dataSourceDeviceId) tests: * - Test with valid data - * - Test with duplicate data - * - Test with duplicate device ID and name but different case - * - Test with invalid case ID + * - Test with non-existent data + * - Test with null correlationCase * - Test with null device ID - * - Test with null name - * getDataSource(CorrelationCase correlationCase, String dataSourceDeviceId) tests: - * - Test with valid data - * - Test with non-existent data - * - Test with null correlationCase - * - Test with null device ID - * List getDataSources()tests: - * - Test that the count and device IDs are as expected - * Long getCountUniqueDataSources() tests: - * - Test that the result is as expected - */ - public void atestDataSources() { + * getDataSources()tests: + * - Test that the count and device IDs are as expected + * getCountUniqueDataSources() tests: + * - Test that the result is as expected + */ + public void testDataSources() { final String dataSourceAname = "dataSourceA"; final String dataSourceAid = "dataSourceA_deviceID"; CorrelationDataSource dataSourceA; @@ -1811,7 +2152,7 @@ public class CentralRepoDatamodelTest extends TestCase { Assert.fail(ex); return; } - + // Test creating a data source with the same case, name, and ID try { CorrelationDataSource temp = new CorrelationDataSource(case2.getID(), dataSourceAid, dataSourceAname); @@ -1820,7 +2161,7 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { // This is the expected behavior } - + // Test creating a data source with the same name and ID but different case try { dataSourceB = new CorrelationDataSource(case1.getID(), dataSourceAid, dataSourceAname); @@ -1909,10 +2250,10 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex); } - + // Test the data source count try { - assertTrue("getCountUniqueDataSources returned unexpected number of data sources", + assertTrue("getCountUniqueDataSources returned unexpected number of data sources", EamDb.getInstance().getCountUniqueDataSources() == 5); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); @@ -1922,23 +2263,35 @@ public class CentralRepoDatamodelTest extends TestCase { /** * Test method for the methods related to the cases table - * newCase(CorrelationCase eamCase) tests: - Test valid data - Test null - * UUID - Test null case name - Test repeated UUID newCase(Case autopsyCase) - * tests: - Test valid data - Test null autopsyCase - * updateCase(CorrelationCase eamCase) tests: - Test with valid data, - * checking all fields - Test null eamCase getCase(Case autopsyCase) tests: - * - Test with current Autopsy case getCaseByUUID(String caseUUID) - * getCases() - Test with UUID that is in the database - Test with UUID that - * is not in the database - Test with null UUID - * bulkInsertCases(List cases) - Test on a list of cases - * larger than the bulk insert threshold. - Test on a null list + * newCase(CorrelationCase eamCase) tests: + * - Test valid data + * - Test null UUID + * - Test null case name + * - Test repeated UUID + * newCase(Case autopsyCase) tests: + * - Test valid data + * - Test null autopsyCase + * updateCase(CorrelationCase eamCase) tests: + * - Test with valid data, checking all fields + * - Test null eamCase + * getCase(Case autopsyCase) tests: + * - Test with current Autopsy case + * getCaseByUUID(String caseUUID) + * - Test with UUID that is in the database + * - Test with UUID that is not in the database + * - Test with null UUID + * getCases() tests: + * - Test getting all cases, checking the count and fields + * bulkInsertCases(List cases) + * - Test on a list of cases larger than the bulk insert threshold. + * - Test on a null list */ - public void atestCases() { + public void testCases() { final String caseAname = "caseA"; final String caseAuuid = "caseA_uuid"; CorrelationCase caseA; CorrelationCase caseB; - + try { // Set up an Autopsy case for testing try { @@ -2148,12 +2501,12 @@ public class CentralRepoDatamodelTest extends TestCase { try { Case.closeCurrentCase(); // This seems to help in allowing the Autopsy case to be deleted - try{ - Thread.sleep(2000); - } catch (Exception ex){ + try { + Thread.sleep(2000); + } catch (Exception ex) { } - } catch (CaseActionException ex){ + } catch (CaseActionException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); } @@ -2162,15 +2515,21 @@ public class CentralRepoDatamodelTest extends TestCase { /** * Test method for the three methods related to the db_info table - * newDbInfo(String name, String value) tests: - Test valid data - Test null - * name - Test null value getDbInfo(String name) - Test getting value for - * existing name - Test getting value for non-existing name - Test getting - * value for null name updateDbInfo(String name, String value) - Test - * updating existing name to valid new value - Test updating existing name - * to null value - Test updating null name - Test updating non-existing name - * to new value + * newDbInfo(String name, String value) tests: + * - Test valid data + * - Test null name + * - Test null value + * getDbInfo(String name) + * - Test getting value for existing name + * - Test getting value for non-existing name + * - Test getting value for null name + * updateDbInfo(String name, String value) + * - Test updating existing name to valid new value + * - Test updating existing name to null value + * - Test updating null name + * - Test updating non-existing name to new value */ - public void atestDbInfo() { + public void testDbInfo() { final String name1 = "testName1"; final String name2 = "testName2"; final String name3 = "testName3"; From 66d3694159df5b393c54c30144b44ecf7e11fa9a Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 6 Feb 2018 14:51:14 -0500 Subject: [PATCH 47/52] Some codacy fixes --- .../datamodel/CentralRepoDatamodelTest.java | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index b2e05d8694..29a3abee71 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -352,7 +352,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting notable instances with null type try { - List attrs = EamDb.getInstance().getArtifactInstancesKnownBad(null, notableHashInOneCaseKnownOther); + EamDb.getInstance().getArtifactInstancesKnownBad(null, notableHashInOneCaseKnownOther); Assert.fail("getArtifactInstancesKnownBad failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior @@ -361,7 +361,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting notable instances with null value (should work fine) try { List attrs = EamDb.getInstance().getArtifactInstancesKnownBad(fileType, null); - assertTrue("getArtifactInstancesKnownBad returned " + attrs.size() + " values - expected ", attrs.size() == 0); + assertTrue("getArtifactInstancesKnownBad returned " + attrs.size() + " values - expected ", attrs.isEmpty()); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); @@ -857,7 +857,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instances with null type try { - List instances = EamDb.getInstance().getArtifactInstancesByTypeValue(null, inAllDataSourcesHash); + EamDb.getInstance().getArtifactInstancesByTypeValue(null, inAllDataSourcesHash); Assert.fail("getArtifactInstancesByTypeValue failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior @@ -901,7 +901,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instances with null path try { - List instances = EamDb.getInstance().getArtifactInstancesByPath(fileType, null); + EamDb.getInstance().getArtifactInstancesByPath(fileType, null); Assert.fail("getArtifactInstancesByPath failed to throw exception for null path"); } catch (EamDbException ex) { // This is the expected behavior @@ -927,7 +927,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instance count with null type try { - long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(null, inAllDataSourcesHash); + EamDb.getInstance().getCountArtifactInstancesByTypeValue(null, inAllDataSourcesHash); Assert.fail("getCountArtifactInstancesByTypeValue failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior @@ -935,7 +935,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instance count with null value try { - long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, null); + EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, null); Assert.fail("getCountArtifactInstancesByTypeValue failed to throw exception for null value"); } catch (EamDbException ex) { // This is the expected behavior @@ -984,7 +984,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting frequency with null type try { CorrelationAttribute attr = new CorrelationAttribute(null, "randomValue"); - int freq = EamDb.getInstance().getFrequencyPercentage(attr); + EamDb.getInstance().getFrequencyPercentage(attr); Assert.fail("getFrequencyPercentage failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior @@ -992,7 +992,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting frequency with null attribute try { - int freq = EamDb.getInstance().getFrequencyPercentage(null); + EamDb.getInstance().getFrequencyPercentage(null); Assert.fail("getFrequencyPercentage failed to throw exception for null attribute"); } catch (EamDbException ex) { // This is the expected behavior @@ -1054,7 +1054,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting data source count for null type try { - long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(null, "abcdef"); + EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(null, "abcdef"); Assert.fail("getCountUniqueCaseDataSourceTuplesHavingTypeValue failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior @@ -1189,7 +1189,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting the type with a invalid ID try { - CorrelationAttribute.Type temp = EamDb.getInstance().getCorrelationTypeById(5555); + EamDb.getInstance().getCorrelationTypeById(5555); Assert.fail("getCorrelationTypeById failed to throw exception for invalid ID"); } catch (EamDbException ex) { // This is the expected behavior @@ -1356,7 +1356,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting org with invalid ID try { - EamOrganization temp = EamDb.getInstance().getOrganizationByID(12345); + EamDb.getInstance().getOrganizationByID(12345); Assert.fail("getOrganizationByID failed to throw exception for invalid ID"); } catch (EamDbException ex) { // This is the expected behavior @@ -1676,7 +1676,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting reference instances an invalid type (the email table is not yet implemented) try { - List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(emailType, inAllSetsHash); + EamDb.getInstance().getReferenceInstancesByTypeValue(emailType, inAllSetsHash); Assert.fail("getReferenceInstancesByTypeValue failed to throw exception for invalid table"); } catch (EamDbException ex) { // This is the expected behavior @@ -1684,7 +1684,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting reference instances with null type try { - List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(null, inAllSetsHash); + EamDb.getInstance().getReferenceInstancesByTypeValue(null, inAllSetsHash); Assert.fail("getReferenceInstancesByTypeValue failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior @@ -1872,9 +1872,7 @@ public class CentralRepoDatamodelTest extends TestCase { int set1id; String set2name = "referenceSet2"; EamGlobalSet set2; - int set2id; EamGlobalSet set3; - int set3id; // Test creating a notable reference set try { @@ -1889,7 +1887,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test creating a known reference set try { set2 = new EamGlobalSet(org2.getOrgID(), set2name, "", TskData.FileKnown.KNOWN, false, fileType); - set2id = EamDb.getInstance().newReferenceSet(set2); + EamDb.getInstance().newReferenceSet(set2); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); @@ -1908,7 +1906,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test creating a reference set with the same name but different version try { set3 = new EamGlobalSet(org1.getOrgID(), set1name, "2.0", TskData.FileKnown.BAD, false, fileType); - set3id = EamDb.getInstance().newReferenceSet(set3); + EamDb.getInstance().newReferenceSet(set3); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); @@ -2111,7 +2109,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting reference set organization for non-existent reference set try { - EamOrganization org = EamDb.getInstance().getReferenceSetOrganization(4567); + EamDb.getInstance().getReferenceSetOrganization(4567); Assert.fail("getReferenceSetOrganization failed to throw exception for invalid reference set ID"); } catch (EamDbException ex) { // This is the expected behavior @@ -2219,7 +2217,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting a data source with a null case try { - CorrelationDataSource temp = EamDb.getInstance().getDataSource(null, dataSourceAid); + EamDb.getInstance().getDataSource(null, dataSourceAid); Assert.fail("getDataSource did not throw exception from null case"); } catch (EamDbException ex) { // This is the expected behavior @@ -2316,7 +2314,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test null uuid try { CorrelationCase tempCase = new CorrelationCase(null, "nullUuidCase"); - tempCase = EamDb.getInstance().newCase(tempCase); + EamDb.getInstance().newCase(tempCase); Assert.fail("newCase did not throw expected exception from null uuid"); } catch (EamDbException ex) { // This is the expected behavior @@ -2325,7 +2323,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test null name try { CorrelationCase tempCase = new CorrelationCase("nullCaseUuid", null); - tempCase = EamDb.getInstance().newCase(tempCase); + EamDb.getInstance().newCase(tempCase); Assert.fail("newCase did not throw expected exception from null name"); } catch (EamDbException ex) { // This is the expected behavior @@ -2359,7 +2357,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test null Autopsy case try { Case nullCase = null; - CorrelationCase tempCase = EamDb.getInstance().newCase(nullCase); + EamDb.getInstance().newCase(nullCase); Assert.fail("newCase did not throw expected exception from null case"); } catch (EamDbException ex) { // This is the expected behavior From b58a7b18536930b36e4b27305e0b5933f169251a Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 7 Feb 2018 07:50:20 -0500 Subject: [PATCH 48/52] codacy fix and removed a few unnecessary return statements. --- .../datamodel/CentralRepoDatamodelTest.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 29a3abee71..644372feab 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -227,7 +227,6 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); - return; } // Add two instances with one notable, one known @@ -253,7 +252,6 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); - return; } // Add an artifact and then update its status @@ -271,7 +269,6 @@ public class CentralRepoDatamodelTest extends TestCase { } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); - return; } // Try to update artifact with two CorrelationAttributeInstance instances @@ -893,7 +890,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instances with null type try { - List instances = EamDb.getInstance().getArtifactInstancesByPath(null, inAllDataSourcesPath); + EamDb.getInstance().getArtifactInstancesByPath(null, inAllDataSourcesPath); Assert.fail("getArtifactInstancesByPath failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior From 4cd548e456532e502172f4b7bcaa8138a16e7da6 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 7 Feb 2018 22:43:56 -0500 Subject: [PATCH 49/52] 3536 - Look at all Content in node so that artifacts are not shown --- .../corecomponents/DataContentViewerHex.java | 2 +- .../DataContentViewerString.java | 3 +- .../DataContentViewerUtility.java | 54 +++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerUtility.java diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index a7a97e4b75..7a4df69e9d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -453,7 +453,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont return; } - Content content = (selectedNode).getLookup().lookup(Content.class); + Content content = DataContentViewerUtility.getDefaultContent(selectedNode); if (content == null) { resetComponent(); return; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java index 14cb2eb2c1..936ff3c46b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java @@ -452,8 +452,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC return; } - Lookup lookup = selectedNode.getLookup(); - Content content = lookup.lookup(Content.class); + Content content = DataContentViewerUtility.getDefaultContent(selectedNode); if (content != null) { this.setDataView(content, 0); return; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerUtility.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerUtility.java new file mode 100755 index 0000000000..53491b407e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerUtility.java @@ -0,0 +1,54 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 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.corecomponents; + +import org.sleuthkit.datamodel.Content; +import org.openide.nodes.Node; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * Utility classes for content viewers. + * In theory, this would live in the contentviewer package, + * but the initial method was needed only be viewers in + * corecomponents and therefore can stay out of public API. + */ +class DataContentViewerUtility { + /** + * Returns the first non-Blackboard Artifact from a Node. + * Needed for (at least) Hex and Strings that want to view + * all types of content (not just AbstractFile), but don't want + * to display an artifact unless that's the only thing there. + * Scenario is hash hit or interesting item hit. + * + * @param node Node passed into content viewer + * @return highest priority content or null if there is no content + */ + static Content getDefaultContent(Node node) { + Content bbContentSeen = null; + for (Content content : (node).getLookup().lookupAll(Content.class)) { + if (content instanceof BlackboardArtifact) { + bbContentSeen = content; + } + else { + return content; + } + } + return bbContentSeen; + } +} From 4bcd518f4bb7f71b3e42b3499344e969a5a1b31c Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Thu, 8 Feb 2018 15:04:29 -0500 Subject: [PATCH 50/52] Disalbe the run time test in nightly. --- test/script/regression.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/script/regression.py b/test/script/regression.py index afe1ea4976..53f8810ff8 100644 --- a/test/script/regression.py +++ b/test/script/regression.py @@ -810,7 +810,7 @@ class TestConfiguration(object): if parsed_config.getElementsByTagName("singleUser_golddir"): self.singleUser_gold = parsed_config.getElementsByTagName("singleUser_golddir")[0].getAttribute("value").encode().decode("utf_8") if parsed_config.getElementsByTagName("timing"): - self.timing = parsed_config.getElementsByTagName("timing")[0].getAttribute("value").encode().decode("utf_8") + self.timing = ("True" == parsed_config.getElementsByTagName("timing")[0].getAttribute("value").encode().decode("utf_8")) if parsed_config.getElementsByTagName("autopsyPlatform"): self.autopsyPlatform = parsed_config.getElementsByTagName("autopsyPlatform")[0].getAttribute("value").encode().decode("utf_8") # Multi-user settings @@ -1392,7 +1392,7 @@ class Logs(object): try: Logs._fill_ingest_data(test_data) except Exception as e: - Errors.print_error("Error: Unknown fatal error when filling test_config data.") + Errors.print_error("Error when filling test_config data.") Errors.print_error(str(e) + "\n") logging.critical(traceback.format_exc()) # If running in verbose mode (-v) @@ -1469,7 +1469,6 @@ class Logs(object): test_data.heap_space = search_logs("Heap memory usage:", test_data)[0].rstrip().split(": ")[1] ingest_line = search_logs("Ingest (including enqueue)", test_data)[0] test_data.total_ingest_time = get_word_at(ingest_line, 6).rstrip() - message_line_count = find_msg_in_log_set("Ingest messages count:", test_data) test_data.indexed_files = message_line_count From 5cf44c5b5523f99e6ed5f54f1545596b6a74d3f8 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 9 Feb 2018 11:04:44 -0500 Subject: [PATCH 51/52] Fix codacy warnings --- .../datamodel/CentralRepoDatamodelTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 644372feab..cce1e807e1 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -792,7 +792,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test adding instance with null path // This will fail in the CorrelationAttributeInstance constructor try { - CorrelationAttributeInstance inst = new CorrelationAttributeInstance(case1, dataSource1fromCase1, null); + new CorrelationAttributeInstance(case1, dataSource1fromCase1, null); Assert.fail("CorrelationAttributeInstance failed to throw exception for null path"); } catch (EamDbException ex) { // This is the expected behavior @@ -821,7 +821,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test null value // This will fail in the CorrelationAttribute constructor try { - CorrelationAttribute attr = new CorrelationAttribute(fileType, null); + new CorrelationAttribute(fileType, null); Assert.fail("addArtifact failed to throw exception for null value"); } catch (EamDbException ex) { // This is the expected behavior @@ -1127,7 +1127,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test new type with null db name // The constructor should fail in this case try { - CorrelationAttribute.Type temp = new CorrelationAttribute.Type("temp", null, false, false); + new CorrelationAttribute.Type("temp", null, false, false); Assert.fail("CorrelationAttribute.Type failed to throw exception for null db table name"); } catch (EamDbException ex) { // This is the expected behavior @@ -1579,7 +1579,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Since it isn't possible to get a null hash into the EamGlobalFileInstance, skip trying to // call addReferenceInstance and just test the EamGlobalFileInstance constructor try { - EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, null, TskData.FileKnown.BAD, "comment"); + new EamGlobalFileInstance(notableSet1id, null, TskData.FileKnown.BAD, "comment"); Assert.fail("EamGlobalFileInstance failed to throw exception for null hash"); } catch (EamDbException ex) { // This is the expected behavior @@ -1589,7 +1589,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Since it isn't possible to get a null known status into the EamGlobalFileInstance, skip trying to // call addReferenceInstance and just test the EamGlobalFileInstance constructor try { - EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, inAllSetsHash, null, "comment"); + new EamGlobalFileInstance(notableSet1id, inAllSetsHash, null, "comment"); Assert.fail("EamGlobalFileInstance failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior From be029b026a5da4f2b6e78b55c48687571a0a159c Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Fri, 9 Feb 2018 14:54:50 -0500 Subject: [PATCH 52/52] Update regresion.py to use the new datetime format in logs. --- test/script/regression.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/script/regression.py b/test/script/regression.py index 53f8810ff8..3e9ee2e585 100644 --- a/test/script/regression.py +++ b/test/script/regression.py @@ -1454,10 +1454,10 @@ class Logs(object): Errors.print_error("Error: Unable to open autopsy.log.0.") Errors.print_error(str(e) + "\n") logging.warning(traceback.format_exc()) - # Start date must look like: "Fri Mar 27 13:27:34 EDT 2015" + # Start date must look like: "" # End date must look like: "Mon Jul 16 13:02:42 2012" # *** If logging time format ever changes this will break *** - start = datetime.datetime.strptime(test_data.start_date, "%a %b %d %H:%M:%S %Z %Y") + start = datetime.datetime.strptime(test_data.start_date, "%Y-%m-%d %H:%M:%S.%f") end = datetime.datetime.strptime(test_data.end_date, "%a %b %d %H:%M:%S %Y") test_data.total_test_time = str(end - start)