diff --git a/Core/build.xml b/Core/build.xml index 65f26273a7..65eeb92964 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -84,7 +84,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataResult.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataResult.java index 6af30b8729..76d76a2bb4 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataResult.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataResult.java @@ -63,7 +63,7 @@ public interface DataResult { * Sets the descriptive text about the source of the nodes displayed in this * result view component. * - * @param description The text to display. + * @param pathText The text to display. */ public void setPath(String pathText); diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java index eea1a61f6e..4aa7a63117 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -734,7 +734,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C * * @return True or false. * - * @Deprecated This method has no valid use case. + * @deprecated This method has no valid use case. */ @Deprecated @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyVisitableItem.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyVisitableItem.java index 4092321ca9..af868a68c4 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyVisitableItem.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyVisitableItem.java @@ -28,7 +28,7 @@ public interface AutopsyVisitableItem { /** * visitor pattern support * - * @param v visitor + * @param visitor visitor * * @return visitor return value */ diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentNode.java index d3531068ee..1bf43f5e79 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentNode.java @@ -40,7 +40,7 @@ abstract class ContentNode extends DisplayableItemNode { /** * Visitor pattern support. * - * @param v visitor + * @param visitor visitor * * @return visitor's visit return value */ diff --git a/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java b/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java index 2818e94e96..9dbd08233e 100644 --- a/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java +++ b/Core/src/org/sleuthkit/autopsy/healthmonitor/HealthMonitorDashboard.java @@ -65,6 +65,8 @@ public class HealthMonitorDashboard { private JComboBox dateComboBox = null; private JComboBox hostComboBox = null; private JCheckBox hostCheckBox = null; + private JCheckBox showTrendLineCheckBox = null; + private JCheckBox skipOutliersCheckBox = null; private JPanel graphPanel = null; private JDialog dialog = null; private final Container parentWindow; @@ -201,7 +203,9 @@ public class HealthMonitorDashboard { * @return the control panel */ @NbBundle.Messages({"HealthMonitorDashboard.createTimingControlPanel.filterByHost=Filter by host", - "HealthMonitorDashboard.createTimingControlPanel.maxDays=Max days to display"}) + "HealthMonitorDashboard.createTimingControlPanel.maxDays=Max days to display", + "HealthMonitorDashboard.createTimingControlPanel.skipOutliers=Do not plot outliers", + "HealthMonitorDashboard.createTimingControlPanel.showTrendLine=Show trend line"}) private JPanel createTimingControlPanel() { JPanel timingControlPanel = new JPanel(); @@ -252,7 +256,7 @@ public class HealthMonitorDashboard { } }); - // Create the checkbox + // Create the host checkbox hostCheckBox = new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_filterByHost()); hostCheckBox.setSelected(false); hostComboBox.setEnabled(false); @@ -270,6 +274,38 @@ public class HealthMonitorDashboard { } }); + // Create the checkbox for showing the trend line + showTrendLineCheckBox = new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_showTrendLine()); + showTrendLineCheckBox.setSelected(true); + + // Set up the listener on the checkbox + showTrendLineCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + try { + updateTimingMetricGraphs(); + } catch (HealthMonitorException ex) { + logger.log(Level.SEVERE, "Error populating timing metric panel", ex); + } + } + }); + + // Create the checkbox for omitting outliers + skipOutliersCheckBox = new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_skipOutliers()); + skipOutliersCheckBox.setSelected(false); + + // Set up the listener on the checkbox + skipOutliersCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + try { + updateTimingMetricGraphs(); + } catch (HealthMonitorException ex) { + logger.log(Level.SEVERE, "Error populating timing metric panel", ex); + } + } + }); + // Add the date range combo box and label to the panel timingControlPanel.add(new JLabel(Bundle.HealthMonitorDashboard_createTimingControlPanel_maxDays())); timingControlPanel.add(dateComboBox); @@ -281,6 +317,18 @@ public class HealthMonitorDashboard { timingControlPanel.add(hostCheckBox); timingControlPanel.add(hostComboBox); + // Put some space between the elements + timingControlPanel.add(Box.createHorizontalStrut(100)); + + // Add the skip outliers checkbox + timingControlPanel.add(this.showTrendLineCheckBox); + + // Put some space between the elements + timingControlPanel.add(Box.createHorizontalStrut(100)); + + // Add the skip outliers checkbox + timingControlPanel.add(this.skipOutliersCheckBox); + return timingControlPanel; } @@ -324,7 +372,7 @@ public class HealthMonitorDashboard { // Generate the graph TimingMetricGraphPanel singleTimingGraphPanel = new TimingMetricGraphPanel(intermediateTimingDataForDisplay, - TimingMetricGraphPanel.TimingMetricType.AVERAGE, hostToDisplay, true, metricName); + hostToDisplay, true, metricName, skipOutliersCheckBox.isSelected(), showTrendLineCheckBox.isSelected()); singleTimingGraphPanel.setPreferredSize(new Dimension(700,200)); graphPanel.add(singleTimingGraphPanel); diff --git a/Core/src/org/sleuthkit/autopsy/healthmonitor/TimingMetricGraphPanel.java b/Core/src/org/sleuthkit/autopsy/healthmonitor/TimingMetricGraphPanel.java index 5e94471ff8..6d995ed9ac 100644 --- a/Core/src/org/sleuthkit/autopsy/healthmonitor/TimingMetricGraphPanel.java +++ b/Core/src/org/sleuthkit/autopsy/healthmonitor/TimingMetricGraphPanel.java @@ -58,9 +58,10 @@ class TimingMetricGraphPanel extends JPanel { private final int pointWidth = 4; private final int numberYDivisions = 10; private List timingResults; - private final TimingMetricType timingMetricType; private final String metricName; private final boolean doLineGraph; + private final boolean skipOutliers; + private final boolean showTrendLine; private String yUnitString; private TrendLine trendLine; private final long MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24; @@ -70,11 +71,12 @@ class TimingMetricGraphPanel extends JPanel { private double maxMetricTime; private double minMetricTime; - TimingMetricGraphPanel(List timingResultsFull, TimingMetricType timingMetricType, - String hostName, boolean doLineGraph, String metricName) { + TimingMetricGraphPanel(List timingResultsFull, + String hostName, boolean doLineGraph, String metricName, boolean skipOutliers, boolean showTrendLine) { - this.timingMetricType = timingMetricType; this.doLineGraph = doLineGraph; + this.skipOutliers = skipOutliers; + this.showTrendLine = showTrendLine; this.metricName = metricName; if(hostName == null || hostName.isEmpty()) { timingResults = timingResultsFull; @@ -84,85 +86,46 @@ class TimingMetricGraphPanel extends JPanel { .collect(Collectors.toList()); } - try { - trendLine = new TrendLine(timingResults, timingMetricType); - } catch (HealthMonitorException ex) { - // Log it, set trendLine to null and continue on - logger.log(Level.WARNING, "Can not generate a trend line on empty data set"); - trendLine = null; + if(showTrendLine) { + try { + trendLine = new TrendLine(timingResults); + } catch (HealthMonitorException ex) { + // Log it, set trendLine to null and continue on + logger.log(Level.WARNING, "Can not generate a trend line on empty data set"); + trendLine = null; + } } // Calculate these using the full data set, to make it easier to compare the results for - // individual hosts - calcMaxTimestamp(timingResultsFull); - calcMinTimestamp(timingResultsFull); - calcMaxMetricTime(timingResultsFull); - calcMinMetricTime(timingResultsFull); - } - - /** - * Set the highest metric time for the given type - */ - private void calcMaxMetricTime(List timingResultsFull) { - // Find the highest of the values being graphed + // individual hosts. Calculate the average at the same time. maxMetricTime = Double.MIN_VALUE; - for (DatabaseTimingResult score : timingResultsFull) { - // Use only the data we're graphing to determing the max - switch (timingMetricType) { - case MAX: - maxMetricTime = Math.max(maxMetricTime, score.getMax()); - break; - case MIN: - maxMetricTime = Math.max(maxMetricTime, score.getMin()); - break; - case AVERAGE: - default: - maxMetricTime = Math.max(maxMetricTime, score.getAverage()); - break; - } - } - } - - /** - * Set the lowest metric time for the given type - */ - private void calcMinMetricTime(List timingResultsFull) { - // Find the lowest of the values being graphed minMetricTime = Double.MAX_VALUE; - for (DatabaseTimingResult result : timingResultsFull) { - // Use only the data we're graphing to determing the min - switch (timingMetricType) { - case MAX: - minMetricTime = Math.min(minMetricTime, result.getMax()); - break; - case MIN: - minMetricTime = Math.min(minMetricTime, result.getMin()); - break; - case AVERAGE: - default: - minMetricTime = Math.min(minMetricTime, result.getAverage()); - break; - } - } - } - - /** - * Set the largest timestamp in the data collection - */ - private void calcMaxTimestamp(List timingResultsFull) { maxTimestamp = Long.MIN_VALUE; - for (DatabaseTimingResult score : timingResultsFull) { - maxTimestamp = Math.max(maxTimestamp, score.getTimestamp()); - } - } - - /** - * Set the smallest timestamp in the data collection - */ - private void calcMinTimestamp(List timingResultsFull) { minTimestamp = Long.MAX_VALUE; - for (DatabaseTimingResult score : timingResultsFull) { - minTimestamp = Math.min(minTimestamp, score.getTimestamp()); + double averageMetricTime = 0.0; + for (DatabaseTimingResult result : timingResultsFull) { + + maxMetricTime = Math.max(maxMetricTime, result.getAverage()); + minMetricTime = Math.min(minMetricTime, result.getAverage()); + + maxTimestamp = Math.max(maxTimestamp, result.getTimestamp()); + minTimestamp = Math.min(minTimestamp, result.getTimestamp()); + + averageMetricTime += result.getAverage(); + } + averageMetricTime = averageMetricTime / timingResultsFull.size(); + + // If we're omitting outliers, we may use a different maxMetricTime. + // If the max time is reasonably close to the average, do nothing + if (this.skipOutliers && (maxMetricTime > (averageMetricTime * 5))) { + // Calculate the standard deviation + double intermediateValue = 0.0; + for (DatabaseTimingResult result : timingResultsFull) { + double diff = result.getAverage() - averageMetricTime; + intermediateValue += diff * diff; + } + double standardDeviation = Math.sqrt(intermediateValue / timingResultsFull.size()); + maxMetricTime = averageMetricTime + standardDeviation; } } @@ -258,6 +221,7 @@ class TimingMetricGraphPanel extends JPanel { // Create hatch marks and grid lines for y axis. int labelWidth; + int positionForMetricNameLabel = 0; for (int i = 0; i < numberYDivisions + 1; i++) { int x0 = leftGraphPadding; int x1 = pointWidth + leftGraphPadding; @@ -278,13 +242,9 @@ class TimingMetricGraphPanel extends JPanel { g2.drawString(yLabel, x0 - labelWidth - 5, y0 + (fontMetrics.getHeight() / 2) - 3); // The nicest looking alignment for this label seems to be left-aligned with the top - // y-axis label + // y-axis label. Save this position to be used to write the label later. if (i == numberYDivisions) { - // Write the scale - g2.setColor(Color.BLACK); - String scaleStr = Bundle.TimingMetricGraphPanel_paintComponent_displayingTime() + yUnitString; - String titleStr = metricName + " - " + scaleStr; - g2.drawString(titleStr, x0 - labelWidth - 5, padding); + positionForMetricNameLabel = x0 - labelWidth - 5; } } @@ -354,20 +314,7 @@ class TimingMetricGraphPanel extends JPanel { // Create the points to plot List graphPoints = new ArrayList<>(); for (int i = 0; i < timingResults.size(); i++) { - double metricTime; - switch (timingMetricType) { - case MAX: - metricTime = timingResults.get(i).getMax(); - break; - case MIN: - metricTime = timingResults.get(i).getMin(); - break; - case AVERAGE: - default: - metricTime = timingResults.get(i).getAverage(); - break; - - } + double metricTime = timingResults.get(i).getAverage(); int x1 = (int) ((timingResults.get(i).getTimestamp() - minValueOnXAxis) * xScale + leftGraphPadding); int y1 = (int) ((maxValueOnYAxis - metricTime) * yScale + topGraphPadding); @@ -411,7 +358,7 @@ class TimingMetricGraphPanel extends JPanel { // Draw the trend line. // Don't draw anything if we don't have at least two data points. - if(trendLine != null && (timingResults.size() > 1)) { + if(showTrendLine && (trendLine != null) && (timingResults.size() > 1)) { double x0value = minValueOnXAxis; double y0value = trendLine.getExpectedValueAt(x0value); if (y0value < minValueOnYAxis) { @@ -470,15 +417,17 @@ class TimingMetricGraphPanel extends JPanel { g2.setColor(trendLineColor); g2.drawLine(x0, y0, x1, y1); } - } - - /** - * The metric field we want to graph - */ - enum TimingMetricType { - AVERAGE, - MAX, - MIN; + + // The graph lines may have extended up past the bounds of the graph. Overwrite that + // area with the original background color. + g2.setColor(this.getBackground()); + g2.fillRect(leftGraphPadding, 0, graphWidth, topGraphPadding); + + // Write the scale. Do this after we erase the top block of the graph. + g2.setColor(Color.BLACK); + String scaleStr = Bundle.TimingMetricGraphPanel_paintComponent_displayingTime() + yUnitString; + String titleStr = metricName + " - " + scaleStr; + g2.drawString(titleStr, positionForMetricNameLabel, padding); } /** @@ -497,7 +446,7 @@ class TimingMetricGraphPanel extends JPanel { double slope; double yInt; - TrendLine(List timingResults, TimingMetricGraphPanel.TimingMetricType timingMetricType) throws HealthMonitorException { + TrendLine(List timingResults) throws HealthMonitorException { if((timingResults == null) || timingResults.isEmpty()) { throw new HealthMonitorException("Can not generate trend line for empty/null data set"); @@ -511,19 +460,7 @@ class TimingMetricGraphPanel extends JPanel { double sumXsquared = 0; for(int i = 0;i < n;i++) { double x = timingResults.get(i).getTimestamp(); - double y; - switch (timingMetricType) { - case MAX: - y = timingResults.get(i).getMax(); - break; - case MIN: - y = timingResults.get(i).getMin(); - break; - case AVERAGE: - default: - y = timingResults.get(i).getAverage(); - break; - } + double y = timingResults.get(i).getAverage(); sumX += x; sumY += y; 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 old mode 100644 new mode 100755 diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java index 215d1fe4da..6af0ec81f9 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java @@ -62,7 +62,7 @@ public class EmbeddedFileTest extends NbTestCase { @Override public void setUp() { - CaseUtils.createCase(CASE_DIRECTORY_PATH, CASE_NAME); + CaseUtils.createCase(CASE_NAME); ImageDSProcessor dataSourceProcessor = new ImageDSProcessor(); IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH); @@ -92,7 +92,6 @@ public class EmbeddedFileTest extends NbTestCase { @Override public void tearDown() { CaseUtils.closeCase(); - CaseUtils.deleteCaseDir(CASE_DIRECTORY_PATH); } public void testEncryption() { diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java old mode 100644 new mode 100755 index 810c682798..7be3e4f794 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/IngestFileFiltersTest.java @@ -72,8 +72,7 @@ public class IngestFileFiltersTest extends NbTestCase { } public void testBasicDir() { - Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testBasicDir"); - CaseUtils.createCase(casePath, "testBasicDir"); + CaseUtils.createCase("testBasicDir"); ImageDSProcessor dataSourceProcessor = new ImageDSProcessor(); IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH); @@ -115,8 +114,7 @@ public class IngestFileFiltersTest extends NbTestCase { } public void testExtAndDirWithOneRule() { - Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testExtAndDirWithOneRule"); - CaseUtils.createCase(casePath, "testExtAndDirWithOneRule"); + CaseUtils.createCase("testExtAndDirWithOneRule"); ImageDSProcessor dataSourceProcessor = new ImageDSProcessor(); IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH); @@ -151,8 +149,7 @@ public class IngestFileFiltersTest extends NbTestCase { } public void testExtAndDirWithTwoRules() { - Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testExtAndDirWithTwoRules"); - CaseUtils.createCase(casePath, "testExtAndDirWithTwoRules"); + CaseUtils.createCase("testExtAndDirWithTwoRules"); ImageDSProcessor dataSourceProcessor = new ImageDSProcessor(); IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH); @@ -196,8 +193,7 @@ public class IngestFileFiltersTest extends NbTestCase { } public void testFullFileNameRule() { - Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testFullFileNameRule"); - CaseUtils.createCase(casePath, "testFullFileNameRule"); + CaseUtils.createCase("testFullFileNameRule"); ImageDSProcessor dataSourceProcessor = new ImageDSProcessor(); IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH); @@ -232,8 +228,7 @@ public class IngestFileFiltersTest extends NbTestCase { } public void testCarvingWithExtRuleAndUnallocSpace() { - Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testCarvingWithExtRuleAndUnallocSpace"); - CaseUtils.createCase(casePath, "testCarvingWithExtRuleAndUnallocSpace"); + CaseUtils.createCase("testCarvingWithExtRuleAndUnallocSpace"); ImageDSProcessor dataSourceProcessor = new ImageDSProcessor(); IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH); @@ -281,8 +276,7 @@ public class IngestFileFiltersTest extends NbTestCase { } public void testCarvingNoUnallocatedSpace() { - Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testCarvingNoUnallocatedSpace"); - CaseUtils.createCase(casePath, "testCarvingNoUnallocatedSpace"); + CaseUtils.createCase("testCarvingNoUnallocatedSpace"); ImageDSProcessor dataSourceProcessor = new ImageDSProcessor(); IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH); @@ -315,8 +309,7 @@ public class IngestFileFiltersTest extends NbTestCase { } public void testEmbeddedModule() { - Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testEmbeddedModule"); - CaseUtils.createCase(casePath, "testEmbeddedModule"); + CaseUtils.createCase("testEmbeddedModule"); LocalFilesDSProcessor dataSourceProcessor = new LocalFilesDSProcessor(); IngestUtils.addDataSource(dataSourceProcessor, ZIPFILE_PATH); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionTest.java index c1e71822a4..2fa219a86d 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionTest.java @@ -33,6 +33,8 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType; +import org.sleuthkit.autopsy.ingest.IngestModuleFactory; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleTemplate; import org.sleuthkit.autopsy.testutils.CaseUtils; import org.sleuthkit.autopsy.testutils.IngestUtils; @@ -49,18 +51,10 @@ import org.sleuthkit.datamodel.VolumeSystem; public class EncryptionDetectionTest extends NbTestCase { private static final String BITLOCKER_CASE_NAME = "testBitlockerEncryption"; - private static final String PASSWORD_CASE_NAME = "testPasswordProtection"; - - private static final Path BITLOCKER_CASE_DIRECTORY_PATH = Paths.get(System.getProperty("java.io.tmpdir"), BITLOCKER_CASE_NAME); - private static final Path PASSWORD_CASE_DIRECTORY_PATH = Paths.get(System.getProperty("java.io.tmpdir"), PASSWORD_CASE_NAME); - private final Path BITLOCKER_IMAGE_PATH = Paths.get(this.getDataDir().toString(), "encryption_detection_bitlocker_test.vhd"); - private final Path PASSWORD_IMAGE_PATH = Paths.get(this.getDataDir().toString(), "password_detection_test.img"); - private static final String PASSWORD_DETECTION_CASE_NAME = "PasswordDetectionTest"; - private static final String VERACRYPT_DETECTION_CASE_NAME = "VeraCryptDetectionTest"; - private final Path PASSWORD_DETECTION_IMAGE_PATH = Paths.get(this.getDataDir().toString(), "password_detection_test.img"); + private static final String VERACRYPT_DETECTION_CASE_NAME = "VeraCryptDetectionTest"; private final Path VERACRYPT_DETECTION_IMAGE_PATH = Paths.get(this.getDataDir().toString(), "veracrypt_detection_test.vhd"); public static Test suite() { @@ -84,7 +78,7 @@ public class EncryptionDetectionTest extends NbTestCase { */ public void testBitlockerEncryption() { try { - CaseUtils.createCase(BITLOCKER_CASE_DIRECTORY_PATH, BITLOCKER_CASE_NAME); + CaseUtils.createCase(BITLOCKER_CASE_NAME); ImageDSProcessor dataSourceProcessor = new ImageDSProcessor(); IngestUtils.addDataSource(dataSourceProcessor, BITLOCKER_IMAGE_PATH); Case openCase = Case.getCurrentCaseThrows(); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/CaseUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/CaseUtils.java index 500aaa6258..17b0c2168b 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/CaseUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/CaseUtils.java @@ -37,13 +37,6 @@ import org.sleuthkit.autopsy.casemodule.CaseDetails; */ public final class CaseUtils { - /** - * CaseUtils constructor. Since this class is not meant to allow for - * instantiation, this constructor is 'private'. - */ - private CaseUtils() { - } - /** * Create a case case directory and case for the given case name. * @@ -105,10 +98,13 @@ public final class CaseUtils { if (!caseDirectory.exists()) { return; } - //We should determine whether the test fails or passes where this is called - //It will usually be a test failure when the case can not be deleted - //but sometimes we might be alright if we are unable to delete it. FileUtils.deleteDirectory(caseDirectory); } + /** + * Private constructor to prevent utility class instantiation. + */ + private CaseUtils() { + } + } diff --git a/docs/doxygen-user/archive_extractor.dox b/docs/doxygen-user/archive_extractor.dox index d3c455695a..3bc606038f 100644 --- a/docs/doxygen-user/archive_extractor.dox +++ b/docs/doxygen-user/archive_extractor.dox @@ -1,7 +1,7 @@ /*! \page embedded_file_extractor_page Embedded File Extraction Module -What Does It Do -======== +\section embedded_files_overview What Does It Do + The Embedded File Extractor module opens ZIP, RAR, other archive formats, Doc, Docx, PPT, PPTX, XLS, and XLSX and sends the derived files from those files back through the ingest pipeline for analysis. @@ -9,21 +9,17 @@ This module expands archive files to enable Autopsy to analyze all files on the NOTE: Certain media content embedded inside Doc, Docx, PPT, PPTX, XLS, and XLSX might not be extracted. -Configuration -======= +\section embedded_files_config Configuration There is no configuration required. -Using the Module -====== +\section embedded_files_usage Using the Module Select the checkbox in the Ingest Modules settings screen to enable the Archive Extractor. -Ingest Settings ------- +\subsection embedded_files_settings Ingest Settings There are no runtime ingest settings required. -Seeing Results ------- +\subsection embedded_files_results Seeing Results Each file extracted shows up in the data source tree view as a child of the archive containing it, \image html zipped_children_1.PNG @@ -32,4 +28,18 @@ Each file extracted shows up in the data source tree view as a child of the arch and as an archive under "Views", "File Types", "Archives". \image html zipped_children_2.PNG +\subsection embedded_files_encryption Encrypted Archives + +When the Embedded File Extractor module encounters an encrypted archive, it will generate a warning bubble in the bottom right of the main screen: + +\image html zipped_encryption_detected.png + +After ingest, you can attempt to decrypt these archives if you know the password. Find the archive (either in the \ref tree_viewer_page "tree view" or \ref result_viewer_page "result view") and right-click on it, then select "Unzip contents with password". + +\image html zipped_context_menu.png + +After entering the password, you can select which ingest modules to run on the newly extracted files. When finished, you can browse to the encrypted archive in the tree view to see the newly extracted files. If the archive was already open in the tree, you may have to close and open the case in order to see the new data. + +\image html zipped_tree.png + */ diff --git a/docs/doxygen-user/communications.dox b/docs/doxygen-user/communications.dox index ced0a044d3..1e89a28d8e 100644 --- a/docs/doxygen-user/communications.dox +++ b/docs/doxygen-user/communications.dox @@ -20,8 +20,30 @@ The middle column displays each account, its device and type, and the number of Selecting an account in the middle column will bring up the messages for that account in the right hand column. Here data about each message is displayed in the top section, and the messages itself can be seen in the bottom section (if applicable). -The middle column and the right hand column both have a \ref ui_quick_search feature which can be used to quickly find a visible item in their section's table. - \image html cvt_messages.png +The middle column and the right hand column both have a \ref ui_quick_search feature which can be used to quickly find a visible item in their section's table. + +\section cvt_viz Visualization + +The Visualize tab in the middle panel will show a graph of one or more accounts selected in the Browse tab. + +To start, right click the first account you want to view. + +\image html cvt_select_account.png + +There are two options, which are equivalent when no accounts have previously been selected: +
    +
  • Add Selected Account to Visualization - Adds this account and its connections to the graph +
  • Visualize Only Selected Account - Clears the graph and only displays the connections for this account +
+ +After selecting either option, the middle tab will switch to the Visualize view and the graph will be displayed. + +\image html cvt_visualize.png + +The options at the top allow you to clear the graph, try different graph layouts, and resize the graph. The nodes in the graph can be dragged around and nodes and edges can be selected to display their messages or relationships in the right side tab. For example, in the image below the link between two email addresses has been selected so the Messages viewer is displaying the single email between those two email addresses. + +\image html cvt_links.png + */ \ No newline at end of file diff --git a/docs/doxygen-user/images/cvt_links.png b/docs/doxygen-user/images/cvt_links.png new file mode 100644 index 0000000000..1aa4db9033 Binary files /dev/null and b/docs/doxygen-user/images/cvt_links.png differ diff --git a/docs/doxygen-user/images/cvt_main.png b/docs/doxygen-user/images/cvt_main.png index 26b763319b..be2c390f66 100644 Binary files a/docs/doxygen-user/images/cvt_main.png and b/docs/doxygen-user/images/cvt_main.png differ diff --git a/docs/doxygen-user/images/cvt_messages.png b/docs/doxygen-user/images/cvt_messages.png index df26ce71ef..956e8a87c6 100644 Binary files a/docs/doxygen-user/images/cvt_messages.png and b/docs/doxygen-user/images/cvt_messages.png differ diff --git a/docs/doxygen-user/images/cvt_select_account.png b/docs/doxygen-user/images/cvt_select_account.png new file mode 100644 index 0000000000..3a0874e081 Binary files /dev/null and b/docs/doxygen-user/images/cvt_select_account.png differ diff --git a/docs/doxygen-user/images/cvt_visualize.png b/docs/doxygen-user/images/cvt_visualize.png new file mode 100644 index 0000000000..e5d56950b5 Binary files /dev/null and b/docs/doxygen-user/images/cvt_visualize.png differ diff --git a/docs/doxygen-user/images/zipped_context_menu.png b/docs/doxygen-user/images/zipped_context_menu.png new file mode 100644 index 0000000000..848ac8ea2e Binary files /dev/null and b/docs/doxygen-user/images/zipped_context_menu.png differ diff --git a/docs/doxygen-user/images/zipped_encryption_detected.png b/docs/doxygen-user/images/zipped_encryption_detected.png new file mode 100644 index 0000000000..cfd4b88953 Binary files /dev/null and b/docs/doxygen-user/images/zipped_encryption_detected.png differ diff --git a/docs/doxygen-user/images/zipped_tree.png b/docs/doxygen-user/images/zipped_tree.png new file mode 100644 index 0000000000..6afc67ecfb Binary files /dev/null and b/docs/doxygen-user/images/zipped_tree.png differ