mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-09 14:49:32 +00:00
Merge branch 'develop' of github.com:sleuthkit/autopsy into java11-upgrade
This commit is contained in:
commit
3ae06e65b3
@ -197,7 +197,7 @@
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!--sets up integration test system properties, calls underlying test-init and then sets up the pathing jar-->
|
<!--sets up integration test system properties, calls underlying test-init and then sets up the pathing jar-->
|
||||||
<target name="test-init" depends="projectized-common.test-init,getTestDataFiles,qa-functional-pathing-jar" />
|
<target name="test-init" depends="projectized-common.test-init,getTestDataFiles,qa-functional-pathing-jar,unit-test-path-simplification" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
The paths specified in 'module.run.classpath' are incorporated into the manifest of a jar and then the path to the
|
The paths specified in 'module.run.classpath' are incorporated into the manifest of a jar and then the path to the
|
||||||
@ -238,4 +238,67 @@
|
|||||||
</path>
|
</path>
|
||||||
</sequential>
|
</sequential>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This specifies the classpath for unit tests using * notation
|
||||||
|
(i.e. https://stackoverflow.com/questions/219585/including-all-the-jars-in-a-directory-within-the-java-classpath).
|
||||||
|
This solution involves taking the initial ‘module.run.classpath’ property and simplifying it to the directories containing jars
|
||||||
|
(i.e. instead of “/dir/lib1.jar:/dir/lib2.jar:/dir/lib3.jar” it becomes “/dir/*” ).
|
||||||
|
More information on ‘module.run.classpath’ can be found in “netbeans-plat\11.3\harness\README” and it appears that
|
||||||
|
“netbeans-plat\11.3\harness\build.xml:build-init target is in charge of setting the ‘module.run.classpath’ variable.
|
||||||
|
More information in Jira: 6970.
|
||||||
|
-->
|
||||||
|
<target name="unit-test-path-simplification" depends="projectized-common.test-init">
|
||||||
|
<sequential>
|
||||||
|
<script language="javascript">
|
||||||
|
<![CDATA[
|
||||||
|
var moduleRunClasspath = project.getProperty("module.run.classpath");
|
||||||
|
|
||||||
|
var directories = [];
|
||||||
|
// searches for jar file parent directories with path separators of \ or /
|
||||||
|
var individualPathRegex = /^\s*(.+?[\\\/])[^\\\/]+?\.jar\s*$/i;
|
||||||
|
// split on ':' but not 'C:\'
|
||||||
|
var classPathRegex = /((C:\\)?.+?)(:|$)/gi;
|
||||||
|
var match;
|
||||||
|
while((match = classPathRegex.exec(moduleRunClasspath)) !== null) {
|
||||||
|
var thisPath = match[1];
|
||||||
|
var pathMatch = thisPath.match(individualPathRegex);
|
||||||
|
// find unique matches
|
||||||
|
if (pathMatch && directories.indexOf(pathMatch[1]) < 0) {
|
||||||
|
directories.push(pathMatch[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// suffix with *
|
||||||
|
for (var i = 0; i < directories.length; i++) {
|
||||||
|
directories[i] = directories[i] + "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
// set project property
|
||||||
|
project.setNewProperty("test.unit.abbreviatedModuleRunClassPath", directories.join(":"));
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--grab properties from common.xml:test-init so that "test.unit.run.cp" can be properly formed-->
|
||||||
|
<property name="build.test.unit.dir" location="${build.dir}/test/unit"/>
|
||||||
|
<property name="build.test.unit.classes.dir" location="${build.test.unit.dir}/classes"/>
|
||||||
|
<property name="test.unit.cp.extra" value=""/>
|
||||||
|
|
||||||
|
<!--set up "test.unit.run.cp" to be used by common.xml:-do-junit-->
|
||||||
|
<path id="test.unit.run.cp">
|
||||||
|
<pathelement path="${build.test.unit.classes.dir}"/>
|
||||||
|
<!-- Cannot use <path refid="cp"/> since that uses ${module.classpath} and we want ${module.run.classpath}: -->
|
||||||
|
<pathelement path="${test.unit.runtime.cp}"/>
|
||||||
|
<pathelement path="${cp.extra}"/>
|
||||||
|
<pathelement location="${cluster}/${module.jar}"/>
|
||||||
|
<path refid="test.unit.lib.cp"/>
|
||||||
|
<!-- for compatibility with property based classpath-->
|
||||||
|
<pathelement path="${test.unit.abbreviatedModuleRunClassPath}"/>
|
||||||
|
<pathelement path="${test.unit.run.cp.extra}"/>
|
||||||
|
<pathelement path="${test.unit.cp.extra}"/>
|
||||||
|
<pathelement path="${test.extra.nb.javac.deps}"/>
|
||||||
|
</path>
|
||||||
|
</sequential>
|
||||||
|
</target>
|
||||||
</project>
|
</project>
|
||||||
|
@ -44,7 +44,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
|||||||
* A class to help display a communication artifact in a panel using a
|
* A class to help display a communication artifact in a panel using a
|
||||||
* gridbaglayout.
|
* gridbaglayout.
|
||||||
*/
|
*/
|
||||||
final class CommunicationArtifactViewerHelper {
|
public final class CommunicationArtifactViewerHelper {
|
||||||
|
|
||||||
// Number of columns in the gridbag layout.
|
// Number of columns in the gridbag layout.
|
||||||
private final static int MAX_COLS = 4;
|
private final static int MAX_COLS = 4;
|
||||||
@ -63,12 +63,12 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
* @param headerString Heading string to display.
|
* @param headerString Heading string to display.
|
||||||
*
|
*
|
||||||
* @return JLabel Heading label added.
|
* @return JLabel Heading label added.
|
||||||
*/
|
*/
|
||||||
static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String headerString) {
|
public static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String headerString) {
|
||||||
|
|
||||||
Insets savedInsets = constraints.insets;
|
Insets savedInsets = constraints.insets;
|
||||||
|
|
||||||
@ -109,6 +109,23 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
return headingLabel;
|
return headingLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a key value row to the specified panel with the specified layout and
|
||||||
|
* constraints.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param panel Panel to update.
|
||||||
|
* @param gridbagLayout Layout to use.
|
||||||
|
* @param constraints Constraints to use.
|
||||||
|
* @param keyString Key name to display.
|
||||||
|
* @param valueString Value string to display.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static void addNameValueRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String keyString, String valueString) {
|
||||||
|
addKey(panel, gridbagLayout, constraints, keyString);
|
||||||
|
addValue(panel, gridbagLayout, constraints, valueString);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the given component to the panel.
|
* Adds the given component to the panel.
|
||||||
*
|
*
|
||||||
@ -116,7 +133,7 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
* @param component Component to add.
|
* @param component Component to add.
|
||||||
*/
|
*/
|
||||||
static void addComponent(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, JComponent component) {
|
static void addComponent(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, JComponent component) {
|
||||||
@ -132,7 +149,7 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
*/
|
*/
|
||||||
static void addLineEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) {
|
static void addLineEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) {
|
||||||
// Place the filler just past the last column.
|
// Place the filler just past the last column.
|
||||||
@ -159,9 +176,9 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
*/
|
*/
|
||||||
static void addPageEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) {
|
public static void addPageEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) {
|
||||||
|
|
||||||
constraints.gridx = 0;
|
constraints.gridx = 0;
|
||||||
|
|
||||||
@ -185,7 +202,7 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
*/
|
*/
|
||||||
static void addBlankLine(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) {
|
static void addBlankLine(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) {
|
||||||
constraints.gridy++;
|
constraints.gridy++;
|
||||||
@ -203,7 +220,7 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
* @param keyString Key name to display.
|
* @param keyString Key name to display.
|
||||||
*
|
*
|
||||||
* @return Label added.
|
* @return Label added.
|
||||||
@ -217,7 +234,7 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
* @param keyString Key name to display.
|
* @param keyString Key name to display.
|
||||||
* @param gridx column index, must be less than MAX_COLS - 1.
|
* @param gridx column index, must be less than MAX_COLS - 1.
|
||||||
*
|
*
|
||||||
@ -246,8 +263,8 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
* @param keyString Value string to display.
|
* @param valueString Value string to display.
|
||||||
*
|
*
|
||||||
* @return Label added.
|
* @return Label added.
|
||||||
*/
|
*/
|
||||||
@ -260,7 +277,7 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
* @param keyString Value string to display.
|
* @param keyString Value string to display.
|
||||||
* @param gridx Column index, must be less than MAX_COLS;
|
* @param gridx Column index, must be less than MAX_COLS;
|
||||||
*
|
*
|
||||||
@ -367,7 +384,7 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
* @param accountIdentifier Account identifier to search the persona.
|
* @param accountIdentifier Account identifier to search the persona.
|
||||||
*
|
*
|
||||||
* @return List of AccountPersonaSearcherData objects.
|
* @return List of AccountPersonaSearcherData objects.
|
||||||
@ -435,7 +452,7 @@ final class CommunicationArtifactViewerHelper {
|
|||||||
*
|
*
|
||||||
* @param panel Panel to update.
|
* @param panel Panel to update.
|
||||||
* @param gridbagLayout Layout to use.
|
* @param gridbagLayout Layout to use.
|
||||||
* @param constraints Constrains to use.
|
* @param constraints Constraints to use.
|
||||||
* @param contactId Contact name to display.
|
* @param contactId Contact name to display.
|
||||||
*
|
*
|
||||||
* @return A JLabel with the contact information.
|
* @return A JLabel with the contact information.
|
||||||
|
@ -54,15 +54,14 @@ import com.google.gson.JsonArray;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
import org.sleuthkit.autopsy.discovery.ui.AbstractArtifactDetailsPanel;
|
||||||
//import org.sleuthkit.autopsy.contentviewers.Bundle;
|
//import org.sleuthkit.autopsy.contentviewers.Bundle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class displays a Blackboard artifact as a table listing all it's
|
* This class displays a Blackboard artifact as a table of its attributes.
|
||||||
* attributes names and values.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
public class DefaultArtifactContentViewer extends javax.swing.JPanel implements ArtifactContentViewer {
|
public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel implements ArtifactContentViewer {
|
||||||
|
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"DefaultArtifactContentViewer.attrsTableHeader.type=Type",
|
"DefaultArtifactContentViewer.attrsTableHeader.type=Type",
|
||||||
@ -279,7 +278,7 @@ public class DefaultArtifactContentViewer extends javax.swing.JPanel implements
|
|||||||
@Override
|
@Override
|
||||||
public void setArtifact(BlackboardArtifact artifact) {
|
public void setArtifact(BlackboardArtifact artifact) {
|
||||||
try {
|
try {
|
||||||
ResultsTableArtifact resultsTableArtifact = new ResultsTableArtifact(artifact, artifact.getParent());
|
ResultsTableArtifact resultsTableArtifact = artifact == null ? null : new ResultsTableArtifact(artifact, artifact.getParent());
|
||||||
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@ -427,9 +426,9 @@ public class DefaultArtifactContentViewer extends javax.swing.JPanel implements
|
|||||||
return returnString;
|
return returnString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given JSON element into string and appends to the given string builder.
|
* Converts the given JSON element into string and appends to the given
|
||||||
|
* string builder.
|
||||||
*
|
*
|
||||||
* @param jsonKey
|
* @param jsonKey
|
||||||
* @param jsonElement
|
* @param jsonElement
|
||||||
@ -468,6 +467,7 @@ public class DefaultArtifactContentViewer extends javax.swing.JPanel implements
|
|||||||
* Converts epoch time to readable string.
|
* Converts epoch time to readable string.
|
||||||
*
|
*
|
||||||
* @param epochTime epoch time value to be converted to string.
|
* @param epochTime epoch time value to be converted to string.
|
||||||
|
*
|
||||||
* @return String with human readable time.
|
* @return String with human readable time.
|
||||||
*/
|
*/
|
||||||
private String epochTimeToString(long epochTime) {
|
private String epochTimeToString(long epochTime) {
|
||||||
@ -490,13 +490,12 @@ public class DefaultArtifactContentViewer extends javax.swing.JPanel implements
|
|||||||
*/
|
*/
|
||||||
private void updateView(ResultsTableArtifact resultsTableArtifact) {
|
private void updateView(ResultsTableArtifact resultsTableArtifact) {
|
||||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||||
|
|
||||||
DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
|
DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
|
||||||
tModel.setDataVector(resultsTableArtifact.getRows(), COLUMN_HEADERS);
|
String[][] rows = resultsTableArtifact == null ? new String[0][0] : resultsTableArtifact.getRows();
|
||||||
|
tModel.setDataVector(rows, COLUMN_HEADERS);
|
||||||
updateColumnSizes();
|
updateColumnSizes();
|
||||||
updateRowHeights();
|
updateRowHeights();
|
||||||
resultsTable.clearSelection();
|
resultsTable.clearSelection();
|
||||||
|
|
||||||
this.setCursor(null);
|
this.setCursor(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,7 +357,9 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
|||||||
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID())
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID())
|
||||||
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID())
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID())
|
||||||
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID())
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID())
|
||||||
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID())) {
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID())
|
||||||
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID())
|
||||||
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())) {
|
||||||
return 3;
|
return 3;
|
||||||
} else {
|
} else {
|
||||||
return 6;
|
return 6;
|
||||||
|
@ -284,17 +284,49 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
|||||||
*/
|
*/
|
||||||
private static Lookup createLookup(BlackboardArtifact artifact) {
|
private static Lookup createLookup(BlackboardArtifact artifact) {
|
||||||
final long objectID = artifact.getObjectID();
|
final long objectID = artifact.getObjectID();
|
||||||
|
Content content = null;
|
||||||
try {
|
try {
|
||||||
Content content = contentCache.get(objectID, () -> artifact.getSleuthkitCase().getContentById(objectID));
|
if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID()) {
|
||||||
|
content = getPathIdFile(artifact);
|
||||||
|
}
|
||||||
|
if (content == null) {
|
||||||
|
content = contentCache.get(objectID, () -> artifact.getSleuthkitCase().getContentById(objectID));
|
||||||
|
}
|
||||||
|
} catch (ExecutionException ex) {
|
||||||
|
logger.log(Level.SEVERE, MessageFormat.format("Error getting source content (artifact objID={0}", artifact.getId()), ex); //NON-NLS
|
||||||
|
content = null;
|
||||||
|
}
|
||||||
if (content == null) {
|
if (content == null) {
|
||||||
return Lookups.fixed(artifact);
|
return Lookups.fixed(artifact);
|
||||||
} else {
|
} else {
|
||||||
return Lookups.fixed(artifact, content);
|
return Lookups.fixed(artifact, content);
|
||||||
}
|
}
|
||||||
} catch (ExecutionException ex) {
|
|
||||||
logger.log(Level.SEVERE, MessageFormat.format("Error getting source content (artifact objID={0}", artifact.getId()), ex); //NON-NLS
|
|
||||||
return Lookups.fixed(artifact);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private helper method to allow content specified in a path id attribute
|
||||||
|
* to be retrieved.
|
||||||
|
*
|
||||||
|
* @param artifact The artifact for which content may be specified as a tsk
|
||||||
|
* path attribute.
|
||||||
|
*
|
||||||
|
* @return The Content specified by the artifact's path id attribute or null
|
||||||
|
* if there was no content available.
|
||||||
|
*
|
||||||
|
* @throws ExecutionException Error retrieving the file specified by the
|
||||||
|
* path id from the cache.
|
||||||
|
*/
|
||||||
|
private static Content getPathIdFile(BlackboardArtifact artifact) throws ExecutionException {
|
||||||
|
try {
|
||||||
|
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID));
|
||||||
|
if (attribute != null) {
|
||||||
|
return contentCache.get(attribute.getValueLong(), () -> artifact.getSleuthkitCase().getContentById(attribute.getValueLong()));
|
||||||
|
}
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.WARNING, MessageFormat.format("Error getting content for path id attrbiute for artifact: ", artifact.getId()), ex); //NON-NLS
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,318 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.datasourcesummary.datamodel;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import org.joda.time.Interval;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
|
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
import org.sleuthkit.datamodel.TimelineEvent;
|
||||||
|
import org.sleuthkit.datamodel.TimelineEventType;
|
||||||
|
import org.sleuthkit.datamodel.TimelineFilter;
|
||||||
|
import org.sleuthkit.datamodel.TimelineFilter.DataSourcesFilter;
|
||||||
|
import org.sleuthkit.datamodel.TimelineFilter.RootFilter;
|
||||||
|
import org.sleuthkit.datamodel.TimelineManager;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides data source summary information pertaining to Timeline data.
|
||||||
|
*/
|
||||||
|
public class TimelineSummary implements DefaultUpdateGovernor {
|
||||||
|
|
||||||
|
private static final long DAY_SECS = 24 * 60 * 60;
|
||||||
|
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS = new HashSet<>(
|
||||||
|
Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED));
|
||||||
|
|
||||||
|
private static final Set<TimelineEventType> FILE_SYSTEM_EVENTS
|
||||||
|
= new HashSet<>(Arrays.asList(
|
||||||
|
TimelineEventType.FILE_MODIFIED,
|
||||||
|
TimelineEventType.FILE_ACCESSED,
|
||||||
|
TimelineEventType.FILE_CREATED,
|
||||||
|
TimelineEventType.FILE_CHANGED));
|
||||||
|
|
||||||
|
private final SleuthkitCaseProvider caseProvider;
|
||||||
|
private final Supplier<TimeZone> timeZoneProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
public TimelineSummary() {
|
||||||
|
this(SleuthkitCaseProvider.DEFAULT, () -> TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct object with given SleuthkitCaseProvider
|
||||||
|
*
|
||||||
|
* @param caseProvider SleuthkitCaseProvider provider, cannot be null.
|
||||||
|
* @param timeZoneProvider The timezone provider, cannot be null.
|
||||||
|
*/
|
||||||
|
public TimelineSummary(SleuthkitCaseProvider caseProvider, Supplier<TimeZone> timeZoneProvider) {
|
||||||
|
this.caseProvider = caseProvider;
|
||||||
|
this.timeZoneProvider = timeZoneProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRefreshRequired(ModuleContentEvent evt) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRefreshRequired(AbstractFile file) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRefreshRequired(IngestManager.IngestJobEvent evt) {
|
||||||
|
return (evt != null && INGEST_JOB_EVENTS.contains(evt));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<IngestManager.IngestJobEvent> getIngestJobEventUpdates() {
|
||||||
|
return INGEST_JOB_EVENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves timeline summary data.
|
||||||
|
*
|
||||||
|
* @param dataSource The data source for which timeline data will be
|
||||||
|
* retrieved.
|
||||||
|
* @param recentDaysNum The maximum number of most recent days' activity to
|
||||||
|
* include.
|
||||||
|
* @return The retrieved data.
|
||||||
|
* @throws SleuthkitCaseProviderException
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
public TimelineSummaryData getData(DataSource dataSource, int recentDaysNum) throws SleuthkitCaseProviderException, TskCoreException {
|
||||||
|
TimeZone timeZone = this.timeZoneProvider.get();
|
||||||
|
TimelineManager timelineManager = this.caseProvider.get().getTimelineManager();
|
||||||
|
|
||||||
|
// get a mapping of days from epoch to the activity for that day
|
||||||
|
Map<Long, DailyActivityAmount> dateCounts = getTimelineEventsByDay(dataSource, timelineManager, timeZone);
|
||||||
|
|
||||||
|
// get minimum and maximum usage date by iterating through
|
||||||
|
Long minDay = null;
|
||||||
|
Long maxDay = null;
|
||||||
|
for (long daysFromEpoch : dateCounts.keySet()) {
|
||||||
|
minDay = (minDay == null) ? daysFromEpoch : Math.min(minDay, daysFromEpoch);
|
||||||
|
maxDay = (maxDay == null) ? daysFromEpoch : Math.max(maxDay, daysFromEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no min date or max date, no usage; return null.
|
||||||
|
if (minDay == null || maxDay == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Date minDate = new Date(minDay * 1000 * DAY_SECS);
|
||||||
|
Date maxDate = new Date(maxDay * 1000 * DAY_SECS);
|
||||||
|
|
||||||
|
// The minimum recent day will be within recentDaysNum from the maximum day
|
||||||
|
// (+1 since maxDay included) or the minimum day of activity
|
||||||
|
long minRecentDay = Math.max(maxDay - recentDaysNum + 1, minDay);
|
||||||
|
|
||||||
|
// get most recent days activity
|
||||||
|
List<DailyActivityAmount> mostRecentActivityAmt = getMostRecentActivityAmounts(dateCounts, minRecentDay, maxDay);
|
||||||
|
|
||||||
|
return new TimelineSummaryData(minDate, maxDate, mostRecentActivityAmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given activity by day, converts to most recent days' activity handling
|
||||||
|
* empty values.
|
||||||
|
*
|
||||||
|
* @param dateCounts The day from epoch mapped to activity amounts for that
|
||||||
|
* day.
|
||||||
|
* @param minRecentDay The minimum recent day in days from epoch.
|
||||||
|
* @param maxDay The maximum recent day in days from epoch;
|
||||||
|
* @return The most recent daily activity amounts.
|
||||||
|
*/
|
||||||
|
private List<DailyActivityAmount> getMostRecentActivityAmounts(Map<Long, DailyActivityAmount> dateCounts, long minRecentDay, long maxDay) {
|
||||||
|
List<DailyActivityAmount> mostRecentActivityAmt = new ArrayList<>();
|
||||||
|
|
||||||
|
for (long curRecentDay = minRecentDay; curRecentDay <= maxDay; curRecentDay++) {
|
||||||
|
DailyActivityAmount prevCounts = dateCounts.get(curRecentDay);
|
||||||
|
DailyActivityAmount countsHandleNotFound = prevCounts != null
|
||||||
|
? prevCounts
|
||||||
|
: new DailyActivityAmount(new Date(curRecentDay * DAY_SECS * 1000), 0, 0);
|
||||||
|
|
||||||
|
mostRecentActivityAmt.add(countsHandleNotFound);
|
||||||
|
}
|
||||||
|
return mostRecentActivityAmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches timeline events per day for a particular data source.
|
||||||
|
*
|
||||||
|
* @param dataSource The data source.
|
||||||
|
* @param timelineManager The timeline manager to use while fetching the
|
||||||
|
* data.
|
||||||
|
* @param timeZone The time zone to use to determine which day activity
|
||||||
|
* belongs.
|
||||||
|
* @return A Map mapping days from epoch to the activity for that day.
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
private Map<Long, DailyActivityAmount> getTimelineEventsByDay(DataSource dataSource, TimelineManager timelineManager, TimeZone timeZone) throws TskCoreException {
|
||||||
|
|
||||||
|
DataSourcesFilter dataSourceFilter = new DataSourcesFilter();
|
||||||
|
dataSourceFilter.addSubFilter(new TimelineFilter.DataSourceFilter(dataSource.getName(), dataSource.getId()));
|
||||||
|
|
||||||
|
RootFilter dataSourceRootFilter = new RootFilter(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
dataSourceFilter,
|
||||||
|
null,
|
||||||
|
Collections.emptySet());
|
||||||
|
|
||||||
|
// get events for data source
|
||||||
|
long curRunTime = System.currentTimeMillis();
|
||||||
|
List<TimelineEvent> events = timelineManager.getEvents(new Interval(1, curRunTime), dataSourceRootFilter);
|
||||||
|
|
||||||
|
// get counts of events per day (left is file system events, right is everything else)
|
||||||
|
Map<Long, DailyActivityAmount> dateCounts = new HashMap<>();
|
||||||
|
for (TimelineEvent evt : events) {
|
||||||
|
long curSecondsFromEpoch = evt.getTime();
|
||||||
|
long curDaysFromEpoch = Instant.ofEpochMilli(curSecondsFromEpoch * 1000)
|
||||||
|
.atZone(timeZone.toZoneId())
|
||||||
|
.toLocalDate()
|
||||||
|
.toEpochDay();
|
||||||
|
|
||||||
|
DailyActivityAmount prevAmt = dateCounts.get(curDaysFromEpoch);
|
||||||
|
long prevFileEvtCount = prevAmt == null ? 0 : prevAmt.getFileActivityCount();
|
||||||
|
long prevArtifactEvtCount = prevAmt == null ? 0 : prevAmt.getArtifactActivityCount();
|
||||||
|
Date thisDay = prevAmt == null ? new Date(curDaysFromEpoch * 1000 * DAY_SECS) : prevAmt.getDay();
|
||||||
|
|
||||||
|
boolean isFileEvt = FILE_SYSTEM_EVENTS.contains(evt.getEventType());
|
||||||
|
long curFileEvtCount = prevFileEvtCount + (isFileEvt ? 1 : 0);
|
||||||
|
long curArtifactEvtCount = prevArtifactEvtCount + (isFileEvt ? 0 : 1);
|
||||||
|
|
||||||
|
dateCounts.put(curDaysFromEpoch, new DailyActivityAmount(thisDay, curFileEvtCount, curArtifactEvtCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
return dateCounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All the data to be represented in the timeline summary tab.
|
||||||
|
*/
|
||||||
|
public static class TimelineSummaryData {
|
||||||
|
|
||||||
|
private final Date minDate;
|
||||||
|
private final Date maxDate;
|
||||||
|
private final List<DailyActivityAmount> histogramActivity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor.
|
||||||
|
*
|
||||||
|
* @param minDate Earliest usage date recorded for the data source.
|
||||||
|
* @param maxDate Latest usage date recorded for the data source.
|
||||||
|
* @param recentDaysActivity A list of activity prior to and including
|
||||||
|
* the latest usage date by day.
|
||||||
|
*/
|
||||||
|
TimelineSummaryData(Date minDate, Date maxDate, List<DailyActivityAmount> recentDaysActivity) {
|
||||||
|
this.minDate = minDate;
|
||||||
|
this.maxDate = maxDate;
|
||||||
|
this.histogramActivity = (recentDaysActivity == null) ? Collections.emptyList() : Collections.unmodifiableList(recentDaysActivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Earliest usage date recorded for the data source.
|
||||||
|
*/
|
||||||
|
public Date getMinDate() {
|
||||||
|
return minDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Latest usage date recorded for the data source.
|
||||||
|
*/
|
||||||
|
public Date getMaxDate() {
|
||||||
|
return maxDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A list of activity prior to and including the latest usage
|
||||||
|
* date by day.
|
||||||
|
*/
|
||||||
|
public List<DailyActivityAmount> getMostRecentDaysActivity() {
|
||||||
|
return histogramActivity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the amount of usage based on timeline events for a day.
|
||||||
|
*/
|
||||||
|
public static class DailyActivityAmount {
|
||||||
|
|
||||||
|
private final Date day;
|
||||||
|
private final long fileActivityCount;
|
||||||
|
private final long artifactActivityCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor.
|
||||||
|
*
|
||||||
|
* @param day The day for which activity is being measured.
|
||||||
|
* @param fileActivityCount The amount of file activity timeline events.
|
||||||
|
* @param artifactActivityCount The amount of artifact timeline events.
|
||||||
|
*/
|
||||||
|
DailyActivityAmount(Date day, long fileActivityCount, long artifactActivityCount) {
|
||||||
|
this.day = day;
|
||||||
|
this.fileActivityCount = fileActivityCount;
|
||||||
|
this.artifactActivityCount = artifactActivityCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The day for which activity is being measured.
|
||||||
|
*/
|
||||||
|
public Date getDay() {
|
||||||
|
return day;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The amount of file activity timeline events.
|
||||||
|
*/
|
||||||
|
public long getFileActivityCount() {
|
||||||
|
return fileActivityCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The amount of artifact timeline events.
|
||||||
|
*/
|
||||||
|
public long getArtifactActivityCount() {
|
||||||
|
return artifactActivityCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -42,3 +42,4 @@ RecentFilesPanel.attachmentLabel.text=Recent Attachments
|
|||||||
PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable
|
PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable
|
||||||
PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs
|
PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs
|
||||||
DataSourceSummaryTabbedPane.noDataSourceLabel.text=No data source has been selected.
|
DataSourceSummaryTabbedPane.noDataSourceLabel.text=No data source has been selected.
|
||||||
|
TimelinePanel.activityRangeLabel.text=Activity Range
|
||||||
|
@ -3,6 +3,7 @@ AnalysisPanel_keyColumn_title=Name
|
|||||||
AnalysisPanel_keywordSearchModuleName=Keyword Search
|
AnalysisPanel_keywordSearchModuleName=Keyword Search
|
||||||
# {0} - module name
|
# {0} - module name
|
||||||
BaseDataSourceSummaryPanel_defaultNotIngestMessage=The {0} ingest module has not been run on this data source.
|
BaseDataSourceSummaryPanel_defaultNotIngestMessage=The {0} ingest module has not been run on this data source.
|
||||||
|
ContainerPanel_setFieldsForNonImageDataSource_na=N/A
|
||||||
CTL_DataSourceSummaryAction=Data Source Summary
|
CTL_DataSourceSummaryAction=Data Source Summary
|
||||||
DataSourceSummaryDialog.closeButton.text=Close
|
DataSourceSummaryDialog.closeButton.text=Close
|
||||||
ContainerPanel.displayNameLabel.text=Display Name:
|
ContainerPanel.displayNameLabel.text=Display Name:
|
||||||
@ -47,6 +48,7 @@ DataSourceSummaryTabbedPane_detailsTab_title=Container
|
|||||||
DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History
|
DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History
|
||||||
DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases
|
DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases
|
||||||
DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files
|
DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files
|
||||||
|
DataSourceSummaryTabbedPane_timelineTab_title=Timeline
|
||||||
DataSourceSummaryTabbedPane_typesTab_title=Types
|
DataSourceSummaryTabbedPane_typesTab_title=Types
|
||||||
DataSourceSummaryTabbedPane_userActivityTab_title=User Activity
|
DataSourceSummaryTabbedPane_userActivityTab_title=User Activity
|
||||||
PastCasesPanel_caseColumn_title=Case
|
PastCasesPanel_caseColumn_title=Case
|
||||||
@ -64,6 +66,11 @@ SizeRepresentationUtil_units_kilobytes=\ kB
|
|||||||
SizeRepresentationUtil_units_megabytes=\ MB
|
SizeRepresentationUtil_units_megabytes=\ MB
|
||||||
SizeRepresentationUtil_units_petabytes=\ PB
|
SizeRepresentationUtil_units_petabytes=\ PB
|
||||||
SizeRepresentationUtil_units_terabytes=\ TB
|
SizeRepresentationUtil_units_terabytes=\ TB
|
||||||
|
TimelinePanel_earliestLabel_title=Earliest
|
||||||
|
TimelinePanel_latestLabel_title=Latest
|
||||||
|
TimlinePanel_last30DaysChart_artifactEvts_title=Artifact Events
|
||||||
|
TimlinePanel_last30DaysChart_fileEvts_title=File Events
|
||||||
|
TimlinePanel_last30DaysChart_title=Last 30 Days
|
||||||
TypesPanel_artifactsTypesPieChart_title=Artifact Types
|
TypesPanel_artifactsTypesPieChart_title=Artifact Types
|
||||||
TypesPanel_fileMimeTypesChart_audio_title=Audio
|
TypesPanel_fileMimeTypesChart_audio_title=Audio
|
||||||
TypesPanel_fileMimeTypesChart_documents_title=Documents
|
TypesPanel_fileMimeTypesChart_documents_title=Documents
|
||||||
@ -95,6 +102,7 @@ RecentFilesPanel.attachmentLabel.text=Recent Attachments
|
|||||||
PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable
|
PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable
|
||||||
PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs
|
PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs
|
||||||
DataSourceSummaryTabbedPane.noDataSourceLabel.text=No data source has been selected.
|
DataSourceSummaryTabbedPane.noDataSourceLabel.text=No data source has been selected.
|
||||||
|
TimelinePanel.activityRangeLabel.text=Activity Range
|
||||||
UserActivityPanel_noDataExists=No communication data exists
|
UserActivityPanel_noDataExists=No communication data exists
|
||||||
UserActivityPanel_tab_title=User Activity
|
UserActivityPanel_tab_title=User Activity
|
||||||
UserActivityPanel_TopAccountTableModel_accountType_header=Account Type
|
UserActivityPanel_TopAccountTableModel_accountType_header=Account Type
|
||||||
|
@ -26,6 +26,7 @@ import java.util.Set;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import javax.swing.table.DefaultTableModel;
|
import javax.swing.table.DefaultTableModel;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary;
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType;
|
||||||
@ -165,8 +166,6 @@ class ContainerPanel extends BaseDataSourceSummaryPanel {
|
|||||||
private void updateDetailsPanelData(DataSource selectedDataSource, Long unallocatedFilesSize) {
|
private void updateDetailsPanelData(DataSource selectedDataSource, Long unallocatedFilesSize) {
|
||||||
clearTableValues();
|
clearTableValues();
|
||||||
if (selectedDataSource != null) {
|
if (selectedDataSource != null) {
|
||||||
unallocatedSizeValue.setText(SizeRepresentationUtil.getSizeString(unallocatedFilesSize));
|
|
||||||
timeZoneValue.setText(selectedDataSource.getTimeZone());
|
|
||||||
displayNameValue.setText(selectedDataSource.getName());
|
displayNameValue.setText(selectedDataSource.getName());
|
||||||
originalNameValue.setText(selectedDataSource.getName());
|
originalNameValue.setText(selectedDataSource.getName());
|
||||||
deviceIdValue.setText(selectedDataSource.getDeviceId());
|
deviceIdValue.setText(selectedDataSource.getDeviceId());
|
||||||
@ -178,24 +177,48 @@ class ContainerPanel extends BaseDataSourceSummaryPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selectedDataSource instanceof Image) {
|
if (selectedDataSource instanceof Image) {
|
||||||
setFieldsForImage((Image) selectedDataSource);
|
setFieldsForImage((Image) selectedDataSource, unallocatedFilesSize);
|
||||||
|
} else {
|
||||||
|
setFieldsForNonImageDataSource();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.repaint();
|
this.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"ContainerPanel_setFieldsForNonImageDataSource_na=N/A"
|
||||||
|
})
|
||||||
|
private void setFieldsForNonImageDataSource() {
|
||||||
|
String NA = Bundle.ContainerPanel_setFieldsForNonImageDataSource_na();
|
||||||
|
|
||||||
|
unallocatedSizeValue.setText(NA);
|
||||||
|
imageTypeValue.setText(NA);
|
||||||
|
sizeValue.setText(NA);
|
||||||
|
sectorSizeValue.setText(NA);
|
||||||
|
timeZoneValue.setText(NA);
|
||||||
|
|
||||||
|
((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{NA});
|
||||||
|
|
||||||
|
md5HashValue.setText(NA);
|
||||||
|
sha1HashValue.setText(NA);
|
||||||
|
sha256HashValue.setText(NA);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets text fields for an image. This should be called after
|
* Sets text fields for an image. This should be called after
|
||||||
* clearTableValues and before updateFieldVisibility to ensure the proper
|
* clearTableValues and before updateFieldVisibility to ensure the proper
|
||||||
* rendering.
|
* rendering.
|
||||||
*
|
*
|
||||||
* @param selectedImage The selected image.
|
* @param selectedImage The selected image.
|
||||||
|
* @param unallocatedFilesSize Unallocated file size in bytes.
|
||||||
*/
|
*/
|
||||||
private void setFieldsForImage(Image selectedImage) {
|
private void setFieldsForImage(Image selectedImage, Long unallocatedFilesSize) {
|
||||||
|
unallocatedSizeValue.setText(SizeRepresentationUtil.getSizeString(unallocatedFilesSize));
|
||||||
imageTypeValue.setText(selectedImage.getType().getName());
|
imageTypeValue.setText(selectedImage.getType().getName());
|
||||||
sizeValue.setText(SizeRepresentationUtil.getSizeString(selectedImage.getSize()));
|
sizeValue.setText(SizeRepresentationUtil.getSizeString(selectedImage.getSize()));
|
||||||
sectorSizeValue.setText(SizeRepresentationUtil.getSizeString(selectedImage.getSsize()));
|
sectorSizeValue.setText(SizeRepresentationUtil.getSizeString(selectedImage.getSsize()));
|
||||||
|
timeZoneValue.setText(selectedImage.getTimeZone());
|
||||||
|
|
||||||
for (String path : selectedImage.getPaths()) {
|
for (String path : selectedImage.getPaths()) {
|
||||||
((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{path});
|
((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{path});
|
||||||
|
@ -38,7 +38,8 @@ import org.sleuthkit.datamodel.DataSource;
|
|||||||
"DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History",
|
"DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History",
|
||||||
"DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files",
|
"DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files",
|
||||||
"DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases",
|
"DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases",
|
||||||
"DataSourceSummaryTabbedPane_analysisTab_title=Analysis"
|
"DataSourceSummaryTabbedPane_analysisTab_title=Analysis",
|
||||||
|
"DataSourceSummaryTabbedPane_timelineTab_title=Timeline"
|
||||||
})
|
})
|
||||||
public class DataSourceSummaryTabbedPane extends javax.swing.JPanel {
|
public class DataSourceSummaryTabbedPane extends javax.swing.JPanel {
|
||||||
|
|
||||||
@ -123,6 +124,7 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel {
|
|||||||
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_analysisTab_title(), new AnalysisPanel()),
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_analysisTab_title(), new AnalysisPanel()),
|
||||||
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_recentFileTab_title(), new RecentFilesPanel()),
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_recentFileTab_title(), new RecentFilesPanel()),
|
||||||
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_pastCasesTab_title(), new PastCasesPanel()),
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_pastCasesTab_title(), new PastCasesPanel()),
|
||||||
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_timelineTab_title(), new TimelinePanel()),
|
||||||
// do nothing on closing
|
// do nothing on closing
|
||||||
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_ingestHistoryTab_title(), ingestHistoryPanel, ingestHistoryPanel::setDataSource, () -> {
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_ingestHistoryTab_title(), ingestHistoryPanel, ingestHistoryPanel::setDataSource, () -> {
|
||||||
}),
|
}),
|
||||||
|
@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.datasourcesummary.ui;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleFactory;
|
import org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleFactory;
|
||||||
@ -28,7 +27,6 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary;
|
|||||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult;
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer.DefaultCellModel;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer.DefaultCellModel;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType;
|
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel;
|
||||||
@ -103,31 +101,8 @@ public class PastCasesPanel extends BaseDataSourceSummaryPanel {
|
|||||||
* @param result The result.
|
* @param result The result.
|
||||||
*/
|
*/
|
||||||
private void handleResult(DataFetchResult<PastCasesResult> result) {
|
private void handleResult(DataFetchResult<PastCasesResult> result) {
|
||||||
showResultWithModuleCheck(notableFileTable, getSubResult(result, (res) -> res.getTaggedNotable()), CR_FACTORY, CR_NAME);
|
showResultWithModuleCheck(notableFileTable, DataFetchResult.getSubResult(result, (res) -> res.getTaggedNotable()), CR_FACTORY, CR_NAME);
|
||||||
showResultWithModuleCheck(sameIdTable, getSubResult(result, (res) -> res.getSameIdsResults()), CR_FACTORY, CR_NAME);
|
showResultWithModuleCheck(sameIdTable, DataFetchResult.getSubResult(result, (res) -> res.getSameIdsResults()), CR_FACTORY, CR_NAME);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given an input data fetch result, creates an error result if the original
|
|
||||||
* is an error. Otherwise, uses the getSubResult function on the underlying
|
|
||||||
* data to create a new DataFetchResult.
|
|
||||||
*
|
|
||||||
* @param inputResult The input result.
|
|
||||||
* @param getSubComponent The means of getting the data given the original
|
|
||||||
* data.
|
|
||||||
*
|
|
||||||
* @return The new result with the error of the original or the processed
|
|
||||||
* data.
|
|
||||||
*/
|
|
||||||
private <O> DataFetchResult<O> getSubResult(DataFetchResult<PastCasesResult> inputResult, Function<PastCasesResult, O> getSubResult) {
|
|
||||||
if (inputResult == null) {
|
|
||||||
return null;
|
|
||||||
} else if (inputResult.getResultType() == ResultType.SUCCESS) {
|
|
||||||
O innerData = (inputResult.getData() == null) ? null : getSubResult.apply(inputResult.getData());
|
|
||||||
return DataFetchResult.getSuccessResult(innerData);
|
|
||||||
} else {
|
|
||||||
return DataFetchResult.getErrorResult(inputResult.getException());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,214 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="mainScrollPane" alignment="0" pref="400" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="mainScrollPane" alignment="0" pref="300" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="mainScrollPane">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JPanel" name="mainContentPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
|
||||||
|
<EmptyBorder bottom="10" left="10" right="10" top="10"/>
|
||||||
|
</Border>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||||
|
<Property name="axis" type="int" value="3"/>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JPanel" name="ingestRunningPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[32767, 25]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[10, 25]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[10, 25]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="ingestRunningLabel"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.JLabel" name="activityRangeLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||||
|
<Font name="Segoe UI" size="12" style="1"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="TimelinePanel.activityRangeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AccessibilityProperties>
|
||||||
|
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="PastCasesPanel.notableFileLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</AccessibilityProperties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.Box$Filler" name="filler1">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JPanel" name="earliestLabelPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[32767, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[100, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[100, 20]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="earliestLabel"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||||
|
</Container>
|
||||||
|
<Container class="javax.swing.JPanel" name="latestLabelPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[32767, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[100, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[100, 20]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="latestLabel"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.Box$Filler" name="filler2">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JPanel" name="sameIdPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[600, 300]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[600, 300]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[600, 300]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="last30DaysChart"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.Box$Filler" name="filler5">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 32767]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,263 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.datasourcesummary.ui;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.BarChartItem;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.BarChartSeries;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.OrderedKey;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel;
|
||||||
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tab shown in data source summary displaying information about a data
|
||||||
|
* source's timeline events.
|
||||||
|
*/
|
||||||
|
@Messages({
|
||||||
|
"TimelinePanel_earliestLabel_title=Earliest",
|
||||||
|
"TimelinePanel_latestLabel_title=Latest",
|
||||||
|
"TimlinePanel_last30DaysChart_title=Last 30 Days",
|
||||||
|
"TimlinePanel_last30DaysChart_fileEvts_title=File Events",
|
||||||
|
"TimlinePanel_last30DaysChart_artifactEvts_title=Artifact Events",})
|
||||||
|
public class TimelinePanel extends BaseDataSourceSummaryPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final DateFormat EARLIEST_LATEST_FORMAT = getUtcFormat("MMM d, yyyy");
|
||||||
|
private static final DateFormat CHART_FORMAT = getUtcFormat("MMM d");
|
||||||
|
private static final int MOST_RECENT_DAYS_COUNT = 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DateFormat formatter that uses UTC for time zone.
|
||||||
|
*
|
||||||
|
* @param formatString The date format string.
|
||||||
|
* @return The data format.
|
||||||
|
*/
|
||||||
|
private static DateFormat getUtcFormat(String formatString) {
|
||||||
|
return new SimpleDateFormat(formatString, Locale.getDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
// components displayed in the tab
|
||||||
|
private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel();
|
||||||
|
private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title());
|
||||||
|
private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title());
|
||||||
|
private final BarChartPanel last30DaysChart = new BarChartPanel(Bundle.TimlinePanel_last30DaysChart_title(), "", "");
|
||||||
|
|
||||||
|
// all loadable components on this tab
|
||||||
|
private final List<LoadableComponent<?>> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart);
|
||||||
|
|
||||||
|
// actions to load data for this tab
|
||||||
|
private final List<DataFetchComponents<DataSource, ?>> dataFetchComponents;
|
||||||
|
|
||||||
|
public TimelinePanel() {
|
||||||
|
this(new TimelineSummary());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form PastCasesPanel
|
||||||
|
*/
|
||||||
|
public TimelinePanel(TimelineSummary timelineData) {
|
||||||
|
// set up data acquisition methods
|
||||||
|
dataFetchComponents = Arrays.asList(
|
||||||
|
new DataFetchWorker.DataFetchComponents<>(
|
||||||
|
(dataSource) -> timelineData.getData(dataSource, MOST_RECENT_DAYS_COUNT),
|
||||||
|
(result) -> handleResult(result))
|
||||||
|
);
|
||||||
|
|
||||||
|
initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a date using a DateFormat. In the event that the date is null,
|
||||||
|
* returns a null string.
|
||||||
|
*
|
||||||
|
* @param date The date to format.
|
||||||
|
* @param formatter The DateFormat to use to format the date.
|
||||||
|
* @return The formatted string generated from the formatter or null if the
|
||||||
|
* date is null.
|
||||||
|
*/
|
||||||
|
private static String formatDate(Date date, DateFormat formatter) {
|
||||||
|
return date == null ? null : formatter.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Color FILE_EVT_COLOR = new Color(228, 22, 28);
|
||||||
|
private static final Color ARTIFACT_EVT_COLOR = new Color(21, 227, 100);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts DailyActivityAmount data retrieved from TimelineSummary into
|
||||||
|
* data to be displayed as a bar chart.
|
||||||
|
*
|
||||||
|
* @param recentDaysActivity The data retrieved from TimelineSummary.
|
||||||
|
* @return The data to be displayed in the BarChart.
|
||||||
|
*/
|
||||||
|
private List<BarChartSeries> parseChartData(List<DailyActivityAmount> recentDaysActivity) {
|
||||||
|
// if no data, return null indicating no result.
|
||||||
|
if (CollectionUtils.isEmpty(recentDaysActivity)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a bar chart item for each recent days activity item
|
||||||
|
List<BarChartItem> fileEvtCounts = new ArrayList<>();
|
||||||
|
List<BarChartItem> artifactEvtCounts = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < recentDaysActivity.size(); i++) {
|
||||||
|
DailyActivityAmount curItem = recentDaysActivity.get(i);
|
||||||
|
|
||||||
|
long fileAmt = curItem.getFileActivityCount();
|
||||||
|
long artifactAmt = curItem.getArtifactActivityCount() * 100;
|
||||||
|
String formattedDate = (i == 0 || i == recentDaysActivity.size() - 1)
|
||||||
|
? formatDate(curItem.getDay(), CHART_FORMAT) : "";
|
||||||
|
|
||||||
|
OrderedKey thisKey = new OrderedKey(formattedDate, i);
|
||||||
|
fileEvtCounts.add(new BarChartItem(thisKey, fileAmt));
|
||||||
|
artifactEvtCounts.add(new BarChartItem(thisKey, artifactAmt));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.asList(
|
||||||
|
new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_fileEvts_title(), FILE_EVT_COLOR, fileEvtCounts),
|
||||||
|
new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_artifactEvts_title(), ARTIFACT_EVT_COLOR, artifactEvtCounts));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles displaying the result for each displayable item in the
|
||||||
|
* TimelinePanel by breaking the TimelineSummaryData result into its
|
||||||
|
* constituent parts and then sending each data item to the pertinent
|
||||||
|
* component.
|
||||||
|
*
|
||||||
|
* @param result The result to be displayed on this tab.
|
||||||
|
*/
|
||||||
|
private void handleResult(DataFetchResult<TimelineSummaryData> result) {
|
||||||
|
earliestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> formatDate(r.getMinDate(), EARLIEST_LATEST_FORMAT)));
|
||||||
|
latestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> formatDate(r.getMaxDate(), EARLIEST_LATEST_FORMAT)));
|
||||||
|
last30DaysChart.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseChartData(r.getMostRecentDaysActivity())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void fetchInformation(DataSource dataSource) {
|
||||||
|
fetchInformation(dataFetchComponents, dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onNewDataSource(DataSource dataSource) {
|
||||||
|
onNewDataSource(dataFetchComponents, loadableComponents, dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
ingestRunningLabel.unregister();
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
javax.swing.JScrollPane mainScrollPane = new javax.swing.JScrollPane();
|
||||||
|
javax.swing.JPanel mainContentPanel = new javax.swing.JPanel();
|
||||||
|
javax.swing.JPanel ingestRunningPanel = ingestRunningLabel;
|
||||||
|
javax.swing.JLabel activityRangeLabel = new javax.swing.JLabel();
|
||||||
|
javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2));
|
||||||
|
javax.swing.JPanel earliestLabelPanel = earliestLabel;
|
||||||
|
javax.swing.JPanel latestLabelPanel = latestLabel;
|
||||||
|
javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20));
|
||||||
|
javax.swing.JPanel sameIdPanel = last30DaysChart;
|
||||||
|
javax.swing.Box.Filler filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
|
||||||
|
|
||||||
|
mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
mainContentPanel.setLayout(new javax.swing.BoxLayout(mainContentPanel, javax.swing.BoxLayout.PAGE_AXIS));
|
||||||
|
|
||||||
|
ingestRunningPanel.setAlignmentX(0.0F);
|
||||||
|
ingestRunningPanel.setMaximumSize(new java.awt.Dimension(32767, 25));
|
||||||
|
ingestRunningPanel.setMinimumSize(new java.awt.Dimension(10, 25));
|
||||||
|
ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25));
|
||||||
|
mainContentPanel.add(ingestRunningPanel);
|
||||||
|
|
||||||
|
activityRangeLabel.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(activityRangeLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.activityRangeLabel.text")); // NOI18N
|
||||||
|
mainContentPanel.add(activityRangeLabel);
|
||||||
|
activityRangeLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(TimelinePanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
filler1.setAlignmentX(0.0F);
|
||||||
|
mainContentPanel.add(filler1);
|
||||||
|
|
||||||
|
earliestLabelPanel.setAlignmentX(0.0F);
|
||||||
|
earliestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20));
|
||||||
|
earliestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20));
|
||||||
|
earliestLabelPanel.setPreferredSize(new java.awt.Dimension(100, 20));
|
||||||
|
mainContentPanel.add(earliestLabelPanel);
|
||||||
|
|
||||||
|
latestLabelPanel.setAlignmentX(0.0F);
|
||||||
|
latestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20));
|
||||||
|
latestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20));
|
||||||
|
latestLabelPanel.setPreferredSize(new java.awt.Dimension(100, 20));
|
||||||
|
mainContentPanel.add(latestLabelPanel);
|
||||||
|
|
||||||
|
filler2.setAlignmentX(0.0F);
|
||||||
|
mainContentPanel.add(filler2);
|
||||||
|
|
||||||
|
sameIdPanel.setAlignmentX(0.0F);
|
||||||
|
sameIdPanel.setMaximumSize(new java.awt.Dimension(600, 300));
|
||||||
|
sameIdPanel.setMinimumSize(new java.awt.Dimension(600, 300));
|
||||||
|
sameIdPanel.setPreferredSize(new java.awt.Dimension(600, 300));
|
||||||
|
sameIdPanel.setVerifyInputWhenFocusTarget(false);
|
||||||
|
mainContentPanel.add(sameIdPanel);
|
||||||
|
|
||||||
|
filler5.setAlignmentX(0.0F);
|
||||||
|
mainContentPanel.add(filler5);
|
||||||
|
|
||||||
|
mainScrollPane.setViewportView(mainContentPanel);
|
||||||
|
|
||||||
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
|
this.setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
@ -30,7 +29,6 @@ import java.util.Set;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import javax.swing.JLabel;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory;
|
import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory;
|
||||||
@ -40,13 +38,13 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary;
|
|||||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.IngestModuleCheckUtil;
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.IngestModuleCheckUtil;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.MimeTypeSummary;
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.MimeTypeSummary;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.AbstractLoadableComponent;
|
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartPanel;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartPanel;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartPanel.PieChartItem;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartPanel.PieChartItem;
|
||||||
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory;
|
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory;
|
||||||
@ -78,46 +76,6 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
"TypesPanel_sizeLabel_title=Size"})
|
"TypesPanel_sizeLabel_title=Size"})
|
||||||
class TypesPanel extends BaseDataSourceSummaryPanel {
|
class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||||
|
|
||||||
/**
|
|
||||||
* A label that allows for displaying loading messages and can be used with
|
|
||||||
* a DataFetchResult. Text displays as "<key>:<value | message>".
|
|
||||||
*/
|
|
||||||
private static class LoadableLabel extends AbstractLoadableComponent<String> {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
private final JLabel label = new JLabel();
|
|
||||||
private final String key;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main constructor for the label.
|
|
||||||
*
|
|
||||||
* @param key The key to be displayed.
|
|
||||||
*/
|
|
||||||
LoadableLabel(String key) {
|
|
||||||
this.key = key;
|
|
||||||
setLayout(new BorderLayout());
|
|
||||||
add(label, BorderLayout.CENTER);
|
|
||||||
this.showResults(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setValue(String value) {
|
|
||||||
String formattedKey = StringUtils.isBlank(key) ? "" : key;
|
|
||||||
String formattedValue = StringUtils.isBlank(value) ? "" : value;
|
|
||||||
label.setText(String.format("%s: %s", formattedKey, formattedValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setMessage(boolean visible, String message) {
|
|
||||||
setValue(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setResults(String data) {
|
|
||||||
setValue(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data for types pie chart.
|
* Data for types pie chart.
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,307 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.datasourcesummary.uiutils;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.jfree.chart.ChartFactory;
|
||||||
|
import org.jfree.chart.ChartPanel;
|
||||||
|
import org.jfree.chart.JFreeChart;
|
||||||
|
import org.jfree.chart.axis.ValueAxis;
|
||||||
|
import org.jfree.chart.plot.CategoryPlot;
|
||||||
|
import org.jfree.chart.plot.PlotOrientation;
|
||||||
|
import org.jfree.chart.renderer.category.BarRenderer;
|
||||||
|
import org.jfree.chart.renderer.category.StandardBarPainter;
|
||||||
|
import org.jfree.data.category.DefaultCategoryDataset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bar chart panel.
|
||||||
|
*/
|
||||||
|
public class BarChartPanel extends AbstractLoadableComponent<List<BarChartPanel.BarChartSeries>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a series in a bar chart where all items pertain to one
|
||||||
|
* category.
|
||||||
|
*/
|
||||||
|
public static class BarChartSeries {
|
||||||
|
|
||||||
|
private final Comparable<?> key;
|
||||||
|
private final Color color;
|
||||||
|
private final List<BarChartItem> items;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor.
|
||||||
|
*
|
||||||
|
* @param color The color for this series.
|
||||||
|
* @param items The bars to be displayed for this series.
|
||||||
|
*/
|
||||||
|
public BarChartSeries(Comparable<?> key, Color color, List<BarChartItem> items) {
|
||||||
|
this.key = key;
|
||||||
|
this.color = color;
|
||||||
|
this.items = (items == null) ? Collections.emptyList() : Collections.unmodifiableList(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The color for this series.
|
||||||
|
*/
|
||||||
|
public Color getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The bars to be displayed for this series.
|
||||||
|
*/
|
||||||
|
public List<BarChartItem> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The key for this item.
|
||||||
|
*/
|
||||||
|
public Comparable<?> getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An individual bar to be displayed in the bar chart.
|
||||||
|
*/
|
||||||
|
public static class BarChartItem {
|
||||||
|
|
||||||
|
private final Comparable<?> key;
|
||||||
|
private final double value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor.
|
||||||
|
*
|
||||||
|
* @param label The key for this bar. Also serves as the label using
|
||||||
|
* toString().
|
||||||
|
* @param value The value for this item.
|
||||||
|
*/
|
||||||
|
public BarChartItem(Comparable<?> key, double value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The key for this item.
|
||||||
|
*/
|
||||||
|
public Comparable<?> getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The value for this item.
|
||||||
|
*/
|
||||||
|
public double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JFreeChart bar charts don't preserve the order of bars provided to the
|
||||||
|
* chart, but instead uses the comparable nature to order items. This
|
||||||
|
* provides order using a provided index as well as the value for the axis.
|
||||||
|
*/
|
||||||
|
public static class OrderedKey implements Comparable<OrderedKey> {
|
||||||
|
|
||||||
|
private final Object keyValue;
|
||||||
|
private final int keyIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor.
|
||||||
|
*
|
||||||
|
* @param keyValue The value for the key to be displayed in the domain
|
||||||
|
* axis.
|
||||||
|
* @param keyIndex The index at which it will be displayed.
|
||||||
|
*/
|
||||||
|
public OrderedKey(Object keyValue, int keyIndex) {
|
||||||
|
this.keyValue = keyValue;
|
||||||
|
this.keyIndex = keyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The value for the key to be displayed in the domain axis.
|
||||||
|
*/
|
||||||
|
Object getKeyValue() {
|
||||||
|
return keyValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The index at which it will be displayed.
|
||||||
|
*/
|
||||||
|
int getKeyIndex() {
|
||||||
|
return keyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(OrderedKey o) {
|
||||||
|
// this will have a higher value than null.
|
||||||
|
if (o == null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare by index
|
||||||
|
return Integer.compare(this.getKeyIndex(), o.getKeyIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 3;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final OrderedKey other = (OrderedKey) obj;
|
||||||
|
if (this.keyIndex != other.keyIndex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
// use toString on the key.
|
||||||
|
return this.getKeyValue() == null ? null : this.getKeyValue().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final Font DEFAULT_FONT = new JLabel().getFont();
|
||||||
|
private static final Font DEFAULT_HEADER_FONT = new Font(DEFAULT_FONT.getName(), DEFAULT_FONT.getStyle(), (int) (DEFAULT_FONT.getSize() * 1.5));
|
||||||
|
|
||||||
|
private final ChartMessageOverlay overlay = new ChartMessageOverlay();
|
||||||
|
private final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
|
||||||
|
private final JFreeChart chart;
|
||||||
|
private final CategoryPlot plot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor assuming null values for all items.
|
||||||
|
*/
|
||||||
|
public BarChartPanel() {
|
||||||
|
this(null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor for the pie chart.
|
||||||
|
*
|
||||||
|
* @param title The title for this pie chart.
|
||||||
|
* @param categoryLabel The x-axis label.
|
||||||
|
* @param valueLabel The y-axis label.
|
||||||
|
*/
|
||||||
|
public BarChartPanel(String title, String categoryLabel, String valueLabel) {
|
||||||
|
this.chart = ChartFactory.createStackedBarChart(
|
||||||
|
title,
|
||||||
|
categoryLabel,
|
||||||
|
valueLabel,
|
||||||
|
dataset,
|
||||||
|
PlotOrientation.VERTICAL,
|
||||||
|
true, false, false);
|
||||||
|
|
||||||
|
// set style to match autopsy components
|
||||||
|
chart.setBackgroundPaint(null);
|
||||||
|
chart.getTitle().setFont(DEFAULT_HEADER_FONT);
|
||||||
|
|
||||||
|
this.plot = ((CategoryPlot) chart.getPlot());
|
||||||
|
this.plot.getRenderer().setBaseItemLabelFont(DEFAULT_FONT);
|
||||||
|
plot.setBackgroundPaint(null);
|
||||||
|
plot.setOutlinePaint(null);
|
||||||
|
|
||||||
|
// hide y axis labels
|
||||||
|
ValueAxis range = plot.getRangeAxis();
|
||||||
|
range.setVisible(false);
|
||||||
|
|
||||||
|
// make sure x axis labels don't get cut off
|
||||||
|
plot.getDomainAxis().setMaximumCategoryLabelWidthRatio(10);
|
||||||
|
|
||||||
|
((BarRenderer) plot.getRenderer()).setBarPainter(new StandardBarPainter());
|
||||||
|
|
||||||
|
// Create Panel
|
||||||
|
ChartPanel panel = new ChartPanel(chart);
|
||||||
|
panel.addOverlay(overlay);
|
||||||
|
panel.setPopupMenu(null);
|
||||||
|
|
||||||
|
this.setLayout(new BorderLayout());
|
||||||
|
this.add(panel, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The title for this chart if one exists.
|
||||||
|
*/
|
||||||
|
public String getTitle() {
|
||||||
|
return (this.chart == null || this.chart.getTitle() == null)
|
||||||
|
? null
|
||||||
|
: this.chart.getTitle().getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the title for this pie chart.
|
||||||
|
*
|
||||||
|
* @param title The title.
|
||||||
|
*
|
||||||
|
* @return As a utility, returns this.
|
||||||
|
*/
|
||||||
|
public BarChartPanel setTitle(String title) {
|
||||||
|
this.chart.getTitle().setText(title);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setMessage(boolean visible, String message) {
|
||||||
|
this.overlay.setVisible(visible);
|
||||||
|
this.overlay.setMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setResults(List<BarChartPanel.BarChartSeries> data) {
|
||||||
|
this.dataset.clear();
|
||||||
|
|
||||||
|
if (CollectionUtils.isNotEmpty(data)) {
|
||||||
|
for (int s = 0; s < data.size(); s++) {
|
||||||
|
BarChartPanel.BarChartSeries series = data.get(s);
|
||||||
|
if (series != null && CollectionUtils.isNotEmpty(series.getItems())) {
|
||||||
|
if (series.getColor() != null) {
|
||||||
|
this.plot.getRenderer().setSeriesPaint(s, series.getColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < series.getItems().size(); i++) {
|
||||||
|
BarChartItem bar = series.getItems().get(i);
|
||||||
|
this.dataset.setValue(bar.getValue(), series.getKey(), bar.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.datasourcesummary.uiutils;
|
||||||
|
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import org.jfree.chart.ChartPanel;
|
||||||
|
import org.jfree.chart.panel.AbstractOverlay;
|
||||||
|
import org.jfree.chart.panel.Overlay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JFreeChart message overlay that can show a message for the purposes of the
|
||||||
|
* LoadableComponent.
|
||||||
|
*/
|
||||||
|
class ChartMessageOverlay extends AbstractOverlay implements Overlay {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final BaseMessageOverlay overlay = new BaseMessageOverlay();
|
||||||
|
|
||||||
|
// multiply this value by the smaller dimension (height or width) of the component
|
||||||
|
// to determine width of text to be displayed.
|
||||||
|
private static final double MESSAGE_WIDTH_FACTOR = .6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this layer visible when painted. In order to be shown in UI, this
|
||||||
|
* component needs to be repainted.
|
||||||
|
*
|
||||||
|
* @param visible Whether or not it is visible.
|
||||||
|
*/
|
||||||
|
void setVisible(boolean visible) {
|
||||||
|
overlay.setVisible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the message to be displayed in the child jlabel.
|
||||||
|
*
|
||||||
|
* @param message The message to be displayed.
|
||||||
|
*/
|
||||||
|
void setMessage(String message) {
|
||||||
|
overlay.setMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintOverlay(Graphics2D gd, ChartPanel cp) {
|
||||||
|
int labelWidth = (int) (Math.min(cp.getWidth(), cp.getHeight()) * MESSAGE_WIDTH_FACTOR);
|
||||||
|
overlay.paintOverlay(gd, cp.getWidth(), cp.getHeight(), labelWidth);
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datasourcesummary.uiutils;
|
package org.sleuthkit.autopsy.datasourcesummary.uiutils;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The result of a loading process.
|
* The result of a loading process.
|
||||||
*/
|
*/
|
||||||
@ -30,6 +32,29 @@ public final class DataFetchResult<R> {
|
|||||||
SUCCESS, ERROR
|
SUCCESS, ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility method that, given an input data fetch result, creates an error
|
||||||
|
* result if the original is an error. Otherwise, uses the getSubResult
|
||||||
|
* function on the underlying data to create a new DataFetchResult.
|
||||||
|
*
|
||||||
|
* @param inputResult The input result.
|
||||||
|
* @param getSubComponent The means of getting the data given the original
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* @return The new result with the error of the original or the processed
|
||||||
|
* data.
|
||||||
|
*/
|
||||||
|
public static <I, O> DataFetchResult<O> getSubResult(DataFetchResult<I> inputResult, Function<I, O> getSubResult) {
|
||||||
|
if (inputResult == null) {
|
||||||
|
return null;
|
||||||
|
} else if (inputResult.getResultType() == ResultType.SUCCESS) {
|
||||||
|
O innerData = (inputResult.getData() == null) ? null : getSubResult.apply(inputResult.getData());
|
||||||
|
return DataFetchResult.getSuccessResult(innerData);
|
||||||
|
} else {
|
||||||
|
return DataFetchResult.getErrorResult(inputResult.getException());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a DataFetchResult of loaded data including the data.
|
* Creates a DataFetchResult of loaded data including the data.
|
||||||
*
|
*
|
||||||
@ -60,8 +85,7 @@ public final class DataFetchResult<R> {
|
|||||||
* Main constructor for the DataLoadingResult.
|
* Main constructor for the DataLoadingResult.
|
||||||
*
|
*
|
||||||
* @param state The state of the result.
|
* @param state The state of the result.
|
||||||
* @param data If the result is SUCCESS, the data related to this
|
* @param data If the result is SUCCESS, the data related to this result.
|
||||||
* result.
|
|
||||||
* @param exception If the result is ERROR, the related exception.
|
* @param exception If the result is ERROR, the related exception.
|
||||||
*/
|
*/
|
||||||
private DataFetchResult(ResultType state, R data, Throwable exception) {
|
private DataFetchResult(ResultType state, R data, Throwable exception) {
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.datasourcesummary.uiutils;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A label that allows for displaying loading messages and can be used with a
|
||||||
|
* DataFetchResult. Text displays as "<key>:<value | message>".
|
||||||
|
*/
|
||||||
|
public class LoadableLabel extends AbstractLoadableComponent<String> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final JLabel label = new JLabel();
|
||||||
|
private final String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor for the label.
|
||||||
|
*
|
||||||
|
* @param key The key to be displayed.
|
||||||
|
*/
|
||||||
|
public LoadableLabel(String key) {
|
||||||
|
this.key = key;
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
add(label, BorderLayout.CENTER);
|
||||||
|
this.showResults(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setValue(String value) {
|
||||||
|
String formattedKey = StringUtils.isBlank(key) ? "" : key;
|
||||||
|
String formattedValue = StringUtils.isBlank(value) ? "" : value;
|
||||||
|
label.setText(String.format("%s: %s", formattedKey, formattedValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setMessage(boolean visible, String message) {
|
||||||
|
setValue(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setResults(String data) {
|
||||||
|
setValue(data);
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.datasourcesummary.uiutils;
|
|||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Graphics2D;
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
@ -30,8 +29,6 @@ import org.jfree.chart.ChartPanel;
|
|||||||
import org.jfree.chart.JFreeChart;
|
import org.jfree.chart.JFreeChart;
|
||||||
import org.jfree.chart.labels.PieSectionLabelGenerator;
|
import org.jfree.chart.labels.PieSectionLabelGenerator;
|
||||||
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
|
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
|
||||||
import org.jfree.chart.panel.AbstractOverlay;
|
|
||||||
import org.jfree.chart.panel.Overlay;
|
|
||||||
import org.jfree.chart.plot.PiePlot;
|
import org.jfree.chart.plot.PiePlot;
|
||||||
import org.jfree.data.general.DefaultPieDataset;
|
import org.jfree.data.general.DefaultPieDataset;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
@ -89,46 +86,6 @@ public class PieChartPanel extends AbstractLoadableComponent<List<PieChartPanel.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A JFreeChart message overlay that can show a message for the purposes of
|
|
||||||
* the LoadableComponent.
|
|
||||||
*/
|
|
||||||
private static class MessageOverlay extends AbstractOverlay implements Overlay {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
private final BaseMessageOverlay overlay = new BaseMessageOverlay();
|
|
||||||
|
|
||||||
// multiply this value by the smaller dimension (height or width) of the component
|
|
||||||
// to determine width of text to be displayed.
|
|
||||||
private static final double MESSAGE_WIDTH_FACTOR = .6;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets this layer visible when painted. In order to be shown in UI,
|
|
||||||
* this component needs to be repainted.
|
|
||||||
*
|
|
||||||
* @param visible Whether or not it is visible.
|
|
||||||
*/
|
|
||||||
void setVisible(boolean visible) {
|
|
||||||
overlay.setVisible(visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the message to be displayed in the child jlabel.
|
|
||||||
*
|
|
||||||
* @param message The message to be displayed.
|
|
||||||
*/
|
|
||||||
void setMessage(String message) {
|
|
||||||
overlay.setMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void paintOverlay(Graphics2D gd, ChartPanel cp) {
|
|
||||||
int labelWidth = (int) (Math.min(cp.getWidth(), cp.getHeight()) * MESSAGE_WIDTH_FACTOR);
|
|
||||||
overlay.paintOverlay(gd, cp.getWidth(), cp.getHeight(), labelWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private static final Font DEFAULT_FONT = new JLabel().getFont();
|
private static final Font DEFAULT_FONT = new JLabel().getFont();
|
||||||
@ -146,7 +103,7 @@ public class PieChartPanel extends AbstractLoadableComponent<List<PieChartPanel.
|
|||||||
= new StandardPieSectionLabelGenerator(
|
= new StandardPieSectionLabelGenerator(
|
||||||
"{0}: {1} ({2})", new DecimalFormat("#,###"), new DecimalFormat("0.0%"));
|
"{0}: {1} ({2})", new DecimalFormat("#,###"), new DecimalFormat("0.0%"));
|
||||||
|
|
||||||
private final MessageOverlay overlay = new MessageOverlay();
|
private final ChartMessageOverlay overlay = new ChartMessageOverlay();
|
||||||
private final DefaultPieDataset dataset = new DefaultPieDataset();
|
private final DefaultPieDataset dataset = new DefaultPieDataset();
|
||||||
private final JFreeChart chart;
|
private final JFreeChart chart;
|
||||||
private final PiePlot plot;
|
private final PiePlot plot;
|
||||||
|
@ -19,12 +19,14 @@
|
|||||||
package org.sleuthkit.autopsy.discovery.search;
|
package org.sleuthkit.autopsy.discovery.search;
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData.Type;
|
import org.sleuthkit.autopsy.discovery.search.SearchData.Type;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to handle event bus and events for discovery tool.
|
* Class to handle event bus and events for discovery tool.
|
||||||
@ -90,8 +92,8 @@ public final class DiscoveryEventUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event to signal that any background tasks currently running should
|
* Event to signal that any background tasks currently running should be
|
||||||
* be cancelled.
|
* cancelled.
|
||||||
*/
|
*/
|
||||||
public static final class CancelBackgroundTasksEvent {
|
public static final class CancelBackgroundTasksEvent {
|
||||||
|
|
||||||
@ -124,6 +126,30 @@ public final class DiscoveryEventUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event to signal that the list should be populated.
|
||||||
|
*/
|
||||||
|
public static final class PopulateDomainTabsEvent {
|
||||||
|
|
||||||
|
private final String domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new PopulateDomainTabsEvent.
|
||||||
|
*/
|
||||||
|
public PopulateDomainTabsEvent(String domain) {
|
||||||
|
this.domain = domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the domain for the details area.
|
||||||
|
*
|
||||||
|
* @return The the domain for the details area.
|
||||||
|
*/
|
||||||
|
public String getDomain() {
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event to signal the completion of a search being performed.
|
* Event to signal the completion of a search being performed.
|
||||||
*/
|
*/
|
||||||
@ -203,6 +229,47 @@ public final class DiscoveryEventUtils {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event to signal the completion of a search being performed.
|
||||||
|
*/
|
||||||
|
public static final class ArtifactSearchResultEvent {
|
||||||
|
|
||||||
|
private final List<BlackboardArtifact> listOfArtifacts = new ArrayList<>();
|
||||||
|
private final BlackboardArtifact.ARTIFACT_TYPE artifactType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new ArtifactSearchResultEvent with a list of specified
|
||||||
|
* artifacts and an artifact type.
|
||||||
|
*
|
||||||
|
* @param artifactType The type of artifacts in the list.
|
||||||
|
* @param listOfArtifacts The list of artifacts retrieved.
|
||||||
|
*/
|
||||||
|
public ArtifactSearchResultEvent(BlackboardArtifact.ARTIFACT_TYPE artifactType, List<BlackboardArtifact> listOfArtifacts) {
|
||||||
|
if (listOfArtifacts != null) {
|
||||||
|
this.listOfArtifacts.addAll(listOfArtifacts);
|
||||||
|
}
|
||||||
|
this.artifactType = artifactType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of artifacts included in the event.
|
||||||
|
*
|
||||||
|
* @return The list of artifacts retrieved.
|
||||||
|
*/
|
||||||
|
public List<BlackboardArtifact> getListOfArtifacts() {
|
||||||
|
return Collections.unmodifiableList(listOfArtifacts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of BlackboardArtifact type of which exist in the list.
|
||||||
|
*
|
||||||
|
* @return The BlackboardArtifact type of which exist in the list.
|
||||||
|
*/
|
||||||
|
public BlackboardArtifact.ARTIFACT_TYPE getArtifactType() {
|
||||||
|
return artifactType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event to signal the completion of page retrieval and include the page
|
* Event to signal the completion of page retrieval and include the page
|
||||||
* contents.
|
* contents.
|
||||||
|
@ -33,6 +33,7 @@ import org.sleuthkit.datamodel.TagName;
|
|||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -217,6 +218,15 @@ public class SearchFiltering {
|
|||||||
this.types = types;
|
this.types = types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of artifact types specified by the filter.
|
||||||
|
*
|
||||||
|
* @return The list of artifact types specified by the filter.
|
||||||
|
*/
|
||||||
|
public List<ARTIFACT_TYPE> getTypes() {
|
||||||
|
return Collections.unmodifiableList(types);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getWhereClause() {
|
public String getWhereClause() {
|
||||||
StringJoiner joiner = new StringJoiner(",");
|
StringJoiner joiner = new StringJoiner(",");
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.discovery.ui;
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for ensuring all ArtifactDetailsPanels have a setArtifact method.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class AbstractArtifactDetailsPanel extends JPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to display the contents of the given artifact.
|
||||||
|
*
|
||||||
|
* @param artifact the artifact to display.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
abstract public void setArtifact(BlackboardArtifact artifact);
|
||||||
|
|
||||||
|
}
|
@ -24,6 +24,7 @@ import javax.swing.JCheckBox;
|
|||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class extending JPanel for filter controls.
|
* Abstract class extending JPanel for filter controls.
|
||||||
@ -41,6 +42,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel {
|
|||||||
* selected, null to indicate leaving selected items
|
* selected, null to indicate leaving selected items
|
||||||
* unchanged or that there are no items to select.
|
* unchanged or that there are no items to select.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
abstract void configurePanel(boolean selected, int[] indicesSelected);
|
abstract void configurePanel(boolean selected, int[] indicesSelected);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,6 +50,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @return The JCheckBox which enables and disables this filter.
|
* @return The JCheckBox which enables and disables this filter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
abstract JCheckBox getCheckbox();
|
abstract JCheckBox getCheckbox();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,6 +60,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel {
|
|||||||
* @return The JList which contains the values available for selection for
|
* @return The JList which contains the values available for selection for
|
||||||
* this filter.
|
* this filter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
abstract JList<?> getList();
|
abstract JList<?> getList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,6 +69,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @return The JLabel to display under the JCheckBox.
|
* @return The JLabel to display under the JCheckBox.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
abstract JLabel getAdditionalLabel();
|
abstract JLabel getAdditionalLabel();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,6 +78,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel {
|
|||||||
* @return If the settings are invalid returns the error that has occurred,
|
* @return If the settings are invalid returns the error that has occurred,
|
||||||
* otherwise returns empty string.
|
* otherwise returns empty string.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
abstract String checkForError();
|
abstract String checkForError();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,6 +88,7 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel {
|
|||||||
* @param actionlistener The listener for the checkbox selection events.
|
* @param actionlistener The listener for the checkbox selection events.
|
||||||
* @param listListener The listener for the list selection events.
|
* @param listListener The listener for the list selection events.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void addListeners(ActionListener actionListener, ListSelectionListener listListener) {
|
void addListeners(ActionListener actionListener, ListSelectionListener listListener) {
|
||||||
if (getCheckbox() != null) {
|
if (getCheckbox() != null) {
|
||||||
getCheckbox().addActionListener(actionListener);
|
getCheckbox().addActionListener(actionListener);
|
||||||
@ -97,11 +104,13 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel {
|
|||||||
* @return The AbstractFilter for the selected settings, null if the
|
* @return The AbstractFilter for the selected settings, null if the
|
||||||
* settings are not in use.
|
* settings are not in use.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
abstract AbstractFilter getFilter();
|
abstract AbstractFilter getFilter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove listeners from the checkbox and the list if they exist.
|
* Remove listeners from the checkbox and the list if they exist.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void removeListeners() {
|
void removeListeners() {
|
||||||
if (getCheckbox() != null) {
|
if (getCheckbox() != null) {
|
||||||
for (ActionListener listener : getCheckbox().getActionListeners()) {
|
for (ActionListener listener : getCheckbox().getActionListeners()) {
|
||||||
|
@ -32,6 +32,7 @@ import javax.swing.JSplitPane;
|
|||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes.GroupingAttributeType;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes.GroupingAttributeType;
|
||||||
import org.sleuthkit.autopsy.discovery.search.Group;
|
import org.sleuthkit.autopsy.discovery.search.Group;
|
||||||
import org.sleuthkit.autopsy.discovery.search.ResultsSorter.SortingMethod;
|
import org.sleuthkit.autopsy.discovery.search.ResultsSorter.SortingMethod;
|
||||||
@ -65,6 +66,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
/**
|
/**
|
||||||
* Setup necessary for implementations of this abstract class.
|
* Setup necessary for implementations of this abstract class.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
AbstractFiltersPanel() {
|
AbstractFiltersPanel() {
|
||||||
firstColumnPanel.setLayout(new GridBagLayout());
|
firstColumnPanel.setLayout(new GridBagLayout());
|
||||||
secondColumnPanel.setLayout(new GridBagLayout());
|
secondColumnPanel.setLayout(new GridBagLayout());
|
||||||
@ -75,6 +77,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
*
|
*
|
||||||
* @return The type of results this panel filters.
|
* @return The type of results this panel filters.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
abstract SearchData.Type getType();
|
abstract SearchData.Type getType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,7 +91,8 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
* list, null if none are selected.
|
* list, null if none are selected.
|
||||||
* @param column The column to add the DiscoveryFilterPanel to.
|
* @param column The column to add the DiscoveryFilterPanel to.
|
||||||
*/
|
*/
|
||||||
final synchronized void addFilter(AbstractDiscoveryFilterPanel filterPanel, boolean isSelected, int[] indicesSelected, int column) {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
final void addFilter(AbstractDiscoveryFilterPanel filterPanel, boolean isSelected, int[] indicesSelected, int column) {
|
||||||
if (!isInitialized) {
|
if (!isInitialized) {
|
||||||
constraints.gridy = 0;
|
constraints.gridy = 0;
|
||||||
constraints.anchor = GridBagConstraints.FIRST_LINE_START;
|
constraints.anchor = GridBagConstraints.FIRST_LINE_START;
|
||||||
@ -132,6 +136,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
*
|
*
|
||||||
* @param splitPane The JSplitPane which the columns are added to.
|
* @param splitPane The JSplitPane which the columns are added to.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
final void addPanelsToScrollPane(JSplitPane splitPane) {
|
final void addPanelsToScrollPane(JSplitPane splitPane) {
|
||||||
splitPane.setLeftComponent(firstColumnPanel);
|
splitPane.setLeftComponent(firstColumnPanel);
|
||||||
splitPane.setRightComponent(secondColumnPanel);
|
splitPane.setRightComponent(secondColumnPanel);
|
||||||
@ -142,7 +147,8 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
/**
|
/**
|
||||||
* Clear the filters from the panel
|
* Clear the filters from the panel
|
||||||
*/
|
*/
|
||||||
final synchronized void clearFilters() {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
final void clearFilters() {
|
||||||
for (AbstractDiscoveryFilterPanel filterPanel : filters) {
|
for (AbstractDiscoveryFilterPanel filterPanel : filters) {
|
||||||
filterPanel.removeListeners();
|
filterPanel.removeListeners();
|
||||||
}
|
}
|
||||||
@ -159,6 +165,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
* column.
|
* column.
|
||||||
* @param columnIndex The column to add the Component to.
|
* @param columnIndex The column to add the Component to.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void addToGridBagLayout(Component componentToAdd, Component additionalComponentToAdd, int columnIndex) {
|
private void addToGridBagLayout(Component componentToAdd, Component additionalComponentToAdd, int columnIndex) {
|
||||||
addToColumn(componentToAdd, columnIndex);
|
addToColumn(componentToAdd, columnIndex);
|
||||||
if (additionalComponentToAdd != null) {
|
if (additionalComponentToAdd != null) {
|
||||||
@ -174,6 +181,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
* @param component The Component to add.
|
* @param component The Component to add.
|
||||||
* @param columnNumber The column to add the Component to.
|
* @param columnNumber The column to add the Component to.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void addToColumn(Component component, int columnNumber) {
|
private void addToColumn(Component component, int columnNumber) {
|
||||||
if (columnNumber == 0) {
|
if (columnNumber == 0) {
|
||||||
firstColumnPanel.add(component, constraints);
|
firstColumnPanel.add(component, constraints);
|
||||||
@ -186,7 +194,8 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
* Check if the fields are valid, and fire a property change event to
|
* Check if the fields are valid, and fire a property change event to
|
||||||
* indicate any errors.
|
* indicate any errors.
|
||||||
*/
|
*/
|
||||||
synchronized void validateFields() {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void validateFields() {
|
||||||
String errorString = null;
|
String errorString = null;
|
||||||
for (AbstractDiscoveryFilterPanel filterPanel : filters) {
|
for (AbstractDiscoveryFilterPanel filterPanel : filters) {
|
||||||
errorString = filterPanel.checkForError();
|
errorString = filterPanel.checkForError();
|
||||||
@ -197,6 +206,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
firePropertyChange("FilterError", null, errorString);
|
firePropertyChange("FilterError", null, errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
validateFields();
|
validateFields();
|
||||||
@ -209,6 +219,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
*
|
*
|
||||||
* @return True if the ObjectsDetectedFilter is supported, false otherwise.
|
* @return True if the ObjectsDetectedFilter is supported, false otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
boolean isObjectsFilterSupported() {
|
boolean isObjectsFilterSupported() {
|
||||||
for (AbstractDiscoveryFilterPanel filter : filters) {
|
for (AbstractDiscoveryFilterPanel filter : filters) {
|
||||||
if (filter instanceof ObjectDetectedFilterPanel) {
|
if (filter instanceof ObjectDetectedFilterPanel) {
|
||||||
@ -223,6 +234,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
*
|
*
|
||||||
* @return True if the HashSetFilter is supported, false otherwise.
|
* @return True if the HashSetFilter is supported, false otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
boolean isHashSetFilterSupported() {
|
boolean isHashSetFilterSupported() {
|
||||||
for (AbstractDiscoveryFilterPanel filter : filters) {
|
for (AbstractDiscoveryFilterPanel filter : filters) {
|
||||||
if (filter instanceof HashSetFilterPanel) {
|
if (filter instanceof HashSetFilterPanel) {
|
||||||
@ -237,6 +249,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
*
|
*
|
||||||
* @return True if the InterestingItemsFilter is supported, false otherwise.
|
* @return True if the InterestingItemsFilter is supported, false otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
boolean isInterestingItemsFilterSupported() {
|
boolean isInterestingItemsFilterSupported() {
|
||||||
for (AbstractDiscoveryFilterPanel filter : filters) {
|
for (AbstractDiscoveryFilterPanel filter : filters) {
|
||||||
if (filter instanceof InterestingItemsFilterPanel) {
|
if (filter instanceof InterestingItemsFilterPanel) {
|
||||||
@ -251,8 +264,8 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
*
|
*
|
||||||
* @return The list of filters selected by the user.
|
* @return The list of filters selected by the user.
|
||||||
*/
|
*/
|
||||||
synchronized List<AbstractFilter> getFilters() {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
List<AbstractFilter> getFilters() {
|
||||||
List<AbstractFilter> filtersToUse = new ArrayList<>();
|
List<AbstractFilter> filtersToUse = new ArrayList<>();
|
||||||
if (getType() != SearchData.Type.DOMAIN) { //Domain type does not have a file type
|
if (getType() != SearchData.Type.DOMAIN) { //Domain type does not have a file type
|
||||||
filtersToUse.add(new SearchFiltering.FileTypeFilter(getType()));
|
filtersToUse.add(new SearchFiltering.FileTypeFilter(getType()));
|
||||||
@ -268,6 +281,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
return filtersToUse;
|
return filtersToUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public void valueChanged(ListSelectionEvent evt) {
|
public void valueChanged(ListSelectionEvent evt) {
|
||||||
if (!evt.getValueIsAdjusting()) {
|
if (!evt.getValueIsAdjusting()) {
|
||||||
@ -282,6 +296,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
*
|
*
|
||||||
* @return The most recently used sorting method.
|
* @return The most recently used sorting method.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
SortingMethod getLastSortingMethod() {
|
SortingMethod getLastSortingMethod() {
|
||||||
return lastSortingMethod;
|
return lastSortingMethod;
|
||||||
}
|
}
|
||||||
@ -291,6 +306,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
*
|
*
|
||||||
* @param lastSortingMethod The most recently used sorting method.
|
* @param lastSortingMethod The most recently used sorting method.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
final void setLastSortingMethod(SortingMethod lastSortingMethod) {
|
final void setLastSortingMethod(SortingMethod lastSortingMethod) {
|
||||||
this.lastSortingMethod = lastSortingMethod;
|
this.lastSortingMethod = lastSortingMethod;
|
||||||
}
|
}
|
||||||
@ -300,6 +316,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
*
|
*
|
||||||
* @return The most recently used grouping attribute.
|
* @return The most recently used grouping attribute.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
GroupingAttributeType getLastGroupingAttributeType() {
|
GroupingAttributeType getLastGroupingAttributeType() {
|
||||||
return lastGroupingAttributeType;
|
return lastGroupingAttributeType;
|
||||||
}
|
}
|
||||||
@ -310,6 +327,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
* @param lastGroupingAttributeType The most recently used grouping
|
* @param lastGroupingAttributeType The most recently used grouping
|
||||||
* attribute.
|
* attribute.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
final void setLastGroupingAttributeType(GroupingAttributeType lastGroupingAttributeType) {
|
final void setLastGroupingAttributeType(GroupingAttributeType lastGroupingAttributeType) {
|
||||||
this.lastGroupingAttributeType = lastGroupingAttributeType;
|
this.lastGroupingAttributeType = lastGroupingAttributeType;
|
||||||
}
|
}
|
||||||
@ -319,6 +337,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
*
|
*
|
||||||
* @return The most recently used group sorting algorithm.
|
* @return The most recently used group sorting algorithm.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
Group.GroupSortingAlgorithm getLastGroupSortingAlg() {
|
Group.GroupSortingAlgorithm getLastGroupSortingAlg() {
|
||||||
return lastGroupSortingAlg;
|
return lastGroupSortingAlg;
|
||||||
}
|
}
|
||||||
@ -329,6 +348,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
|||||||
* @param lastGroupSortingAlg The most recently used group sorting
|
* @param lastGroupSortingAlg The most recently used group sorting
|
||||||
* algorithm.
|
* algorithm.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
final void setLastGroupSortingAlg(Group.GroupSortingAlgorithm lastGroupSortingAlg) {
|
final void setLastGroupSortingAlg(Group.GroupSortingAlgorithm lastGroupSortingAlg) {
|
||||||
this.lastGroupSortingAlg = lastGroupSortingAlg;
|
this.lastGroupSortingAlg = lastGroupSortingAlg;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import javax.swing.JCheckBox;
|
|||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ArtifactTypeFilter;
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ArtifactTypeFilter;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
@ -40,6 +41,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form ArtifactTypeFilterPanel
|
* Creates new form ArtifactTypeFilterPanel
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
ArtifactTypeFilterPanel() {
|
ArtifactTypeFilterPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
setUpArtifactTypeFilter();
|
setUpArtifactTypeFilter();
|
||||||
@ -49,6 +51,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Initialize the data source filter.
|
* Initialize the data source filter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void setUpArtifactTypeFilter() {
|
private void setUpArtifactTypeFilter() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
DefaultListModel<ArtifactTypeItem> artifactTypeModel = (DefaultListModel<ArtifactTypeItem>) artifactList.getModel();
|
DefaultListModel<ArtifactTypeItem> artifactTypeModel = (DefaultListModel<ArtifactTypeItem>) artifactList.getModel();
|
||||||
@ -104,6 +107,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
artifactList.setEnabled(artifactTypeCheckbox.isSelected());
|
artifactList.setEnabled(artifactTypeCheckbox.isSelected());
|
||||||
}//GEN-LAST:event_artifactTypeCheckboxActionPerformed
|
}//GEN-LAST:event_artifactTypeCheckboxActionPerformed
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||||
artifactTypeCheckbox.setSelected(selected);
|
artifactTypeCheckbox.setSelected(selected);
|
||||||
@ -119,11 +123,13 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JCheckBox getCheckbox() {
|
JCheckBox getCheckbox() {
|
||||||
return artifactTypeCheckbox;
|
return artifactTypeCheckbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JList<?> getList() {
|
JList<?> getList() {
|
||||||
return artifactList;
|
return artifactList;
|
||||||
@ -134,6 +140,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({"ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected."})
|
@NbBundle.Messages({"ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected."})
|
||||||
@Override
|
@Override
|
||||||
String checkForError() {
|
String checkForError() {
|
||||||
@ -143,6 +150,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
AbstractFilter getFilter() {
|
AbstractFilter getFilter() {
|
||||||
if (artifactTypeCheckbox.isSelected() && !artifactList.getSelectedValuesList().isEmpty()) {
|
if (artifactTypeCheckbox.isSelected() && !artifactList.getSelectedValuesList().isEmpty()) {
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.6" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<Properties>
|
||||||
|
<Property name="opaque" type="boolean" value="false"/>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="jScrollPane1" pref="400" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="jScrollPane1" alignment="0" pref="607" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||||
|
<Properties>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="null"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JTable" name="jTable1">
|
||||||
|
<Properties>
|
||||||
|
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
||||||
|
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
|
<Connection code="tableModel" type="code"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
||||||
|
<JTableSelectionModel selectionMode="0"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,346 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.discovery.ui;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panel to display list of artifacts for selected domain.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class ArtifactsListPanel extends JPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final DomainArtifactTableModel tableModel;
|
||||||
|
private static final Logger logger = Logger.getLogger(ArtifactsListPanel.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form ArtifactsListPanel.
|
||||||
|
*
|
||||||
|
* @param artifactType The type of artifact displayed in this table.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
ArtifactsListPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) {
|
||||||
|
tableModel = new DomainArtifactTableModel(artifactType);
|
||||||
|
initComponents();
|
||||||
|
jTable1.getRowSorter().toggleSortOrder(0);
|
||||||
|
jTable1.getRowSorter().toggleSortOrder(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a listener to the table of artifacts to perform actions when an
|
||||||
|
* artifact is selected.
|
||||||
|
*
|
||||||
|
* @param listener The listener to add to the table of artifacts.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void addSelectionListener(ListSelectionListener listener) {
|
||||||
|
jTable1.getSelectionModel().addListSelectionListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a listener from the table of artifacts.
|
||||||
|
*
|
||||||
|
* @param listener The listener to remove from the table of artifacts.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void removeListSelectionListener(ListSelectionListener listener) {
|
||||||
|
jTable1.getSelectionModel().removeListSelectionListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The artifact which is currently selected, null if no artifact is
|
||||||
|
* selected.
|
||||||
|
*
|
||||||
|
* @return The currently selected BlackboardArtifact or null if none is
|
||||||
|
* selected.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
BlackboardArtifact getSelectedArtifact() {
|
||||||
|
int selectedIndex = jTable1.getSelectionModel().getLeadSelectionIndex();
|
||||||
|
if (selectedIndex < jTable1.getSelectionModel().getMinSelectionIndex() || jTable1.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex > jTable1.getSelectionModel().getMaxSelectionIndex()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return tableModel.getArtifactByRow(jTable1.convertRowIndexToModel(selectedIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the list of artifacts is empty.
|
||||||
|
*
|
||||||
|
* @return true if the list of artifacts is empty, false if there are
|
||||||
|
* artifacts.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
boolean isEmpty() {
|
||||||
|
return tableModel.getRowCount() <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select the first available artifact in the list if it is not empty to
|
||||||
|
* populate the panel to the right.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void selectFirst() {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
jTable1.setRowSelectionInterval(0, 0);
|
||||||
|
} else {
|
||||||
|
jTable1.clearSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the specified list of artifacts to the list of artifacts which should
|
||||||
|
* be displayed.
|
||||||
|
*
|
||||||
|
* @param artifactList The list of artifacts to display.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void addArtifacts(List<BlackboardArtifact> artifactList) {
|
||||||
|
tableModel.setContents(artifactList);
|
||||||
|
jTable1.validate();
|
||||||
|
jTable1.repaint();
|
||||||
|
tableModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all artifacts from the list of artifacts displayed.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void clearArtifacts() {
|
||||||
|
tableModel.setContents(new ArrayList<>());
|
||||||
|
tableModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
|
||||||
|
jTable1 = new javax.swing.JTable();
|
||||||
|
|
||||||
|
setOpaque(false);
|
||||||
|
|
||||||
|
jScrollPane1.setBorder(null);
|
||||||
|
|
||||||
|
jTable1.setAutoCreateRowSorter(true);
|
||||||
|
jTable1.setModel(tableModel);
|
||||||
|
jTable1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
jScrollPane1.setViewportView(jTable1);
|
||||||
|
|
||||||
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
|
this.setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 607, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table model which allows the artifact table in this panel to mimic a list
|
||||||
|
* of artifacts.
|
||||||
|
*/
|
||||||
|
private class DomainArtifactTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final List<BlackboardArtifact> artifactList = new ArrayList<>();
|
||||||
|
private final BlackboardArtifact.ARTIFACT_TYPE artifactType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new DomainArtifactTableModel.
|
||||||
|
*
|
||||||
|
* @param artifactType The type of artifact displayed in this table.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
DomainArtifactTableModel(BlackboardArtifact.ARTIFACT_TYPE artifactType) {
|
||||||
|
this.artifactType = artifactType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the list of artifacts which should be represented by this table
|
||||||
|
* model.
|
||||||
|
*
|
||||||
|
* @param artifacts The list of BlackboardArtifacts to represent.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void setContents(List<BlackboardArtifact> artifacts) {
|
||||||
|
jTable1.clearSelection();
|
||||||
|
artifactList.clear();
|
||||||
|
artifactList.addAll(artifacts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
@Override
|
||||||
|
public int getRowCount() {
|
||||||
|
return artifactList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
@Override
|
||||||
|
public int getColumnCount() {
|
||||||
|
if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) {
|
||||||
|
return 3;
|
||||||
|
} else {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the BlackboardArtifact at the specified row.
|
||||||
|
*
|
||||||
|
* @param rowIndex The row the artifact to return is at.
|
||||||
|
*
|
||||||
|
* @return The BlackboardArtifact at the specified row.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
BlackboardArtifact getArtifactByRow(int rowIndex) {
|
||||||
|
return artifactList.get(rowIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
@NbBundle.Messages({"ArtifactsListPanel.value.noValue=No value available."})
|
||||||
|
@Override
|
||||||
|
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||||
|
if (columnIndex < 2 || artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) {
|
||||||
|
try {
|
||||||
|
for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) {
|
||||||
|
if (!StringUtils.isBlank(bba.getDisplayString())) {
|
||||||
|
String stringFromAttribute = getStringForColumn(bba, columnIndex);
|
||||||
|
if (!StringUtils.isBlank(stringFromAttribute)) {
|
||||||
|
return stringFromAttribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getFallbackValue(rowIndex, columnIndex);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.WARNING, "Error getting attributes for artifact " + getArtifactByRow(rowIndex).getArtifactID(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Bundle.ArtifactsListPanel_value_noValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the appropriate String for the specified column from the
|
||||||
|
* BlackboardAttribute.
|
||||||
|
*
|
||||||
|
* @param bba The BlackboardAttribute which may contain a value.
|
||||||
|
* @param columnIndex The column the value will be displayed in.
|
||||||
|
*
|
||||||
|
* @return The value from the specified attribute which should be
|
||||||
|
* displayed in the specified column, null if the specified
|
||||||
|
* attribute does not contain a value for that column.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException When unable to get abstract files based on
|
||||||
|
* the TSK_PATH_ID.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
private String getStringForColumn(BlackboardAttribute bba, int columnIndex) throws TskCoreException {
|
||||||
|
if (columnIndex == 0 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) {
|
||||||
|
return bba.getDisplayString();
|
||||||
|
} else if (columnIndex == 1) {
|
||||||
|
if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD || artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) {
|
||||||
|
if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) {
|
||||||
|
return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getName();
|
||||||
|
} else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID()) {
|
||||||
|
return FilenameUtils.getName(bba.getDisplayString());
|
||||||
|
}
|
||||||
|
} else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID()) {
|
||||||
|
return bba.getDisplayString();
|
||||||
|
}
|
||||||
|
} else if (columnIndex == 2 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) {
|
||||||
|
return Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bba.getValueLong()).getMIMEType();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private helper method to use when the value we want for either date
|
||||||
|
* or title is not available.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param rowIndex The row the artifact to return is at.
|
||||||
|
* @param columnIndex The column index the attribute will be displayed
|
||||||
|
* at.
|
||||||
|
*
|
||||||
|
* @return A string that can be used in place of the accessed date time
|
||||||
|
* attribute title when they are not available.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
private String getFallbackValue(int rowIndex, int columnIndex) throws TskCoreException {
|
||||||
|
for (BlackboardAttribute bba : getArtifactByRow(rowIndex).getAttributes()) {
|
||||||
|
if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME") && !StringUtils.isBlank(bba.getDisplayString())) {
|
||||||
|
return bba.getDisplayString();
|
||||||
|
} else if (columnIndex == 1 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) {
|
||||||
|
return bba.getDisplayString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Bundle.ArtifactsListPanel_value_noValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
@NbBundle.Messages({"ArtifactsListPanel.titleColumn.name=Title",
|
||||||
|
"ArtifactsListPanel.fileNameColumn.name=Name",
|
||||||
|
"ArtifactsListPanel.dateColumn.name=Date/Time",
|
||||||
|
"ArtifactsListPanel.mimeTypeColumn.name=MIME Type"})
|
||||||
|
@Override
|
||||||
|
public String getColumnName(int column) {
|
||||||
|
switch (column) {
|
||||||
|
case 0:
|
||||||
|
return Bundle.ArtifactsListPanel_dateColumn_name();
|
||||||
|
case 1:
|
||||||
|
if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE || artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) {
|
||||||
|
return Bundle.ArtifactsListPanel_fileNameColumn_name();
|
||||||
|
} else {
|
||||||
|
return Bundle.ArtifactsListPanel_titleColumn_name();
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
return Bundle.ArtifactsListPanel_mimeTypeColumn_name();
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JTable jTable1;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.discovery.ui;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DomainSearch;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DomainSearchArtifactsRequest;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SwingWorker to retrieve a list of artifacts for a specified type and domain.
|
||||||
|
*/
|
||||||
|
class ArtifactsWorker extends SwingWorker<List<BlackboardArtifact>, Void> {
|
||||||
|
|
||||||
|
private final BlackboardArtifact.ARTIFACT_TYPE artifactType;
|
||||||
|
private final static Logger logger = Logger.getLogger(ArtifactsWorker.class.getName());
|
||||||
|
private final String domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new ArtifactsWorker.
|
||||||
|
*
|
||||||
|
* @param artifactType The type of artifact being retrieved.
|
||||||
|
* @param domain The domain the artifacts should have as an attribute.
|
||||||
|
*/
|
||||||
|
ArtifactsWorker(BlackboardArtifact.ARTIFACT_TYPE artifactType, String domain) {
|
||||||
|
this.artifactType = artifactType;
|
||||||
|
this.domain = domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<BlackboardArtifact> doInBackground() throws Exception {
|
||||||
|
if (artifactType != null && !StringUtils.isBlank(domain)) {
|
||||||
|
DomainSearch domainSearch = new DomainSearch();
|
||||||
|
return domainSearch.getArtifacts(new DomainSearchArtifactsRequest(Case.getCurrentCase().getSleuthkitCase(), domain, artifactType));
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
List<BlackboardArtifact> listOfArtifacts = new ArrayList<>();
|
||||||
|
if (!isCancelled()) {
|
||||||
|
try {
|
||||||
|
listOfArtifacts.addAll(get());
|
||||||
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Exception while trying to get list of artifacts for Domain details for artifact type: "
|
||||||
|
+ artifactType.getDisplayName() + " and domain: " + domain, ex);
|
||||||
|
} catch (CancellationException ignored) {
|
||||||
|
//Worker was cancelled after previously finishing its background work, exception ignored to cut down on non-helpful logging
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.ArtifactSearchResultEvent(artifactType, listOfArtifacts));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -51,10 +51,12 @@ HashSetFilterPanel.hashSetCheckbox.text=Hash Set:
|
|||||||
PastOccurrencesFilterPanel.pastOccurrencesCheckbox.text=Past Occurrences:
|
PastOccurrencesFilterPanel.pastOccurrencesCheckbox.text=Past Occurrences:
|
||||||
DocumentFilterPanel.documentsFiltersSplitPane.border.title=Step 2: Filter which documents to show
|
DocumentFilterPanel.documentsFiltersSplitPane.border.title=Step 2: Filter which documents to show
|
||||||
ObjectDetectedFilterPanel.text=Object Detected:
|
ObjectDetectedFilterPanel.text=Object Detected:
|
||||||
DetailsPanel.instancesList.border.title=Instances
|
|
||||||
DateFilterPanel.mostRecentRadioButton.text=Only last:
|
DateFilterPanel.mostRecentRadioButton.text=Only last:
|
||||||
DateFilterPanel.dateFilterCheckBox.text=Date Filter:
|
DateFilterPanel.dateFilterCheckBox.text=Date Filter:
|
||||||
DomainSummaryPanel.activityLabel.text=
|
DomainSummaryPanel.activityLabel.text=
|
||||||
DomainSummaryPanel.pagesLabel.text=
|
DomainSummaryPanel.pagesLabel.text=
|
||||||
DomainSummaryPanel.filesDownloadedLabel.text=
|
DomainSummaryPanel.filesDownloadedLabel.text=
|
||||||
DomainSummaryPanel.totalVisitsLabel.text=
|
DomainSummaryPanel.totalVisitsLabel.text=
|
||||||
|
FileDetailsPanel.instancesList.border.title=Instances
|
||||||
|
CookieDetailsPanel.jLabel1.text=Artifact:
|
||||||
|
CookieDetailsPanel.jLabel2.text=
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
ArtifactsListPanel.dateColumn.name=Date/Time
|
||||||
|
ArtifactsListPanel.fileNameColumn.name=Name
|
||||||
|
ArtifactsListPanel.mimeTypeColumn.name=MIME Type
|
||||||
|
ArtifactsListPanel.titleColumn.name=Title
|
||||||
|
ArtifactsListPanel.value.noValue=No value available.
|
||||||
ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected.
|
ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected.
|
||||||
CTL_OpenDiscoveryAction=Discovery
|
CTL_OpenDiscoveryAction=Discovery
|
||||||
DataSourceFilterPanel.error.text=At least one data source must be selected.
|
DataSourceFilterPanel.error.text=At least one data source must be selected.
|
||||||
@ -126,13 +131,15 @@ HashSetFilterPanel.hashSetCheckbox.text=Hash Set:
|
|||||||
PastOccurrencesFilterPanel.pastOccurrencesCheckbox.text=Past Occurrences:
|
PastOccurrencesFilterPanel.pastOccurrencesCheckbox.text=Past Occurrences:
|
||||||
DocumentFilterPanel.documentsFiltersSplitPane.border.title=Step 2: Filter which documents to show
|
DocumentFilterPanel.documentsFiltersSplitPane.border.title=Step 2: Filter which documents to show
|
||||||
ObjectDetectedFilterPanel.text=Object Detected:
|
ObjectDetectedFilterPanel.text=Object Detected:
|
||||||
DetailsPanel.instancesList.border.title=Instances
|
|
||||||
DateFilterPanel.mostRecentRadioButton.text=Only last:
|
DateFilterPanel.mostRecentRadioButton.text=Only last:
|
||||||
DateFilterPanel.dateFilterCheckBox.text=Date Filter:
|
DateFilterPanel.dateFilterCheckBox.text=Date Filter:
|
||||||
DomainSummaryPanel.activityLabel.text=
|
DomainSummaryPanel.activityLabel.text=
|
||||||
DomainSummaryPanel.pagesLabel.text=
|
DomainSummaryPanel.pagesLabel.text=
|
||||||
DomainSummaryPanel.filesDownloadedLabel.text=
|
DomainSummaryPanel.filesDownloadedLabel.text=
|
||||||
DomainSummaryPanel.totalVisitsLabel.text=
|
DomainSummaryPanel.totalVisitsLabel.text=
|
||||||
|
FileDetailsPanel.instancesList.border.title=Instances
|
||||||
|
CookieDetailsPanel.jLabel1.text=Artifact:
|
||||||
|
CookieDetailsPanel.jLabel2.text=
|
||||||
VideoThumbnailPanel.bytes.text=bytes
|
VideoThumbnailPanel.bytes.text=bytes
|
||||||
VideoThumbnailPanel.deleted.text=All instances of file are deleted.
|
VideoThumbnailPanel.deleted.text=All instances of file are deleted.
|
||||||
VideoThumbnailPanel.gigaBytes.text=GB
|
VideoThumbnailPanel.gigaBytes.text=GB
|
||||||
@ -144,3 +151,7 @@ VideoThumbnailPanel.nameLabel.more.text=\ and {0} more
|
|||||||
# {1} - units
|
# {1} - units
|
||||||
VideoThumbnailPanel.sizeLabel.text=Size: {0} {1}
|
VideoThumbnailPanel.sizeLabel.text=Size: {0} {1}
|
||||||
VideoThumbnailPanel.terraBytes.text=TB
|
VideoThumbnailPanel.terraBytes.text=TB
|
||||||
|
WebHistoryDetailsPanel.details.attrHeader=Attributes
|
||||||
|
WebHistoryDetailsPanel.details.dataSource=Data Source
|
||||||
|
WebHistoryDetailsPanel.details.file=File
|
||||||
|
WebHistoryDetailsPanel.details.sourceHeader=Source
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
|
</Form>
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.discovery.ui;
|
||||||
|
|
||||||
|
import org.openide.nodes.Node;
|
||||||
|
import org.sleuthkit.autopsy.corecomponents.DataContentPanel;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Details panel for displaying the collection of content viewers.
|
||||||
|
*/
|
||||||
|
final class ContentViewerDetailsPanel extends AbstractArtifactDetailsPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final DataContentPanel contentViewer = DataContentPanel.createInstance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form ContentViewerDetailsPanel
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
ContentViewerDetailsPanel() {
|
||||||
|
initComponents();
|
||||||
|
add(contentViewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
setLayout(new java.awt.BorderLayout());
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
@Override
|
||||||
|
public void setArtifact(BlackboardArtifact artifact) {
|
||||||
|
Node node = Node.EMPTY;
|
||||||
|
if (artifact != null) {
|
||||||
|
node = new BlackboardArtifactNode(artifact);
|
||||||
|
}
|
||||||
|
contentViewer.setNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -30,6 +30,7 @@ import javax.swing.JList;
|
|||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
||||||
import org.sleuthkit.datamodel.DataSource;
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
@ -45,6 +46,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form DataSourceFilterPanel.
|
* Creates new form DataSourceFilterPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
DataSourceFilterPanel() {
|
DataSourceFilterPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
setUpDataSourceFilter();
|
setUpDataSourceFilter();
|
||||||
@ -109,6 +111,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
private javax.swing.JScrollPane dataSourceScrollPane;
|
private javax.swing.JScrollPane dataSourceScrollPane;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||||
dataSourceCheckbox.setSelected(selected);
|
dataSourceCheckbox.setSelected(selected);
|
||||||
@ -124,6 +127,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JCheckBox getCheckbox() {
|
JCheckBox getCheckbox() {
|
||||||
return dataSourceCheckbox;
|
return dataSourceCheckbox;
|
||||||
@ -137,6 +141,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Initialize the data source filter.
|
* Initialize the data source filter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void setUpDataSourceFilter() {
|
private void setUpDataSourceFilter() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
try {
|
try {
|
||||||
@ -156,6 +161,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JList<?> getList() {
|
JList<?> getList() {
|
||||||
return dataSourceList;
|
return dataSourceList;
|
||||||
@ -193,6 +199,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({"DataSourceFilterPanel.error.text=At least one data source must be selected."})
|
@NbBundle.Messages({"DataSourceFilterPanel.error.text=At least one data source must be selected."})
|
||||||
@Override
|
@Override
|
||||||
String checkForError() {
|
String checkForError() {
|
||||||
@ -202,6 +209,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
AbstractFilter getFilter() {
|
AbstractFilter getFilter() {
|
||||||
if (dataSourceCheckbox.isSelected()) {
|
if (dataSourceCheckbox.isSelected()) {
|
||||||
|
@ -33,6 +33,7 @@ import javax.swing.JSpinner;
|
|||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.communications.Utils;
|
import org.sleuthkit.autopsy.communications.Utils;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,6 +49,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
*/
|
*/
|
||||||
@NbBundle.Messages({"# {0} - timeZone",
|
@NbBundle.Messages({"# {0} - timeZone",
|
||||||
"DateFilterPanel.dateRange.text=Date Range ({0}):"})
|
"DateFilterPanel.dateRange.text=Date Range ({0}):"})
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
DateFilterPanel() {
|
DateFilterPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
rangeRadioButton.setText(Bundle.DateFilterPanel_dateRange_text(Utils.getUserPreferredZoneId().toString()));
|
rangeRadioButton.setText(Bundle.DateFilterPanel_dateRange_text(Utils.getUserPreferredZoneId().toString()));
|
||||||
@ -225,6 +227,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
endCheckBox.firePropertyChange("EndButtonChange", true, false);
|
endCheckBox.firePropertyChange("EndButtonChange", true, false);
|
||||||
}//GEN-LAST:event_rangeRadioButtonStateChanged
|
}//GEN-LAST:event_rangeRadioButtonStateChanged
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||||
dateFilterCheckBox.setSelected(selected);
|
dateFilterCheckBox.setSelected(selected);
|
||||||
@ -238,6 +241,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JCheckBox getCheckbox() {
|
JCheckBox getCheckbox() {
|
||||||
return dateFilterCheckBox;
|
return dateFilterCheckBox;
|
||||||
@ -253,6 +257,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void addListeners(ActionListener actionListener, ListSelectionListener listListener) {
|
void addListeners(ActionListener actionListener, ListSelectionListener listListener) {
|
||||||
dateFilterCheckBox.addActionListener(actionListener);
|
dateFilterCheckBox.addActionListener(actionListener);
|
||||||
@ -274,6 +279,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void removeListeners() {
|
void removeListeners() {
|
||||||
for (ActionListener listener : dateFilterCheckBox.getActionListeners()) {
|
for (ActionListener listener : dateFilterCheckBox.getActionListeners()) {
|
||||||
@ -302,6 +308,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({"DateFilterPanel.invalidRange.text=Range or Only Last must be selected.",
|
@NbBundle.Messages({"DateFilterPanel.invalidRange.text=Range or Only Last must be selected.",
|
||||||
"DateFilterPanel.startOrEndNeeded.text=A start or end date must be specified to use the range filter.",
|
"DateFilterPanel.startOrEndNeeded.text=A start or end date must be specified to use the range filter.",
|
||||||
"DateFilterPanel.startAfterEnd.text=Start date should be before the end date when both are enabled."})
|
"DateFilterPanel.startAfterEnd.text=Start date should be before the end date when both are enabled."})
|
||||||
@ -320,6 +327,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
AbstractFilter getFilter() {
|
AbstractFilter getFilter() {
|
||||||
if (dateFilterCheckBox.isSelected()) {
|
if (dateFilterCheckBox.isSelected()) {
|
||||||
|
@ -40,6 +40,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
|||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
import org.sleuthkit.autopsy.discovery.search.Group;
|
import org.sleuthkit.autopsy.discovery.search.Group;
|
||||||
@ -99,6 +100,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
/**
|
/**
|
||||||
* Private constructor to construct a new DiscoveryDialog
|
* Private constructor to construct a new DiscoveryDialog
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Messages("DiscoveryDialog.name.text=Discovery")
|
@Messages("DiscoveryDialog.name.text=Discovery")
|
||||||
private DiscoveryDialog() {
|
private DiscoveryDialog() {
|
||||||
super(WindowManager.getDefault().getMainWindow(), Bundle.DiscoveryDialog_name_text(), true);
|
super(WindowManager.getDefault().getMainWindow(), Bundle.DiscoveryDialog_name_text(), true);
|
||||||
@ -151,6 +153,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
/**
|
/**
|
||||||
* Update the search settings to a default state.
|
* Update the search settings to a default state.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void updateSearchSettings() {
|
void updateSearchSettings() {
|
||||||
removeAllPanels();
|
removeAllPanels();
|
||||||
imageFilterPanel = null;
|
imageFilterPanel = null;
|
||||||
@ -176,6 +179,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
/**
|
/**
|
||||||
* Set the type buttons to a default state where none are selected.
|
* Set the type buttons to a default state where none are selected.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void unselectAllButtons() {
|
private void unselectAllButtons() {
|
||||||
imagesButton.setSelected(false);
|
imagesButton.setSelected(false);
|
||||||
imagesButton.setEnabled(true);
|
imagesButton.setEnabled(true);
|
||||||
@ -194,6 +198,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
/**
|
/**
|
||||||
* Private helper method to perform update of comboboxes update.
|
* Private helper method to perform update of comboboxes update.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void updateComboBoxes() {
|
private void updateComboBoxes() {
|
||||||
// Set up the grouping attributes
|
// Set up the grouping attributes
|
||||||
List<GroupingAttributeType> groupingAttrs = new ArrayList<>();
|
List<GroupingAttributeType> groupingAttrs = new ArrayList<>();
|
||||||
@ -230,6 +235,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
*
|
*
|
||||||
* @return The panel that corresponds to the currently selected type.
|
* @return The panel that corresponds to the currently selected type.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private AbstractFiltersPanel getSelectedFilterPanel() {
|
private AbstractFiltersPanel getSelectedFilterPanel() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IMAGE:
|
case IMAGE:
|
||||||
@ -251,6 +257,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
*
|
*
|
||||||
* @param type The Type of GroupingAttribute to add.
|
* @param type The Type of GroupingAttribute to add.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void addTypeToGroupByComboBox(GroupingAttributeType type) {
|
private void addTypeToGroupByComboBox(GroupingAttributeType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case FREQUENCY:
|
case FREQUENCY:
|
||||||
@ -282,7 +289,8 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
/**
|
/**
|
||||||
* Validate the filter settings for File type filters.
|
* Validate the filter settings for File type filters.
|
||||||
*/
|
*/
|
||||||
synchronized void validateDialog() {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void validateDialog() {
|
||||||
AbstractFiltersPanel panel = getSelectedFilterPanel();
|
AbstractFiltersPanel panel = getSelectedFilterPanel();
|
||||||
if (panel != null) {
|
if (panel != null) {
|
||||||
panel.validateFields();
|
panel.validateFields();
|
||||||
@ -551,6 +559,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
/**
|
/**
|
||||||
* Helper method to remove all filter panels and their listeners
|
* Helper method to remove all filter panels and their listeners
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void removeAllPanels() {
|
private void removeAllPanels() {
|
||||||
if (imageFilterPanel != null) {
|
if (imageFilterPanel != null) {
|
||||||
remove(imageFilterPanel);
|
remove(imageFilterPanel);
|
||||||
@ -635,6 +644,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
repaint();
|
repaint();
|
||||||
}//GEN-LAST:event_domainsButtonActionPerformed
|
}//GEN-LAST:event_domainsButtonActionPerformed
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
@ -643,6 +653,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
/**
|
/**
|
||||||
* Cancel the searchWorker if it exists.
|
* Cancel the searchWorker if it exists.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void cancelSearch() {
|
void cancelSearch() {
|
||||||
if (searchWorker != null) {
|
if (searchWorker != null) {
|
||||||
searchWorker.cancel(true);
|
searchWorker.cancel(true);
|
||||||
@ -656,6 +667,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
* @param error The error message to display, empty string if there is no
|
* @param error The error message to display, empty string if there is no
|
||||||
* error.
|
* error.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void setValid(String error) {
|
private void setValid(String error) {
|
||||||
if (StringUtils.isBlank(error)) {
|
if (StringUtils.isBlank(error)) {
|
||||||
errorLabel.setText("");
|
errorLabel.setText("");
|
||||||
|
@ -27,6 +27,7 @@ import org.openide.nodes.Children;
|
|||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
|
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
@ -42,28 +43,27 @@ class DiscoveryThumbnailChildren extends Children.Keys<AbstractFile> {
|
|||||||
/*
|
/*
|
||||||
* Creates the list of thumbnails from the given list of AbstractFiles.
|
* Creates the list of thumbnails from the given list of AbstractFiles.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
DiscoveryThumbnailChildren(List<AbstractFile> files) {
|
DiscoveryThumbnailChildren(List<AbstractFile> files) {
|
||||||
super(false);
|
super(false);
|
||||||
|
|
||||||
this.files = files;
|
this.files = files;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
protected Node[] createNodes(AbstractFile t) {
|
protected Node[] createNodes(AbstractFile t) {
|
||||||
return new Node[]{new ThumbnailNode(t)};
|
return new Node[]{new ThumbnailNode(t)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
protected void addNotify() {
|
protected void addNotify() {
|
||||||
super.addNotify();
|
super.addNotify();
|
||||||
|
|
||||||
Set<AbstractFile> thumbnails = new TreeSet<>((AbstractFile file1, AbstractFile file2) -> {
|
Set<AbstractFile> thumbnails = new TreeSet<>((AbstractFile file1, AbstractFile file2) -> {
|
||||||
int result = Long.compare(file1.getSize(), file2.getSize());
|
int result = Long.compare(file1.getSize(), file2.getSize());
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
result = file1.getName().compareTo(file2.getName());
|
result = file1.getName().compareTo(file2.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
thumbnails.addAll(files);
|
thumbnails.addAll(files);
|
||||||
@ -75,10 +75,12 @@ class DiscoveryThumbnailChildren extends Children.Keys<AbstractFile> {
|
|||||||
*/
|
*/
|
||||||
static class ThumbnailNode extends FileNode {
|
static class ThumbnailNode extends FileNode {
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
ThumbnailNode(AbstractFile file) {
|
ThumbnailNode(AbstractFile file) {
|
||||||
super(file, false);
|
super(file, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
protected Sheet createSheet() {
|
protected Sheet createSheet() {
|
||||||
Sheet sheet = super.createSheet();
|
Sheet sheet = super.createSheet();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
<Dimension value="[199, 200]"/>
|
<Dimension value="[199, 200]"/>
|
||||||
|
@ -28,6 +28,7 @@ import java.beans.PropertyChangeListener;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.swing.JSplitPane;
|
import javax.swing.JSplitPane;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.plaf.basic.BasicSplitPaneDivider;
|
import javax.swing.plaf.basic.BasicSplitPaneDivider;
|
||||||
import javax.swing.plaf.basic.BasicSplitPaneUI;
|
import javax.swing.plaf.basic.BasicSplitPaneUI;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
@ -40,6 +41,8 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
|||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData.Type;
|
import org.sleuthkit.autopsy.discovery.search.SearchData.Type;
|
||||||
import static org.sleuthkit.autopsy.discovery.search.SearchData.Type.DOMAIN;
|
import static org.sleuthkit.autopsy.discovery.search.SearchData.Type.DOMAIN;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ArtifactTypeFilter;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a dialog for displaying the Discovery results.
|
* Create a dialog for displaying the Discovery results.
|
||||||
@ -55,8 +58,8 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
private static final int ANIMATION_INCREMENT = 30;
|
private static final int ANIMATION_INCREMENT = 30;
|
||||||
private volatile static int resultsAreaSize = 250;
|
private volatile static int resultsAreaSize = 250;
|
||||||
private final GroupListPanel groupListPanel;
|
private final GroupListPanel groupListPanel;
|
||||||
private final DetailsPanel detailsPanel;
|
|
||||||
private final ResultsPanel resultsPanel;
|
private final ResultsPanel resultsPanel;
|
||||||
|
private String selectedDomainTabName;
|
||||||
private Type searchType;
|
private Type searchType;
|
||||||
private int dividerLocation = -1;
|
private int dividerLocation = -1;
|
||||||
private SwingAnimator animator = null;
|
private SwingAnimator animator = null;
|
||||||
@ -70,10 +73,7 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
setName(Bundle.DiscoveryTopComponent_name());
|
setName(Bundle.DiscoveryTopComponent_name());
|
||||||
groupListPanel = new GroupListPanel();
|
groupListPanel = new GroupListPanel();
|
||||||
resultsPanel = new ResultsPanel();
|
resultsPanel = new ResultsPanel();
|
||||||
detailsPanel = new DetailsPanel();
|
|
||||||
mainSplitPane.setLeftComponent(groupListPanel);
|
mainSplitPane.setLeftComponent(groupListPanel);
|
||||||
rightSplitPane.setTopComponent(resultsPanel);
|
|
||||||
rightSplitPane.setBottomComponent(detailsPanel);
|
|
||||||
//set color of divider
|
//set color of divider
|
||||||
rightSplitPane.setUI(new BasicSplitPaneUI() {
|
rightSplitPane.setUI(new BasicSplitPaneUI() {
|
||||||
@Override
|
@Override
|
||||||
@ -95,6 +95,7 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
rightSplitPane.setTopComponent(resultsPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,6 +109,7 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
* @param ui The component which contains the split pane this divider is
|
* @param ui The component which contains the split pane this divider is
|
||||||
* in.
|
* in.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
BasicSplitPaneDividerImpl(BasicSplitPaneUI ui) {
|
BasicSplitPaneDividerImpl(BasicSplitPaneUI ui) {
|
||||||
super(ui);
|
super(ui);
|
||||||
this.setLayout(new BorderLayout());
|
this.setLayout(new BorderLayout());
|
||||||
@ -129,11 +131,13 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
/**
|
/**
|
||||||
* Reset the top component so it isn't displaying any results.
|
* Reset the top component so it isn't displaying any results.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
public void resetTopComponent() {
|
public void resetTopComponent() {
|
||||||
resultsPanel.resetResultViewer();
|
resultsPanel.resetResultViewer();
|
||||||
groupListPanel.resetGroupList();
|
groupListPanel.resetGroupList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public void componentOpened() {
|
public void componentOpened() {
|
||||||
super.componentOpened();
|
super.componentOpened();
|
||||||
@ -141,9 +145,9 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
DiscoveryEventUtils.getDiscoveryEventBus().register(this);
|
DiscoveryEventUtils.getDiscoveryEventBus().register(this);
|
||||||
DiscoveryEventUtils.getDiscoveryEventBus().register(resultsPanel);
|
DiscoveryEventUtils.getDiscoveryEventBus().register(resultsPanel);
|
||||||
DiscoveryEventUtils.getDiscoveryEventBus().register(groupListPanel);
|
DiscoveryEventUtils.getDiscoveryEventBus().register(groupListPanel);
|
||||||
DiscoveryEventUtils.getDiscoveryEventBus().register(detailsPanel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
protected void componentClosed() {
|
protected void componentClosed() {
|
||||||
DiscoveryDialog.getDiscoveryDialogInstance().cancelSearch();
|
DiscoveryDialog.getDiscoveryDialogInstance().cancelSearch();
|
||||||
@ -152,7 +156,10 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
DiscoveryEventUtils.getDiscoveryEventBus().unregister(this);
|
DiscoveryEventUtils.getDiscoveryEventBus().unregister(this);
|
||||||
DiscoveryEventUtils.getDiscoveryEventBus().unregister(groupListPanel);
|
DiscoveryEventUtils.getDiscoveryEventBus().unregister(groupListPanel);
|
||||||
DiscoveryEventUtils.getDiscoveryEventBus().unregister(resultsPanel);
|
DiscoveryEventUtils.getDiscoveryEventBus().unregister(resultsPanel);
|
||||||
DiscoveryEventUtils.getDiscoveryEventBus().unregister(detailsPanel);
|
DiscoveryEventUtils.getDiscoveryEventBus().unregister(rightSplitPane.getBottomComponent());
|
||||||
|
if (rightSplitPane.getBottomComponent() instanceof DomainDetailsPanel) {
|
||||||
|
selectedDomainTabName = ((DomainDetailsPanel) rightSplitPane.getBottomComponent()).getSelectedTabName();
|
||||||
|
}
|
||||||
super.componentClosed();
|
super.componentClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +269,7 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
*/
|
*/
|
||||||
@Subscribe
|
@Subscribe
|
||||||
void handleDetailsVisibleEvent(DiscoveryEventUtils.DetailsVisibleEvent detailsVisibleEvent) {
|
void handleDetailsVisibleEvent(DiscoveryEventUtils.DetailsVisibleEvent detailsVisibleEvent) {
|
||||||
if (resultsPanel.getActiveType() != DOMAIN) {
|
SwingUtilities.invokeLater(() -> {
|
||||||
if (animator != null && animator.isRunning()) {
|
if (animator != null && animator.isRunning()) {
|
||||||
animator.stop();
|
animator.stop();
|
||||||
animator = null;
|
animator = null;
|
||||||
@ -274,7 +281,7 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
animator = new SwingAnimator(new HideDetailsAreaCallback());
|
animator = new SwingAnimator(new HideDetailsAreaCallback());
|
||||||
}
|
}
|
||||||
animator.start();
|
animator.start();
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -289,12 +296,12 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
"DiscoveryTopComponent.searchError.text=Error no type specified for search."})
|
"DiscoveryTopComponent.searchError.text=Error no type specified for search."})
|
||||||
@Subscribe
|
@Subscribe
|
||||||
void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) {
|
void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
newSearchButton.setText(Bundle.DiscoveryTopComponent_cancelButton_text());
|
newSearchButton.setText(Bundle.DiscoveryTopComponent_cancelButton_text());
|
||||||
progressMessageTextArea.setForeground(Color.red);
|
progressMessageTextArea.setForeground(Color.red);
|
||||||
searchType = searchStartedEvent.getType();
|
searchType = searchStartedEvent.getType();
|
||||||
progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchInProgress_text(searchType.name()));
|
progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchInProgress_text(searchType.name()));
|
||||||
rightSplitPane.getComponent(1).setVisible(searchStartedEvent.getType() != DOMAIN);
|
});
|
||||||
rightSplitPane.getComponent(2).setVisible(searchStartedEvent.getType() != DOMAIN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -310,6 +317,7 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
"DiscoveryTopComponent.domainSearch.text=Type: Domain",
|
"DiscoveryTopComponent.domainSearch.text=Type: Domain",
|
||||||
"DiscoveryTopComponent.additionalFilters.text=; "})
|
"DiscoveryTopComponent.additionalFilters.text=; "})
|
||||||
void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) {
|
void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text());
|
newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text());
|
||||||
progressMessageTextArea.setForeground(Color.black);
|
progressMessageTextArea.setForeground(Color.black);
|
||||||
String descriptionText = "";
|
String descriptionText = "";
|
||||||
@ -319,10 +327,41 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
if (!searchCompleteEvent.getFilters().isEmpty()) {
|
if (!searchCompleteEvent.getFilters().isEmpty()) {
|
||||||
descriptionText += Bundle.DiscoveryTopComponent_additionalFilters_text();
|
descriptionText += Bundle.DiscoveryTopComponent_additionalFilters_text();
|
||||||
}
|
}
|
||||||
|
selectedDomainTabName = validateLastSelectedType(searchCompleteEvent);
|
||||||
|
rightSplitPane.setBottomComponent(new DomainDetailsPanel(selectedDomainTabName));
|
||||||
|
} else {
|
||||||
|
rightSplitPane.setBottomComponent(new FileDetailsPanel());
|
||||||
}
|
}
|
||||||
|
DiscoveryEventUtils.getDiscoveryEventBus().register(rightSplitPane.getBottomComponent());
|
||||||
descriptionText += searchCompleteEvent.getFilters().stream().map(AbstractFilter::getDesc).collect(Collectors.joining("; "));
|
descriptionText += searchCompleteEvent.getFilters().stream().map(AbstractFilter::getDesc).collect(Collectors.joining("; "));
|
||||||
progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchComplete_text(descriptionText));
|
progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchComplete_text(descriptionText));
|
||||||
progressMessageTextArea.setCaretPosition(0);
|
progressMessageTextArea.setCaretPosition(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the tab which was last selected unless the tab last
|
||||||
|
* selected would not be included in the types currently being displayed or
|
||||||
|
* was not previously set.
|
||||||
|
*
|
||||||
|
* @return The name of the tab which should be selected in the new
|
||||||
|
* DomainDetailsPanel.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
private String validateLastSelectedType(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) {
|
||||||
|
String typeFilteredOn = selectedDomainTabName;
|
||||||
|
for (AbstractFilter filter : searchCompleteEvent.getFilters()) {
|
||||||
|
if (filter instanceof ArtifactTypeFilter) {
|
||||||
|
for (ARTIFACT_TYPE type : ((ArtifactTypeFilter) filter).getTypes()) {
|
||||||
|
typeFilteredOn = type.getDisplayName();
|
||||||
|
if (selectedDomainTabName == null || typeFilteredOn.equalsIgnoreCase(selectedDomainTabName)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return typeFilteredOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -334,9 +373,11 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
@Messages({"DiscoveryTopComponent.searchCancelled.text=Search has been cancelled."})
|
@Messages({"DiscoveryTopComponent.searchCancelled.text=Search has been cancelled."})
|
||||||
@Subscribe
|
@Subscribe
|
||||||
void handleSearchCancelledEvent(DiscoveryEventUtils.SearchCancelledEvent searchCancelledEvent) {
|
void handleSearchCancelledEvent(DiscoveryEventUtils.SearchCancelledEvent searchCancelledEvent) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text());
|
newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text());
|
||||||
progressMessageTextArea.setForeground(Color.red);
|
progressMessageTextArea.setForeground(Color.red);
|
||||||
progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchCancelled_text());
|
progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchCancelled_text());
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,12 +386,14 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
*/
|
*/
|
||||||
private final class ShowDetailsAreaCallback implements SwingAnimatorCallback {
|
private final class ShowDetailsAreaCallback implements SwingAnimatorCallback {
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public void callback(Object caller) {
|
public void callback(Object caller) {
|
||||||
dividerLocation -= ANIMATION_INCREMENT;
|
dividerLocation -= ANIMATION_INCREMENT;
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTerminated() {
|
public boolean hasTerminated() {
|
||||||
if (dividerLocation != JSplitPane.UNDEFINED_CONDITION && dividerLocation < resultsAreaSize) {
|
if (dividerLocation != JSplitPane.UNDEFINED_CONDITION && dividerLocation < resultsAreaSize) {
|
||||||
@ -368,12 +411,14 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
*/
|
*/
|
||||||
private final class HideDetailsAreaCallback implements SwingAnimatorCallback {
|
private final class HideDetailsAreaCallback implements SwingAnimatorCallback {
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public void callback(Object caller) {
|
public void callback(Object caller) {
|
||||||
dividerLocation += ANIMATION_INCREMENT;
|
dividerLocation += ANIMATION_INCREMENT;
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTerminated() {
|
public boolean hasTerminated() {
|
||||||
if (dividerLocation > rightSplitPane.getHeight() || dividerLocation == JSplitPane.UNDEFINED_CONDITION) {
|
if (dividerLocation > rightSplitPane.getHeight() || dividerLocation == JSplitPane.UNDEFINED_CONDITION) {
|
||||||
@ -399,6 +444,7 @@ public final class DiscoveryTopComponent extends TopComponent {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public void paintComponent(Graphics g) {
|
public void paintComponent(Graphics g) {
|
||||||
if (animator != null && animator.isRunning() && (dividerLocation == JSplitPane.UNDEFINED_CONDITION
|
if (animator != null && animator.isRunning() && (dividerLocation == JSplitPane.UNDEFINED_CONDITION
|
||||||
|
@ -51,6 +51,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
|||||||
import org.sleuthkit.autopsy.corelibs.ScalrWrapper;
|
import org.sleuthkit.autopsy.corelibs.ScalrWrapper;
|
||||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import static org.sleuthkit.autopsy.coreutils.VideoUtils.getVideoFileInTempDir;
|
import static org.sleuthkit.autopsy.coreutils.VideoUtils.getVideoFileInTempDir;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
import org.sleuthkit.autopsy.discovery.search.ResultFile;
|
import org.sleuthkit.autopsy.discovery.search.ResultFile;
|
||||||
@ -173,6 +174,7 @@ final class DiscoveryUiUtils {
|
|||||||
*
|
*
|
||||||
* @return True if the point is over the icon, false otherwise.
|
* @return True if the point is over the icon, false otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
static boolean isPointOnIcon(Component comp, Point point) {
|
static boolean isPointOnIcon(Component comp, Point point) {
|
||||||
return comp instanceof JComponent && point.x >= comp.getX() && point.x <= comp.getX() + ICON_SIZE && point.y >= comp.getY() && point.y <= comp.getY() + ICON_SIZE;
|
return comp instanceof JComponent && point.x >= comp.getX() && point.x <= comp.getX() + ICON_SIZE && point.y >= comp.getY() && point.y <= comp.getY() + ICON_SIZE;
|
||||||
}
|
}
|
||||||
@ -186,6 +188,7 @@ final class DiscoveryUiUtils {
|
|||||||
* @param isDeletedLabel The label to set the icon and tooltip for.
|
* @param isDeletedLabel The label to set the icon and tooltip for.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({"DiscoveryUiUtils.isDeleted.text=All instances of file are deleted."})
|
@NbBundle.Messages({"DiscoveryUiUtils.isDeleted.text=All instances of file are deleted."})
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
static void setDeletedIcon(boolean isDeleted, javax.swing.JLabel isDeletedLabel) {
|
static void setDeletedIcon(boolean isDeleted, javax.swing.JLabel isDeletedLabel) {
|
||||||
if (isDeleted) {
|
if (isDeleted) {
|
||||||
isDeletedLabel.setIcon(DELETED_ICON);
|
isDeletedLabel.setIcon(DELETED_ICON);
|
||||||
@ -203,6 +206,7 @@ final class DiscoveryUiUtils {
|
|||||||
* score of.
|
* score of.
|
||||||
* @param scoreLabel The label to set the icon and tooltip for.
|
* @param scoreLabel The label to set the icon and tooltip for.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
static void setScoreIcon(ResultFile resultFile, javax.swing.JLabel scoreLabel) {
|
static void setScoreIcon(ResultFile resultFile, javax.swing.JLabel scoreLabel) {
|
||||||
switch (resultFile.getScore()) {
|
switch (resultFile.getScore()) {
|
||||||
case NOTABLE_SCORE:
|
case NOTABLE_SCORE:
|
||||||
@ -232,6 +236,7 @@ final class DiscoveryUiUtils {
|
|||||||
* Helper method to display an error message when the results of the
|
* Helper method to display an error message when the results of the
|
||||||
* Discovery Top component may be incomplete.
|
* Discovery Top component may be incomplete.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({"DiscoveryUiUtils.resultsIncomplete.text=Discovery results may be incomplete"})
|
@NbBundle.Messages({"DiscoveryUiUtils.resultsIncomplete.text=Discovery results may be incomplete"})
|
||||||
static void displayErrorMessage(DiscoveryDialog dialog) {
|
static void displayErrorMessage(DiscoveryDialog dialog) {
|
||||||
//check if modules run and assemble message
|
//check if modules run and assemble message
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.discovery.ui;
|
package org.sleuthkit.autopsy.discovery.ui;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,6 +33,7 @@ final class DocumentFilterPanel extends AbstractFiltersPanel {
|
|||||||
/**
|
/**
|
||||||
* Constructs a new DocumentFilterPanel.
|
* Constructs a new DocumentFilterPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
DocumentFilterPanel() {
|
DocumentFilterPanel() {
|
||||||
super();
|
super();
|
||||||
initComponents();
|
initComponents();
|
||||||
|
@ -79,9 +79,6 @@
|
|||||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/file-icon-deleted.png"/>
|
<Image iconType="3" name="/org/sleuthkit/autopsy/images/file-icon-deleted.png"/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="DocumentPanel.isDeletedLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
@ -91,6 +88,9 @@
|
|||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="DocumentPanel.isDeletedLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JLabel" name="scoreLabel">
|
<Component class="javax.swing.JLabel" name="scoreLabel">
|
||||||
@ -98,7 +98,6 @@
|
|||||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/red-circle-exclamation.png"/>
|
<Image iconType="3" name="/org/sleuthkit/autopsy/images/red-circle-exclamation.png"/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
|
||||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
@ -108,6 +107,7 @@
|
|||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JLabel" name="fileSizeLabel">
|
<Component class="javax.swing.JLabel" name="fileSizeLabel">
|
||||||
|
@ -29,6 +29,7 @@ import javax.swing.JList;
|
|||||||
import javax.swing.ListCellRenderer;
|
import javax.swing.ListCellRenderer;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.corecomponents.AutoWrappingJTextPane;
|
import org.sleuthkit.autopsy.corecomponents.AutoWrappingJTextPane;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,6 +44,7 @@ class DocumentPanel extends javax.swing.JPanel implements ListCellRenderer<Docum
|
|||||||
/**
|
/**
|
||||||
* Creates new form DocumentPanel.
|
* Creates new form DocumentPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
DocumentPanel() {
|
DocumentPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
}
|
}
|
||||||
@ -150,7 +152,7 @@ class DocumentPanel extends javax.swing.JPanel implements ListCellRenderer<Docum
|
|||||||
"DocumentPanel.numberOfImages.text=1 of {0} images",
|
"DocumentPanel.numberOfImages.text=1 of {0} images",
|
||||||
"DocumentPanel.numberOfImages.noImages=No images",
|
"DocumentPanel.numberOfImages.noImages=No images",
|
||||||
"DocumentPanel.noImageExtraction.text=0 of ? images"})
|
"DocumentPanel.noImageExtraction.text=0 of ? images"})
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public Component getListCellRendererComponent(JList<? extends DocumentWrapper> list, DocumentWrapper value, int index, boolean isSelected, boolean cellHasFocus) {
|
public Component getListCellRendererComponent(JList<? extends DocumentWrapper> list, DocumentWrapper value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||||
fileSizeLabel.setText(DiscoveryUiUtils.getFileSizeString(value.getResultFile().getFirstInstance().getSize()));
|
fileSizeLabel.setText(DiscoveryUiUtils.getFileSizeString(value.getResultFile().getFirstInstance().getSize()));
|
||||||
@ -180,6 +182,7 @@ class DocumentPanel extends javax.swing.JPanel implements ListCellRenderer<Docum
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public String getToolTipText(MouseEvent event) {
|
public String getToolTipText(MouseEvent event) {
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.DefaultListModel;
|
import javax.swing.DefaultListModel;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,6 +36,7 @@ final class DocumentPreviewViewer extends javax.swing.JPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form DocumentViewer.
|
* Creates new form DocumentViewer.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
DocumentPreviewViewer() {
|
DocumentPreviewViewer() {
|
||||||
initComponents();
|
initComponents();
|
||||||
}
|
}
|
||||||
@ -75,12 +77,11 @@ final class DocumentPreviewViewer extends javax.swing.JPanel {
|
|||||||
/**
|
/**
|
||||||
* Clear the list of documents being displayed.
|
* Clear the list of documents being displayed.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void clearViewer() {
|
void clearViewer() {
|
||||||
synchronized (this) {
|
|
||||||
documentListModel.removeAllElements();
|
documentListModel.removeAllElements();
|
||||||
documentScrollPane.getVerticalScrollBar().setValue(0);
|
documentScrollPane.getVerticalScrollBar().setValue(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a selection listener to the list of document previews being
|
* Add a selection listener to the list of document previews being
|
||||||
@ -88,6 +89,7 @@ final class DocumentPreviewViewer extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @param listener The ListSelectionListener to add to the selection model.
|
* @param listener The ListSelectionListener to add to the selection model.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void addListSelectionListener(ListSelectionListener listener) {
|
void addListSelectionListener(ListSelectionListener listener) {
|
||||||
documentList.getSelectionModel().addListSelectionListener(listener);
|
documentList.getSelectionModel().addListSelectionListener(listener);
|
||||||
}
|
}
|
||||||
@ -99,15 +101,14 @@ final class DocumentPreviewViewer extends javax.swing.JPanel {
|
|||||||
* @return The list of AbstractFiles which are represented by the selected
|
* @return The list of AbstractFiles which are represented by the selected
|
||||||
* document preview.
|
* document preview.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
List<AbstractFile> getInstancesForSelected() {
|
List<AbstractFile> getInstancesForSelected() {
|
||||||
synchronized (this) {
|
|
||||||
if (documentList.getSelectedIndex() == -1) {
|
if (documentList.getSelectedIndex() == -1) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
} else {
|
} else {
|
||||||
return documentListModel.getElementAt(documentList.getSelectedIndex()).getResultFile().getAllInstances();
|
return documentListModel.getElementAt(documentList.getSelectedIndex()).getResultFile().getAllInstances();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JList<DocumentWrapper> documentList;
|
private javax.swing.JList<DocumentWrapper> documentList;
|
||||||
@ -120,9 +121,8 @@ final class DocumentPreviewViewer extends javax.swing.JPanel {
|
|||||||
* @param documentWrapper The object which contains the document preview
|
* @param documentWrapper The object which contains the document preview
|
||||||
* which will be displayed.
|
* which will be displayed.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void addDocument(DocumentWrapper documentWrapper) {
|
void addDocument(DocumentWrapper documentWrapper) {
|
||||||
synchronized (this) {
|
|
||||||
documentListModel.addElement(documentWrapper);
|
documentListModel.addElement(documentWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||||
|
<BorderConstraints direction="Center"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.discovery.ui;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import org.sleuthkit.autopsy.contentviewers.artifactviewers.DefaultArtifactContentViewer;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JPanel which should be used as a tab in the domain artifacts details area.
|
||||||
|
*/
|
||||||
|
final class DomainArtifactsTabPanel extends JPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final static Logger logger = Logger.getLogger(DomainArtifactsTabPanel.class.getName());
|
||||||
|
private final ArtifactsListPanel listPanel;
|
||||||
|
private final BlackboardArtifact.ARTIFACT_TYPE artifactType;
|
||||||
|
private AbstractArtifactDetailsPanel rightPanel = null;
|
||||||
|
|
||||||
|
private volatile ArtifactRetrievalStatus status = ArtifactRetrievalStatus.UNPOPULATED;
|
||||||
|
private final ListSelectionListener listener = new ListSelectionListener() {
|
||||||
|
@Override
|
||||||
|
public void valueChanged(ListSelectionEvent event) {
|
||||||
|
if (!event.getValueIsAdjusting()) {
|
||||||
|
rightPanel.setArtifact(listPanel.getSelectedArtifact());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form CookiesPanel
|
||||||
|
*
|
||||||
|
* @param type The type of Artifact this tab is displaying information for.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
DomainArtifactsTabPanel(BlackboardArtifact.ARTIFACT_TYPE type) {
|
||||||
|
initComponents();
|
||||||
|
this.artifactType = type;
|
||||||
|
listPanel = new ArtifactsListPanel(artifactType);
|
||||||
|
jSplitPane1.setLeftComponent(listPanel);
|
||||||
|
setRightComponent();
|
||||||
|
listPanel.addSelectionListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the right component of the tab panel, which will display the details
|
||||||
|
* for the artifact.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
private void setRightComponent() {
|
||||||
|
switch (artifactType) {
|
||||||
|
case TSK_WEB_HISTORY:
|
||||||
|
rightPanel = new WebHistoryDetailsPanel();
|
||||||
|
break;
|
||||||
|
case TSK_WEB_COOKIE:
|
||||||
|
case TSK_WEB_SEARCH_QUERY:
|
||||||
|
case TSK_WEB_BOOKMARK:
|
||||||
|
rightPanel = new DefaultArtifactContentViewer();
|
||||||
|
break;
|
||||||
|
case TSK_WEB_DOWNLOAD:
|
||||||
|
case TSK_WEB_CACHE:
|
||||||
|
rightPanel = new ContentViewerDetailsPanel();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rightPanel = new DefaultArtifactContentViewer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (rightPanel != null) {
|
||||||
|
jSplitPane1.setRightComponent(new JScrollPane(rightPanel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the status of the panel which indicates if it is populated.
|
||||||
|
*
|
||||||
|
* @return The ArtifactRetrievalStatuss of the panel.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
ArtifactRetrievalStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manually set the status of the panel.
|
||||||
|
*
|
||||||
|
* @param status The ArtifactRetrievalStatus of the panel.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void setStatus(ArtifactRetrievalStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
if (status == ArtifactRetrievalStatus.UNPOPULATED && rightPanel != null) {
|
||||||
|
rightPanel.setArtifact(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event which indicates the artifacts have been retrieved.
|
||||||
|
*
|
||||||
|
* @param artifactresultEvent The event which indicates the artifacts have
|
||||||
|
* been retrieved.
|
||||||
|
*/
|
||||||
|
@Subscribe
|
||||||
|
void handleArtifactSearchResultEvent(DiscoveryEventUtils.ArtifactSearchResultEvent artifactresultEvent) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
if (artifactType == artifactresultEvent.getArtifactType()) {
|
||||||
|
listPanel.removeListSelectionListener(listener);
|
||||||
|
listPanel.addArtifacts(artifactresultEvent.getListOfArtifacts());
|
||||||
|
listPanel.addSelectionListener(listener);
|
||||||
|
listPanel.selectFirst();
|
||||||
|
try {
|
||||||
|
DiscoveryEventUtils.getDiscoveryEventBus().unregister(this);
|
||||||
|
} catch (IllegalArgumentException notRegistered) {
|
||||||
|
logger.log(Level.INFO, "Attempting to unregister tab which was not registered");
|
||||||
|
// attempting to remove a tab that was never registered
|
||||||
|
}
|
||||||
|
status = ArtifactRetrievalStatus.POPULATED;
|
||||||
|
setEnabled(!listPanel.isEmpty());
|
||||||
|
validate();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of Artifact the panel exists for.
|
||||||
|
*
|
||||||
|
* @return The ARTIFACT_TYPE of the BlackboardArtifact being displayed.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
BlackboardArtifact.ARTIFACT_TYPE getArtifactType() {
|
||||||
|
return artifactType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
jSplitPane1 = new javax.swing.JSplitPane();
|
||||||
|
|
||||||
|
setLayout(new java.awt.BorderLayout());
|
||||||
|
add(jSplitPane1, java.awt.BorderLayout.CENTER);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JSplitPane jSplitPane1;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum to keep track of the populated state of this panel.
|
||||||
|
*/
|
||||||
|
enum ArtifactRetrievalStatus {
|
||||||
|
UNPOPULATED(),
|
||||||
|
POPULATING(),
|
||||||
|
POPULATED();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<Properties>
|
||||||
|
<Property name="enabled" type="boolean" value="false"/>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JTabbedPane" name="jTabbedPane1">
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||||
|
<BorderConstraints direction="Center"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.discovery.ui;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import java.awt.Component;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panel to display details area for domain discovery results.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
final class DomainDetailsPanel extends JPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private ArtifactsWorker detailsWorker;
|
||||||
|
private String domain;
|
||||||
|
private String selectedTabName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form ArtifactDetailsPanel.
|
||||||
|
*
|
||||||
|
* @param selectedTabName The name of the tab to select initially.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
DomainDetailsPanel(String selectedTabName) {
|
||||||
|
initComponents();
|
||||||
|
addArtifactTabs(selectedTabName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the tabs for each of the artifact types which we will be displaying.
|
||||||
|
*
|
||||||
|
* @param tabName The name of the tab to select initially.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
private void addArtifactTabs(String tabName) {
|
||||||
|
for (BlackboardArtifact.ARTIFACT_TYPE type : SearchData.Type.DOMAIN.getArtifactTypes()) {
|
||||||
|
jTabbedPane1.add(type.getDisplayName(), new DomainArtifactsTabPanel(type));
|
||||||
|
}
|
||||||
|
selectedTabName = tabName;
|
||||||
|
selectTab();
|
||||||
|
jTabbedPane1.addChangeListener(new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
if (jTabbedPane1.getSelectedIndex() >= 0) {
|
||||||
|
String newTabTitle = jTabbedPane1.getTitleAt(jTabbedPane1.getSelectedIndex());
|
||||||
|
if (selectedTabName == null || !selectedTabName.equals(newTabTitle)) {
|
||||||
|
selectedTabName = newTabTitle;
|
||||||
|
runDomainWorker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
/**
|
||||||
|
* Set the selected tab index to be the previously selected tab if a
|
||||||
|
* previously selected tab exists.
|
||||||
|
*/
|
||||||
|
private void selectTab() {
|
||||||
|
for (int i = 0; i < jTabbedPane1.getTabCount(); i++) {
|
||||||
|
if (!StringUtils.isBlank(selectedTabName) && selectedTabName.equals(jTabbedPane1.getTitleAt(i))) {
|
||||||
|
jTabbedPane1.setSelectedIndex(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the worker which retrieves the list of artifacts for the domain to
|
||||||
|
* populate the details area.
|
||||||
|
*/
|
||||||
|
private void runDomainWorker() {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
Component selectedComponent = jTabbedPane1.getSelectedComponent();
|
||||||
|
if (selectedComponent instanceof DomainArtifactsTabPanel) {
|
||||||
|
if (detailsWorker != null && !detailsWorker.isDone()) {
|
||||||
|
detailsWorker.cancel(true);
|
||||||
|
}
|
||||||
|
DomainArtifactsTabPanel selectedTab = (DomainArtifactsTabPanel) selectedComponent;
|
||||||
|
if (selectedTab.getStatus() == DomainArtifactsTabPanel.ArtifactRetrievalStatus.UNPOPULATED) {
|
||||||
|
selectedTab.setStatus(DomainArtifactsTabPanel.ArtifactRetrievalStatus.POPULATING);
|
||||||
|
DiscoveryEventUtils.getDiscoveryEventBus().register(selectedTab);
|
||||||
|
detailsWorker = new ArtifactsWorker(selectedTab.getArtifactType(), domain);
|
||||||
|
detailsWorker.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the the details tabs.
|
||||||
|
*
|
||||||
|
* @param populateEvent The PopulateDomainTabsEvent which indicates which
|
||||||
|
* domain the details tabs should be populated for.
|
||||||
|
*/
|
||||||
|
@Subscribe
|
||||||
|
void handlePopulateDomainTabsEvent(DiscoveryEventUtils.PopulateDomainTabsEvent populateEvent) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
domain = populateEvent.getDomain();
|
||||||
|
resetTabsStatus();
|
||||||
|
selectTab();
|
||||||
|
runDomainWorker();
|
||||||
|
if (StringUtils.isBlank(domain)) {
|
||||||
|
//send fade out event
|
||||||
|
DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.DetailsVisibleEvent(false));
|
||||||
|
} else {
|
||||||
|
//send fade in event
|
||||||
|
DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.DetailsVisibleEvent(true));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private helper method to ensure tabs will re-populate after a new domain
|
||||||
|
* is selected.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
private void resetTabsStatus() {
|
||||||
|
for (Component comp : jTabbedPane1.getComponents()) {
|
||||||
|
if (comp instanceof DomainArtifactsTabPanel) {
|
||||||
|
((DomainArtifactsTabPanel) comp).setStatus(DomainArtifactsTabPanel.ArtifactRetrievalStatus.UNPOPULATED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the tab that was most recently selected.
|
||||||
|
*
|
||||||
|
* @return The name of the tab that was most recently selected.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
String getSelectedTabName() {
|
||||||
|
return selectedTabName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
jTabbedPane1 = new javax.swing.JTabbedPane();
|
||||||
|
|
||||||
|
setEnabled(false);
|
||||||
|
setLayout(new java.awt.BorderLayout());
|
||||||
|
add(jTabbedPane1, java.awt.BorderLayout.CENTER);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JTabbedPane jTabbedPane1;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.discovery.ui;
|
package org.sleuthkit.autopsy.discovery.ui;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||||
import org.sleuthkit.autopsy.discovery.search.ResultsSorter;
|
import org.sleuthkit.autopsy.discovery.search.ResultsSorter;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||||
@ -34,6 +35,7 @@ public class DomainFilterPanel extends AbstractFiltersPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form DomainFilterPanel.
|
* Creates new form DomainFilterPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
public DomainFilterPanel() {
|
public DomainFilterPanel() {
|
||||||
super();
|
super();
|
||||||
initComponents();
|
initComponents();
|
||||||
|
@ -30,6 +30,7 @@ import javax.swing.JComponent;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.ListCellRenderer;
|
import javax.swing.ListCellRenderer;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which displays a preview and details about a domain.
|
* Class which displays a preview and details about a domain.
|
||||||
@ -43,6 +44,7 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer<
|
|||||||
/**
|
/**
|
||||||
* Creates new form DomainPanel.
|
* Creates new form DomainPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
DomainSummaryPanel() {
|
DomainSummaryPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
domainNameLabel.setFont(domainNameLabel.getFont().deriveFont(domainNameLabel.getFont().getStyle(), domainNameLabel.getFont().getSize() + 6));
|
domainNameLabel.setFont(domainNameLabel.getFont().deriveFont(domainNameLabel.getFont().getStyle(), domainNameLabel.getFont().getSize() + 6));
|
||||||
@ -136,6 +138,7 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer<
|
|||||||
private javax.swing.JLabel totalVisitsLabel;
|
private javax.swing.JLabel totalVisitsLabel;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({"# {0} - startDate",
|
@NbBundle.Messages({"# {0} - startDate",
|
||||||
"# {1} - endDate",
|
"# {1} - endDate",
|
||||||
"DomainSummaryPanel.activity.text=Activity: {0} to {1}",
|
"DomainSummaryPanel.activity.text=Activity: {0} to {1}",
|
||||||
@ -163,6 +166,7 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer<
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public String getToolTipText(MouseEvent event) {
|
public String getToolTipText(MouseEvent event) {
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
|
@ -39,8 +39,6 @@
|
|||||||
</Properties>
|
</Properties>
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<DomainWrapper>"/>
|
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<DomainWrapper>"/>
|
||||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
|
||||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
</Component>
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
package org.sleuthkit.autopsy.discovery.ui;
|
package org.sleuthkit.autopsy.discovery.ui;
|
||||||
|
|
||||||
import javax.swing.DefaultListModel;
|
import javax.swing.DefaultListModel;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JPanel to display domain summaries.
|
* A JPanel to display domain summaries.
|
||||||
@ -30,20 +33,20 @@ public class DomainSummaryViewer extends javax.swing.JPanel {
|
|||||||
private final DefaultListModel<DomainWrapper> domainListModel = new DefaultListModel<>();
|
private final DefaultListModel<DomainWrapper> domainListModel = new DefaultListModel<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the list of documents being displayed.
|
* Creates new form DomainSummaryPanel
|
||||||
*/
|
*/
|
||||||
void clearViewer() {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
synchronized (this) {
|
public DomainSummaryViewer() {
|
||||||
domainListModel.removeAllElements();
|
initComponents();
|
||||||
domainScrollPane.getVerticalScrollBar().setValue(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form DomainSummaryPanel
|
* Clear the list of documents being displayed.
|
||||||
*/
|
*/
|
||||||
public DomainSummaryViewer() {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
initComponents();
|
void clearViewer() {
|
||||||
|
domainListModel.removeAllElements();
|
||||||
|
domainScrollPane.getVerticalScrollBar().setValue(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +59,7 @@ public class DomainSummaryViewer extends javax.swing.JPanel {
|
|||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
|
|
||||||
domainScrollPane = new javax.swing.JScrollPane();
|
domainScrollPane = new javax.swing.JScrollPane();
|
||||||
javax.swing.JList<DomainWrapper> domainList = new javax.swing.JList<>();
|
domainList = new javax.swing.JList<>();
|
||||||
|
|
||||||
setLayout(new java.awt.BorderLayout());
|
setLayout(new java.awt.BorderLayout());
|
||||||
|
|
||||||
@ -69,6 +72,7 @@ public class DomainSummaryViewer extends javax.swing.JPanel {
|
|||||||
|
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JList<DomainWrapper> domainList;
|
||||||
private javax.swing.JScrollPane domainScrollPane;
|
private javax.swing.JScrollPane domainScrollPane;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
@ -78,9 +82,39 @@ public class DomainSummaryViewer extends javax.swing.JPanel {
|
|||||||
* @param domainWrapper The object which contains the domain summary which
|
* @param domainWrapper The object which contains the domain summary which
|
||||||
* will be displayed.
|
* will be displayed.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void addDomain(DomainWrapper domainWrapper) {
|
void addDomain(DomainWrapper domainWrapper) {
|
||||||
synchronized (this) {
|
|
||||||
domainListModel.addElement(domainWrapper);
|
domainListModel.addElement(domainWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an event to perform the population of the domain details tabs to
|
||||||
|
* reflect the currently selected domain. Will populate the list with
|
||||||
|
* nothing when a domain is not used.
|
||||||
|
*
|
||||||
|
* @param useDomain If the currently selected domain should be used to
|
||||||
|
* retrieve a list.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void sendPopulateEvent(boolean useDomain) {
|
||||||
|
String domain = "";
|
||||||
|
if (useDomain) {
|
||||||
|
if (domainList.getSelectedIndex() != -1) {
|
||||||
|
domain = domainListModel.getElementAt(domainList.getSelectedIndex()).getResultDomain().getDomain();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//send populateMesage
|
||||||
|
DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.PopulateDomainTabsEvent(domain));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a selection listener to the list of document previews being
|
||||||
|
* displayed.
|
||||||
|
*
|
||||||
|
* @param listener The ListSelectionListener to add to the selection model.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void addListSelectionListener(ListSelectionListener listener) {
|
||||||
|
domainList.getSelectionModel().addListSelectionListener(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,8 +105,8 @@
|
|||||||
<Properties>
|
<Properties>
|
||||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||||
<TitledBorder title="Instances">
|
<TitledBorder title="<FileDetailsPanel.instancesList.border.title>">
|
||||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="DetailsPanel.instancesList.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="FileDetailsPanel.instancesList.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
</TitledBorder>
|
</TitledBorder>
|
||||||
</Border>
|
</Border>
|
||||||
</Property>
|
</Property>
|
@ -36,6 +36,7 @@ import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
|||||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||||
import org.sleuthkit.autopsy.corecomponents.DataContentPanel;
|
import org.sleuthkit.autopsy.corecomponents.DataContentPanel;
|
||||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||||
@ -48,7 +49,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
/**
|
/**
|
||||||
* Panel to display the details of the selected result.
|
* Panel to display the details of the selected result.
|
||||||
*/
|
*/
|
||||||
final class DetailsPanel extends javax.swing.JPanel {
|
final class FileDetailsPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -59,7 +60,8 @@ final class DetailsPanel extends javax.swing.JPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form DetailsPanel.
|
* Creates new form DetailsPanel.
|
||||||
*/
|
*/
|
||||||
DetailsPanel() {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
FileDetailsPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
dataContentPanel = DataContentPanel.createInstance();
|
dataContentPanel = DataContentPanel.createInstance();
|
||||||
detailsSplitPane.setBottomComponent(dataContentPanel);
|
detailsSplitPane.setBottomComponent(dataContentPanel);
|
||||||
@ -112,7 +114,9 @@ final class DetailsPanel extends javax.swing.JPanel {
|
|||||||
*/
|
*/
|
||||||
@Subscribe
|
@Subscribe
|
||||||
void handleClearSelectionListener(DiscoveryEventUtils.ClearInstanceSelectionEvent clearEvent) {
|
void handleClearSelectionListener(DiscoveryEventUtils.ClearInstanceSelectionEvent clearEvent) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
instancesList.clearSelection();
|
instancesList.clearSelection();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -122,7 +126,7 @@ final class DetailsPanel extends javax.swing.JPanel {
|
|||||||
* instances list should be populated
|
* instances list should be populated
|
||||||
*/
|
*/
|
||||||
@Subscribe
|
@Subscribe
|
||||||
synchronized void handlePopulateInstancesListEvent(DiscoveryEventUtils.PopulateInstancesListEvent populateEvent) {
|
void handlePopulateInstancesListEvent(DiscoveryEventUtils.PopulateInstancesListEvent populateEvent) {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
List<AbstractFile> files = populateEvent.getInstances();
|
List<AbstractFile> files = populateEvent.getInstances();
|
||||||
if (files.isEmpty()) {
|
if (files.isEmpty()) {
|
||||||
@ -154,7 +158,8 @@ final class DetailsPanel extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @return The AbstractFile which is currently selected.
|
* @return The AbstractFile which is currently selected.
|
||||||
*/
|
*/
|
||||||
synchronized AbstractFile getSelectedFile() {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
AbstractFile getSelectedFile() {
|
||||||
if (instancesList.getSelectedIndex() == -1) {
|
if (instancesList.getSelectedIndex() == -1) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
@ -186,7 +191,7 @@ final class DetailsPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
instancesScrollPane.setPreferredSize(new java.awt.Dimension(775, 60));
|
instancesScrollPane.setPreferredSize(new java.awt.Dimension(775, 60));
|
||||||
|
|
||||||
instancesList.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(DetailsPanel.class, "DetailsPanel.instancesList.border.title"))); // NOI18N
|
instancesList.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(FileDetailsPanel.class, "FileDetailsPanel.instancesList.border.title"))); // NOI18N
|
||||||
instancesList.setModel(instancesListModel);
|
instancesList.setModel(instancesListModel);
|
||||||
instancesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
instancesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
instancesList.setCellRenderer(new InstancesCellRenderer());
|
instancesList.setCellRenderer(new InstancesCellRenderer());
|
||||||
@ -241,6 +246,7 @@ final class DetailsPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||||
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
@ -31,6 +31,7 @@ import javax.swing.JList;
|
|||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
||||||
@ -56,6 +57,7 @@ final class GroupListPanel extends javax.swing.JPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form GroupListPanel.
|
* Creates new form GroupListPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
GroupListPanel() {
|
GroupListPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
}
|
}
|
||||||
@ -67,8 +69,10 @@ final class GroupListPanel extends javax.swing.JPanel {
|
|||||||
*/
|
*/
|
||||||
@Subscribe
|
@Subscribe
|
||||||
void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) {
|
void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
type = searchStartedEvent.getType();
|
type = searchStartedEvent.getType();
|
||||||
groupKeyList.setListData(new GroupKey[0]);
|
groupKeyList.setListData(new GroupKey[0]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Messages({"GroupsListPanel.noFileResults.message.text=No files were found for the selected filters.\n\n"
|
@Messages({"GroupsListPanel.noFileResults.message.text=No files were found for the selected filters.\n\n"
|
||||||
@ -90,6 +94,7 @@ final class GroupListPanel extends javax.swing.JPanel {
|
|||||||
*/
|
*/
|
||||||
@Subscribe
|
@Subscribe
|
||||||
void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) {
|
void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
groupMap = searchCompleteEvent.getGroupMap();
|
groupMap = searchCompleteEvent.getGroupMap();
|
||||||
searchfilters = searchCompleteEvent.getFilters();
|
searchfilters = searchCompleteEvent.getFilters();
|
||||||
groupingAttribute = searchCompleteEvent.getGroupingAttr();
|
groupingAttribute = searchCompleteEvent.getGroupingAttr();
|
||||||
@ -112,6 +117,7 @@ final class GroupListPanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -168,10 +174,9 @@ final class GroupListPanel extends javax.swing.JPanel {
|
|||||||
/**
|
/**
|
||||||
* Reset the group list to be empty.
|
* Reset the group list to be empty.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void resetGroupList() {
|
void resetGroupList() {
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||||
});
|
|
||||||
groupKeyList.setListData(new GroupKey[0]);
|
groupKeyList.setListData(new GroupKey[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +216,7 @@ final class GroupListPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public java.awt.Component getListCellRendererComponent(
|
public java.awt.Component getListCellRendererComponent(
|
||||||
JList<?> list,
|
JList<?> list,
|
||||||
|
@ -27,6 +27,7 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
@ -43,6 +44,7 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form HashSetFilterPaenl.
|
* Creates new form HashSetFilterPaenl.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
HashSetFilterPanel() {
|
HashSetFilterPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
setUpHashFilter();
|
setUpHashFilter();
|
||||||
@ -51,6 +53,7 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Initialize the hash filter.
|
* Initialize the hash filter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void setUpHashFilter() {
|
private void setUpHashFilter() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
try {
|
try {
|
||||||
@ -123,6 +126,7 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
private javax.swing.JScrollPane hashSetScrollPane;
|
private javax.swing.JScrollPane hashSetScrollPane;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||||
boolean hasHashSets = hashSetList.getModel().getSize() > 0;
|
boolean hasHashSets = hashSetList.getModel().getSize() > 0;
|
||||||
@ -140,6 +144,7 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JCheckBox getCheckbox() {
|
JCheckBox getCheckbox() {
|
||||||
return hashSetCheckbox;
|
return hashSetCheckbox;
|
||||||
@ -150,6 +155,7 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({"HashSetFilterPanel.error.text=At least one hash set name must be selected."})
|
@NbBundle.Messages({"HashSetFilterPanel.error.text=At least one hash set name must be selected."})
|
||||||
@Override
|
@Override
|
||||||
String checkForError() {
|
String checkForError() {
|
||||||
@ -159,11 +165,13 @@ final class HashSetFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JList<?> getList() {
|
JList<?> getList() {
|
||||||
return hashSetList;
|
return hashSetList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
AbstractFilter getFilter() {
|
AbstractFilter getFilter() {
|
||||||
if (hashSetCheckbox.isSelected()) {
|
if (hashSetCheckbox.isSelected()) {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.discovery.ui;
|
package org.sleuthkit.autopsy.discovery.ui;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,6 +33,7 @@ final class ImageFilterPanel extends AbstractFiltersPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form ImageFilterPanel.
|
* Creates new form ImageFilterPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
ImageFilterPanel() {
|
ImageFilterPanel() {
|
||||||
super();
|
super();
|
||||||
initComponents();
|
initComponents();
|
||||||
|
@ -84,7 +84,6 @@
|
|||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JLabel" name="nameLabel">
|
<Component class="javax.swing.JLabel" name="nameLabel">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
|
||||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
<Dimension value="[159, 12]"/>
|
<Dimension value="[159, 12]"/>
|
||||||
</Property>
|
</Property>
|
||||||
@ -94,6 +93,7 @@
|
|||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
<Dimension value="[159, 12]"/>
|
<Dimension value="[159, 12]"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JLabel" name="isDeletedLabel">
|
<Component class="javax.swing.JLabel" name="isDeletedLabel">
|
||||||
@ -101,9 +101,6 @@
|
|||||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/file-icon-deleted.png"/>
|
<Image iconType="3" name="/org/sleuthkit/autopsy/images/file-icon-deleted.png"/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="ImageThumbnailPanel.isDeletedLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
@ -113,6 +110,9 @@
|
|||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="ImageThumbnailPanel.isDeletedLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JLabel" name="scoreLabel">
|
<Component class="javax.swing.JLabel" name="scoreLabel">
|
||||||
@ -120,7 +120,6 @@
|
|||||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/red-circle-exclamation.png"/>
|
<Image iconType="3" name="/org/sleuthkit/autopsy/images/red-circle-exclamation.png"/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
|
||||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
@ -130,6 +129,7 @@
|
|||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
<Connection code="new Dimension(org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.discovery.ui.DiscoveryUiUtils.getIconSize())" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
|
@ -28,6 +28,7 @@ import javax.swing.JComponent;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.ListCellRenderer;
|
import javax.swing.ListCellRenderer;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which displays a thumbnail and information for an image file.
|
* Class which displays a thumbnail and information for an image file.
|
||||||
@ -41,6 +42,7 @@ final class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellRe
|
|||||||
/**
|
/**
|
||||||
* Creates new form ImageThumbnailPanel
|
* Creates new form ImageThumbnailPanel
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
ImageThumbnailPanel() {
|
ImageThumbnailPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
}
|
}
|
||||||
@ -129,6 +131,7 @@ final class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellRe
|
|||||||
private javax.swing.JLabel thumbnailLabel;
|
private javax.swing.JLabel thumbnailLabel;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"# {0} - otherInstanceCount",
|
"# {0} - otherInstanceCount",
|
||||||
"ImageThumbnailPanel.nameLabel.more.text= and {0} more",
|
"ImageThumbnailPanel.nameLabel.more.text= and {0} more",
|
||||||
@ -152,6 +155,7 @@ final class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellRe
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public String getToolTipText(MouseEvent event) {
|
public String getToolTipText(MouseEvent event) {
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.DefaultListModel;
|
import javax.swing.DefaultListModel;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,6 +38,7 @@ final class ImageThumbnailViewer extends javax.swing.JPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form ImageThumbnailViewer.
|
* Creates new form ImageThumbnailViewer.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
ImageThumbnailViewer() {
|
ImageThumbnailViewer() {
|
||||||
initComponents();
|
initComponents();
|
||||||
|
|
||||||
@ -77,6 +79,7 @@ final class ImageThumbnailViewer extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @param listener The ListSelectionListener to add to the selection model.
|
* @param listener The ListSelectionListener to add to the selection model.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void addListSelectionListener(ListSelectionListener listener) {
|
void addListSelectionListener(ListSelectionListener listener) {
|
||||||
thumbnailList.getSelectionModel().addListSelectionListener(listener);
|
thumbnailList.getSelectionModel().addListSelectionListener(listener);
|
||||||
}
|
}
|
||||||
@ -88,24 +91,23 @@ final class ImageThumbnailViewer extends javax.swing.JPanel {
|
|||||||
* @return The list of AbstractFiles which are represented by the selected
|
* @return The list of AbstractFiles which are represented by the selected
|
||||||
* image thumbnail.
|
* image thumbnail.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
List<AbstractFile> getInstancesForSelected() {
|
List<AbstractFile> getInstancesForSelected() {
|
||||||
synchronized (this) {
|
|
||||||
if (thumbnailList.getSelectedIndex() == -1) {
|
if (thumbnailList.getSelectedIndex() == -1) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
} else {
|
} else {
|
||||||
return thumbnailListModel.getElementAt(thumbnailList.getSelectedIndex()).getResultFile().getAllInstances();
|
return thumbnailListModel.getElementAt(thumbnailList.getSelectedIndex()).getResultFile().getAllInstances();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the list of thumbnails being displayed.
|
* Clear the list of thumbnails being displayed.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void clearViewer() {
|
void clearViewer() {
|
||||||
synchronized (this) {
|
|
||||||
thumbnailListModel.removeAllElements();
|
thumbnailListModel.removeAllElements();
|
||||||
thumbnailListScrollPane.getVerticalScrollBar().setValue(0);
|
thumbnailListScrollPane.getVerticalScrollBar().setValue(0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,9 +116,8 @@ final class ImageThumbnailViewer extends javax.swing.JPanel {
|
|||||||
* @param thumbnailWrapper The object which contains the thumbnail which
|
* @param thumbnailWrapper The object which contains the thumbnail which
|
||||||
* will be displayed.
|
* will be displayed.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void addImage(ImageThumbnailWrapper thumbnailWrapper) {
|
void addImage(ImageThumbnailWrapper thumbnailWrapper) {
|
||||||
synchronized (this) {
|
|
||||||
thumbnailListModel.addElement(thumbnailWrapper);
|
thumbnailListModel.addElement(thumbnailWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -27,6 +27,7 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
@ -43,6 +44,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form InterestingItemsFilterPanel.
|
* Creates new form InterestingItemsFilterPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
InterestingItemsFilterPanel() {
|
InterestingItemsFilterPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
setUpInterestingItemsFilter();
|
setUpInterestingItemsFilter();
|
||||||
@ -51,6 +53,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Initialize the interesting items filter.
|
* Initialize the interesting items filter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void setUpInterestingItemsFilter() {
|
private void setUpInterestingItemsFilter() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
try {
|
try {
|
||||||
@ -118,6 +121,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
interestingItemsList.setEnabled(interestingItemsCheckbox.isSelected());
|
interestingItemsList.setEnabled(interestingItemsCheckbox.isSelected());
|
||||||
}//GEN-LAST:event_interestingItemsCheckboxActionPerformed
|
}//GEN-LAST:event_interestingItemsCheckboxActionPerformed
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||||
boolean hasInterestingItems = interestingItemsList.getModel().getSize() > 0;
|
boolean hasInterestingItems = interestingItemsList.getModel().getSize() > 0;
|
||||||
@ -135,6 +139,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JCheckBox getCheckbox() {
|
JCheckBox getCheckbox() {
|
||||||
return interestingItemsCheckbox;
|
return interestingItemsCheckbox;
|
||||||
@ -145,6 +150,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({"InterestingItemsFilterPanel.error.text=At least one interesting file set name must be selected."})
|
@NbBundle.Messages({"InterestingItemsFilterPanel.error.text=At least one interesting file set name must be selected."})
|
||||||
@Override
|
@Override
|
||||||
String checkForError() {
|
String checkForError() {
|
||||||
@ -161,11 +167,13 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
private javax.swing.JScrollPane interestingItemsScrollPane;
|
private javax.swing.JScrollPane interestingItemsScrollPane;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JList<?> getList() {
|
JList<?> getList() {
|
||||||
return interestingItemsList;
|
return interestingItemsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
AbstractFilter getFilter() {
|
AbstractFilter getFilter() {
|
||||||
if (interestingItemsCheckbox.isSelected()) {
|
if (interestingItemsCheckbox.isSelected()) {
|
||||||
|
@ -27,6 +27,7 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
@ -43,6 +44,7 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form ObjectDetectedFilter.
|
* Creates new form ObjectDetectedFilter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
ObjectDetectedFilterPanel() {
|
ObjectDetectedFilterPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
setUpObjectFilter();
|
setUpObjectFilter();
|
||||||
@ -51,6 +53,7 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Initialize the object filter.
|
* Initialize the object filter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void setUpObjectFilter() {
|
private void setUpObjectFilter() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
try {
|
try {
|
||||||
@ -129,6 +132,7 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
private javax.swing.JScrollPane objectsScrollPane;
|
private javax.swing.JScrollPane objectsScrollPane;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||||
boolean hasObjects = objectsList.getModel().getSize() > 0;
|
boolean hasObjects = objectsList.getModel().getSize() > 0;
|
||||||
@ -146,6 +150,7 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JCheckBox getCheckbox() {
|
JCheckBox getCheckbox() {
|
||||||
return objectsCheckbox;
|
return objectsCheckbox;
|
||||||
@ -155,6 +160,8 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
JLabel getAdditionalLabel() {
|
JLabel getAdditionalLabel() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({"ObjectDetectedFilterPanel.error.text=At least one object type name must be selected."})
|
@NbBundle.Messages({"ObjectDetectedFilterPanel.error.text=At least one object type name must be selected."})
|
||||||
@Override
|
@Override
|
||||||
String checkForError() {
|
String checkForError() {
|
||||||
@ -164,11 +171,13 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JList<?> getList() {
|
JList<?> getList() {
|
||||||
return objectsList;
|
return objectsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
AbstractFilter getFilter() {
|
AbstractFilter getFilter() {
|
||||||
if (objectsCheckbox.isSelected()) {
|
if (objectsCheckbox.isSelected()) {
|
||||||
|
@ -31,6 +31,7 @@ import org.openide.util.NbBundle;
|
|||||||
import org.openide.util.actions.CallableSystemAction;
|
import org.openide.util.actions.CallableSystemAction;
|
||||||
import org.openide.util.actions.Presenter;
|
import org.openide.util.actions.Presenter;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to open the Discovery dialog. Allows the user to run searches and see
|
* Class to open the Discovery dialog. Allows the user to run searches and see
|
||||||
@ -76,6 +77,7 @@ public final class OpenDiscoveryAction extends CallableSystemAction implements P
|
|||||||
*
|
*
|
||||||
* @return The toolbar button
|
* @return The toolbar button
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public Component getToolbarPresenter() {
|
public Component getToolbarPresenter() {
|
||||||
ImageIcon icon = new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/discovery-icon-24.png")); //NON-NLS
|
ImageIcon icon = new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/discovery-icon-24.png")); //NON-NLS
|
||||||
|
@ -26,6 +26,7 @@ import javax.swing.JCheckBox;
|
|||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ParentSearchTerm;
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ParentSearchTerm;
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form ParentFolderFilterPanel.
|
* Creates new form ParentFolderFilterPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
ParentFolderFilterPanel() {
|
ParentFolderFilterPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
setUpParentPathFilter();
|
setUpParentPathFilter();
|
||||||
@ -49,6 +51,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Initialize the parent path filter.
|
* Initialize the parent path filter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void setUpParentPathFilter() {
|
private void setUpParentPathFilter() {
|
||||||
fullRadioButton.setSelected(true);
|
fullRadioButton.setSelected(true);
|
||||||
includeRadioButton.setSelected(true);
|
includeRadioButton.setSelected(true);
|
||||||
@ -239,6 +242,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
private javax.swing.JRadioButton substringRadioButton;
|
private javax.swing.JRadioButton substringRadioButton;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||||
parentCheckbox.setSelected(selected);
|
parentCheckbox.setSelected(selected);
|
||||||
@ -270,16 +274,19 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JCheckBox getCheckbox() {
|
JCheckBox getCheckbox() {
|
||||||
return parentCheckbox;
|
return parentCheckbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JLabel getAdditionalLabel() {
|
JLabel getAdditionalLabel() {
|
||||||
return parentLabel;
|
return parentLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({"ParentFolderFilterPanel.error.text=At least one parent path must be entered."})
|
@NbBundle.Messages({"ParentFolderFilterPanel.error.text=At least one parent path must be entered."})
|
||||||
@Override
|
@Override
|
||||||
String checkForError() {
|
String checkForError() {
|
||||||
@ -290,6 +297,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
/**
|
/**
|
||||||
* Utility method to get the parent path objects out of the JList.
|
* Utility method to get the parent path objects out of the JList.
|
||||||
*
|
*
|
||||||
@ -303,11 +311,13 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JList<?> getList() {
|
JList<?> getList() {
|
||||||
return parentList;
|
return parentList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
AbstractFilter getFilter() {
|
AbstractFilter getFilter() {
|
||||||
if (parentCheckbox.isSelected()) {
|
if (parentCheckbox.isSelected()) {
|
||||||
|
@ -24,6 +24,7 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
|
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData.Frequency;
|
import org.sleuthkit.autopsy.discovery.search.SearchData.Frequency;
|
||||||
@ -41,6 +42,7 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form PastOccurrencesFilterPanel.
|
* Creates new form PastOccurrencesFilterPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
PastOccurrencesFilterPanel(Type type) {
|
PastOccurrencesFilterPanel(Type type) {
|
||||||
initComponents();
|
initComponents();
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@ -101,6 +103,7 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Initialize the frequency filter.
|
* Initialize the frequency filter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void setUpFrequencyFilter() {
|
private void setUpFrequencyFilter() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
DefaultListModel<SearchData.Frequency> frequencyListModel = (DefaultListModel<SearchData.Frequency>) crFrequencyList.getModel();
|
DefaultListModel<SearchData.Frequency> frequencyListModel = (DefaultListModel<SearchData.Frequency>) crFrequencyList.getModel();
|
||||||
@ -126,6 +129,7 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
private javax.swing.JCheckBox pastOccurrencesCheckbox;
|
private javax.swing.JCheckBox pastOccurrencesCheckbox;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||||
boolean canBeFilteredOn = type != Type.DOMAIN || CentralRepository.isEnabled();
|
boolean canBeFilteredOn = type != Type.DOMAIN || CentralRepository.isEnabled();
|
||||||
@ -144,6 +148,7 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JCheckBox getCheckbox() {
|
JCheckBox getCheckbox() {
|
||||||
return pastOccurrencesCheckbox;
|
return pastOccurrencesCheckbox;
|
||||||
@ -154,6 +159,7 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@NbBundle.Messages({"PastOccurrencesFilterPanel.error.text=At least one value in the past occurrence filter must be selected."})
|
@NbBundle.Messages({"PastOccurrencesFilterPanel.error.text=At least one value in the past occurrence filter must be selected."})
|
||||||
@Override
|
@Override
|
||||||
String checkForError() {
|
String checkForError() {
|
||||||
@ -163,11 +169,13 @@ final class PastOccurrencesFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JList<?> getList() {
|
JList<?> getList() {
|
||||||
return crFrequencyList;
|
return crFrequencyList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
AbstractFilter getFilter() {
|
AbstractFilter getFilter() {
|
||||||
if (pastOccurrencesCheckbox.isSelected()) {
|
if (pastOccurrencesCheckbox.isSelected()) {
|
||||||
|
@ -40,6 +40,7 @@ import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
||||||
@ -85,6 +86,7 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
*/
|
*/
|
||||||
@Messages({"ResultsPanel.viewFileInDir.name=View File in Directory",
|
@Messages({"ResultsPanel.viewFileInDir.name=View File in Directory",
|
||||||
"ResultsPanel.openInExternalViewer.name=Open in External Viewer"})
|
"ResultsPanel.openInExternalViewer.name=Open in External Viewer"})
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
ResultsPanel() {
|
ResultsPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
imageThumbnailViewer = new ImageThumbnailViewer();
|
imageThumbnailViewer = new ImageThumbnailViewer();
|
||||||
@ -125,9 +127,14 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//JIRA-TODO 6307 Add listener for domainSummaryViewer when 6782, 6773, and the other details area related stories are done
|
domainSummaryViewer.addListSelectionListener((e) -> {
|
||||||
|
if (resultType == SearchData.Type.DOMAIN) {
|
||||||
|
domainSummaryViewer.sendPopulateEvent(!e.getValueIsAdjusting());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
SearchData.Type getActiveType() {
|
SearchData.Type getActiveType() {
|
||||||
return resultType;
|
return resultType;
|
||||||
}
|
}
|
||||||
@ -139,6 +146,7 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
* @return The list of AbstractFiles which are represented by the item
|
* @return The list of AbstractFiles which are represented by the item
|
||||||
* selected in the results viewer area.
|
* selected in the results viewer area.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private List<AbstractFile> getInstancesForSelected() {
|
private List<AbstractFile> getInstancesForSelected() {
|
||||||
if (null != resultType) {
|
if (null != resultType) {
|
||||||
switch (resultType) {
|
switch (resultType) {
|
||||||
@ -212,20 +220,22 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
void handleCancelBackgroundTasksEvent(DiscoveryEventUtils.CancelBackgroundTasksEvent cancelEvent) {
|
void handleCancelBackgroundTasksEvent(DiscoveryEventUtils.CancelBackgroundTasksEvent cancelEvent) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
for (SwingWorker<Void, Void> thumbWorker : resultContentWorkers) {
|
for (SwingWorker<Void, Void> thumbWorker : resultContentWorkers) {
|
||||||
if (!thumbWorker.isDone()) {
|
if (!thumbWorker.isDone()) {
|
||||||
thumbWorker.cancel(true);
|
thumbWorker.cancel(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultContentWorkers.clear();
|
resultContentWorkers.clear();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the result viewer and any associate workers to a default empty
|
* Reset the result viewer and any associate workers to a default empty
|
||||||
* state.
|
* state.
|
||||||
*/
|
*/
|
||||||
synchronized void resetResultViewer() {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void resetResultViewer() {
|
||||||
resultsViewerPanel.remove(imageThumbnailViewer);
|
resultsViewerPanel.remove(imageThumbnailViewer);
|
||||||
resultsViewerPanel.remove(videoThumbnailViewer);
|
resultsViewerPanel.remove(videoThumbnailViewer);
|
||||||
resultsViewerPanel.remove(documentPreviewViewer);
|
resultsViewerPanel.remove(documentPreviewViewer);
|
||||||
@ -250,7 +260,8 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @param results The list of ResultFiles to populate the video viewer with.
|
* @param results The list of ResultFiles to populate the video viewer with.
|
||||||
*/
|
*/
|
||||||
synchronized void populateVideoViewer(List<Result> results) {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void populateVideoViewer(List<Result> results) {
|
||||||
for (Result result : results) {
|
for (Result result : results) {
|
||||||
VideoThumbnailWorker thumbWorker = new VideoThumbnailWorker((ResultFile) result);
|
VideoThumbnailWorker thumbWorker = new VideoThumbnailWorker((ResultFile) result);
|
||||||
thumbWorker.execute();
|
thumbWorker.execute();
|
||||||
@ -265,7 +276,8 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @param results The list of ResultFiles to populate the image viewer with.
|
* @param results The list of ResultFiles to populate the image viewer with.
|
||||||
*/
|
*/
|
||||||
synchronized void populateImageViewer(List<Result> results) {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void populateImageViewer(List<Result> results) {
|
||||||
for (Result result : results) {
|
for (Result result : results) {
|
||||||
ImageThumbnailWorker thumbWorker = new ImageThumbnailWorker((ResultFile) result);
|
ImageThumbnailWorker thumbWorker = new ImageThumbnailWorker((ResultFile) result);
|
||||||
thumbWorker.execute();
|
thumbWorker.execute();
|
||||||
@ -281,7 +293,8 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
* @param results The list of ResultFiles to populate the document viewer
|
* @param results The list of ResultFiles to populate the document viewer
|
||||||
* with.
|
* with.
|
||||||
*/
|
*/
|
||||||
synchronized void populateDocumentViewer(List<Result> results) {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void populateDocumentViewer(List<Result> results) {
|
||||||
for (Result result : results) {
|
for (Result result : results) {
|
||||||
DocumentPreviewWorker documentWorker = new DocumentPreviewWorker((ResultFile) result);
|
DocumentPreviewWorker documentWorker = new DocumentPreviewWorker((ResultFile) result);
|
||||||
documentWorker.execute();
|
documentWorker.execute();
|
||||||
@ -297,7 +310,8 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
* @param results The list of ResultDomains to populate the domain summary
|
* @param results The list of ResultDomains to populate the domain summary
|
||||||
* viewer with.
|
* viewer with.
|
||||||
*/
|
*/
|
||||||
synchronized void populateDomainViewer(List<Result> results) {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
void populateDomainViewer(List<Result> results) {
|
||||||
SleuthkitCase currentCase;
|
SleuthkitCase currentCase;
|
||||||
try {
|
try {
|
||||||
currentCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
currentCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||||
@ -374,11 +388,9 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
* @param startingEntry The index of the first file in the group to include
|
* @param startingEntry The index of the first file in the group to include
|
||||||
* in this page.
|
* in this page.
|
||||||
*/
|
*/
|
||||||
@Subscribe
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private synchronized void setPage(int startingEntry
|
private void setPage(int startingEntry) {
|
||||||
) {
|
|
||||||
int pageSize = pageSizeComboBox.getItemAt(pageSizeComboBox.getSelectedIndex());
|
int pageSize = pageSizeComboBox.getItemAt(pageSizeComboBox.getSelectedIndex());
|
||||||
synchronized (this) {
|
|
||||||
if (pageWorker != null && !pageWorker.isDone()) {
|
if (pageWorker != null && !pageWorker.isDone()) {
|
||||||
pageWorker.cancel(true);
|
pageWorker.cancel(true);
|
||||||
}
|
}
|
||||||
@ -395,16 +407,14 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
pageWorker = new PageWorker(searchFilters, groupingAttribute, groupSort, fileSortMethod, selectedGroupKey, startingEntry, pageSize, resultType, centralRepo);
|
pageWorker = new PageWorker(searchFilters, groupingAttribute, groupSort, fileSortMethod, selectedGroupKey, startingEntry, pageSize, resultType, centralRepo);
|
||||||
pageWorker.execute();
|
pageWorker.execute();
|
||||||
} else {
|
} else {
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
pageSizeComboBox.setEnabled(true);
|
pageSizeComboBox.setEnabled(true);
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable the paging controls based on what exists in the page.
|
* Enable the paging controls based on what exists in the page.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Messages({"# {0} - currentPage",
|
@Messages({"# {0} - currentPage",
|
||||||
"# {1} - totalPages",
|
"# {1} - totalPages",
|
||||||
"ResultsPanel.currentPage.displayValue=Page: {0} of {1}"})
|
"ResultsPanel.currentPage.displayValue=Page: {0} of {1}"})
|
||||||
@ -678,6 +688,7 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
/**
|
/**
|
||||||
* Disable all the paging controls.
|
* Disable all the paging controls.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void disablePagingControls() {
|
private void disablePagingControls() {
|
||||||
nextPageButton.setEnabled(false);
|
nextPageButton.setEnabled(false);
|
||||||
previousPageButton.setEnabled(false);
|
previousPageButton.setEnabled(false);
|
||||||
@ -708,6 +719,7 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
* @param file The ResultFile which represents the video file thumbnails
|
* @param file The ResultFile which represents the video file thumbnails
|
||||||
* are being retrieved for.
|
* are being retrieved for.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
VideoThumbnailWorker(ResultFile file) {
|
VideoThumbnailWorker(ResultFile file) {
|
||||||
thumbnailWrapper = new VideoThumbnailsWrapper(file);
|
thumbnailWrapper = new VideoThumbnailsWrapper(file);
|
||||||
videoThumbnailViewer.addVideo(thumbnailWrapper);
|
videoThumbnailViewer.addVideo(thumbnailWrapper);
|
||||||
@ -746,6 +758,7 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
* @param file The ResultFile which represents the image file thumbnails
|
* @param file The ResultFile which represents the image file thumbnails
|
||||||
* are being retrieved for.
|
* are being retrieved for.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
ImageThumbnailWorker(ResultFile file) {
|
ImageThumbnailWorker(ResultFile file) {
|
||||||
thumbnailWrapper = new ImageThumbnailWrapper(file);
|
thumbnailWrapper = new ImageThumbnailWrapper(file);
|
||||||
imageThumbnailViewer.addImage(thumbnailWrapper);
|
imageThumbnailViewer.addImage(thumbnailWrapper);
|
||||||
@ -788,6 +801,7 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
* @param file The ResultFile which represents the document file a
|
* @param file The ResultFile which represents the document file a
|
||||||
* preview is being retrieved for.
|
* preview is being retrieved for.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
DocumentPreviewWorker(ResultFile file) {
|
DocumentPreviewWorker(ResultFile file) {
|
||||||
documentWrapper = new DocumentWrapper(file);
|
documentWrapper = new DocumentWrapper(file);
|
||||||
documentPreviewViewer.addDocument(documentWrapper);
|
documentPreviewViewer.addDocument(documentWrapper);
|
||||||
@ -836,6 +850,7 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
* @param file The ResultFile which represents the domain attribute the
|
* @param file The ResultFile which represents the domain attribute the
|
||||||
* preview is being retrieved for.
|
* preview is being retrieved for.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
DomainThumbnailWorker(SleuthkitCase caseDb, ResultDomain domain) {
|
DomainThumbnailWorker(SleuthkitCase caseDb, ResultDomain domain) {
|
||||||
this.caseDb = caseDb;
|
this.caseDb = caseDb;
|
||||||
domainWrapper = new DomainWrapper(domain);
|
domainWrapper = new DomainWrapper(domain);
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.discovery.ui;
|
package org.sleuthkit.autopsy.discovery.ui;
|
||||||
|
|
||||||
import java.awt.Cursor;
|
import java.awt.Cursor;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ final class ResultsSplitPaneDivider extends javax.swing.JPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form LabeledSplitPaneDivider.
|
* Creates new form LabeledSplitPaneDivider.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
ResultsSplitPaneDivider() {
|
ResultsSplitPaneDivider() {
|
||||||
initComponents();
|
initComponents();
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import javax.swing.JCheckBox;
|
|||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData.FileSize;
|
import org.sleuthkit.autopsy.discovery.search.SearchData.FileSize;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
||||||
@ -42,6 +43,7 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
*
|
*
|
||||||
* @param type The type of result being searched for.
|
* @param type The type of result being searched for.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
SizeFilterPanel(SearchData.Type type) {
|
SizeFilterPanel(SearchData.Type type) {
|
||||||
initComponents();
|
initComponents();
|
||||||
setUpSizeFilter(type);
|
setUpSizeFilter(type);
|
||||||
@ -109,6 +111,7 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
private javax.swing.JScrollPane sizeScrollPane;
|
private javax.swing.JScrollPane sizeScrollPane;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||||
sizeCheckbox.setSelected(selected);
|
sizeCheckbox.setSelected(selected);
|
||||||
@ -124,6 +127,7 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JCheckBox getCheckbox() {
|
JCheckBox getCheckbox() {
|
||||||
return sizeCheckbox;
|
return sizeCheckbox;
|
||||||
@ -137,6 +141,7 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Initialize the file size filter.
|
* Initialize the file size filter.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void setUpSizeFilter(SearchData.Type fileType) {
|
private void setUpSizeFilter(SearchData.Type fileType) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
DefaultListModel<FileSize> sizeListModel = (DefaultListModel<FileSize>) sizeList.getModel();
|
DefaultListModel<FileSize> sizeListModel = (DefaultListModel<FileSize>) sizeList.getModel();
|
||||||
@ -169,6 +174,7 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
|
|
||||||
@NbBundle.Messages({"SizeFilterPanel.error.text=At least one size must be selected."})
|
@NbBundle.Messages({"SizeFilterPanel.error.text=At least one size must be selected."})
|
||||||
@Override
|
@Override
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
String checkForError() {
|
String checkForError() {
|
||||||
if (sizeCheckbox.isSelected() && sizeList.getSelectedValuesList().isEmpty()) {
|
if (sizeCheckbox.isSelected() && sizeList.getSelectedValuesList().isEmpty()) {
|
||||||
return Bundle.SizeFilterPanel_error_text();
|
return Bundle.SizeFilterPanel_error_text();
|
||||||
@ -177,11 +183,13 @@ final class SizeFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JList<?> getList() {
|
JList<?> getList() {
|
||||||
return sizeList;
|
return sizeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
AbstractFilter getFilter() {
|
AbstractFilter getFilter() {
|
||||||
if (sizeCheckbox.isSelected()) {
|
if (sizeCheckbox.isSelected()) {
|
||||||
|
@ -22,6 +22,7 @@ import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
|
|||||||
import javax.swing.JCheckBox;
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,6 +35,7 @@ final class UserCreatedFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form UserCreatedFilterPanel.
|
* Creates new form UserCreatedFilterPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
UserCreatedFilterPanel() {
|
UserCreatedFilterPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
}
|
}
|
||||||
@ -69,11 +71,13 @@ final class UserCreatedFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||||
userCreatedCheckbox.setSelected(selected);
|
userCreatedCheckbox.setSelected(selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
JCheckBox getCheckbox() {
|
JCheckBox getCheckbox() {
|
||||||
return userCreatedCheckbox;
|
return userCreatedCheckbox;
|
||||||
@ -99,6 +103,7 @@ final class UserCreatedFilterPanel extends AbstractDiscoveryFilterPanel {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
AbstractFilter getFilter() {
|
AbstractFilter getFilter() {
|
||||||
if (userCreatedCheckbox.isSelected()) {
|
if (userCreatedCheckbox.isSelected()) {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.discovery.ui;
|
package org.sleuthkit.autopsy.discovery.ui;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,6 +33,7 @@ final class VideoFilterPanel extends AbstractFiltersPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form VideoFilterPanel.
|
* Creates new form VideoFilterPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
VideoFilterPanel() {
|
VideoFilterPanel() {
|
||||||
super();
|
super();
|
||||||
initComponents();
|
initComponents();
|
||||||
|
@ -32,6 +32,7 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.ListCellRenderer;
|
import javax.swing.ListCellRenderer;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which displays thumbnails and information for a video file.
|
* Class which displays thumbnails and information for a video file.
|
||||||
@ -47,6 +48,7 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe
|
|||||||
/**
|
/**
|
||||||
* Creates new form VideoThumbnailPanel.
|
* Creates new form VideoThumbnailPanel.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
VideoThumbnailPanel() {
|
VideoThumbnailPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
this.setFocusable(true);
|
this.setFocusable(true);
|
||||||
@ -58,6 +60,7 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe
|
|||||||
* @param thumbnailWrapper The object which contains the video thumbnails to
|
* @param thumbnailWrapper The object which contains the video thumbnails to
|
||||||
* add.
|
* add.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private void addThumbnails(VideoThumbnailsWrapper thumbnailWrapper) {
|
private void addThumbnails(VideoThumbnailsWrapper thumbnailWrapper) {
|
||||||
imagePanel.removeAll();
|
imagePanel.removeAll();
|
||||||
GridBagConstraints gridBagConstraints = new GridBagConstraints();
|
GridBagConstraints gridBagConstraints = new GridBagConstraints();
|
||||||
@ -164,6 +167,7 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe
|
|||||||
private javax.swing.JLabel scoreLabel;
|
private javax.swing.JLabel scoreLabel;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Messages({
|
@Messages({
|
||||||
"# {0} - otherInstanceCount",
|
"# {0} - otherInstanceCount",
|
||||||
"VideoThumbnailPanel.nameLabel.more.text= and {0} more",
|
"VideoThumbnailPanel.nameLabel.more.text= and {0} more",
|
||||||
@ -231,6 +235,7 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe
|
|||||||
return Bundle.VideoThumbnailPanel_sizeLabel_text(size, units);
|
return Bundle.VideoThumbnailPanel_sizeLabel_text(size, units);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
@Override
|
@Override
|
||||||
public String getToolTipText(MouseEvent event) {
|
public String getToolTipText(MouseEvent event) {
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.DefaultListModel;
|
import javax.swing.DefaultListModel;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,6 +37,7 @@ final class VideoThumbnailViewer extends javax.swing.JPanel {
|
|||||||
/**
|
/**
|
||||||
* Creates new form VideoThumbnailViewer.
|
* Creates new form VideoThumbnailViewer.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
VideoThumbnailViewer() {
|
VideoThumbnailViewer() {
|
||||||
initComponents();
|
initComponents();
|
||||||
}
|
}
|
||||||
@ -45,6 +47,7 @@ final class VideoThumbnailViewer extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @param listener The ListSelectionListener to add to the selection model.
|
* @param listener The ListSelectionListener to add to the selection model.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void addListSelectionListener(ListSelectionListener listener) {
|
void addListSelectionListener(ListSelectionListener listener) {
|
||||||
thumbnailList.getSelectionModel().addListSelectionListener(listener);
|
thumbnailList.getSelectionModel().addListSelectionListener(listener);
|
||||||
}
|
}
|
||||||
@ -56,25 +59,23 @@ final class VideoThumbnailViewer extends javax.swing.JPanel {
|
|||||||
* @return The list of AbstractFiles which are represented by the selected
|
* @return The list of AbstractFiles which are represented by the selected
|
||||||
* Video thumbnails.
|
* Video thumbnails.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
List<AbstractFile> getInstancesForSelected() {
|
List<AbstractFile> getInstancesForSelected() {
|
||||||
synchronized (this) {
|
|
||||||
if (thumbnailList.getSelectedIndex() == -1) {
|
if (thumbnailList.getSelectedIndex() == -1) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
} else {
|
} else {
|
||||||
return thumbnailListModel.getElementAt(thumbnailList.getSelectedIndex()).getResultFile().getAllInstances();
|
return thumbnailListModel.getElementAt(thumbnailList.getSelectedIndex()).getResultFile().getAllInstances();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the list of thumbnails being displayed.
|
* Clear the list of thumbnails being displayed.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void clearViewer() {
|
void clearViewer() {
|
||||||
synchronized (this) {
|
|
||||||
thumbnailListModel.removeAllElements();
|
thumbnailListModel.removeAllElements();
|
||||||
thumbnailListScrollPane.getVerticalScrollBar().setValue(0);
|
thumbnailListScrollPane.getVerticalScrollBar().setValue(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add thumbnails for a video to the panel.
|
* Add thumbnails for a video to the panel.
|
||||||
@ -82,11 +83,10 @@ final class VideoThumbnailViewer extends javax.swing.JPanel {
|
|||||||
* @param thumbnailWrapper The object which contains the thumbnails which
|
* @param thumbnailWrapper The object which contains the thumbnails which
|
||||||
* will be displayed.
|
* will be displayed.
|
||||||
*/
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
void addVideo(VideoThumbnailsWrapper thumbnailWrapper) {
|
void addVideo(VideoThumbnailsWrapper thumbnailWrapper) {
|
||||||
synchronized (this) {
|
|
||||||
thumbnailListModel.addElement(thumbnailWrapper);
|
thumbnailListModel.addElement(thumbnailWrapper);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="400" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="300" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
</Form>
|
@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.discovery.ui;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
|
import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer;
|
||||||
|
import org.sleuthkit.autopsy.contentviewers.artifactviewers.CommunicationArtifactViewerHelper;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panel to display the details for a Web History Artifact.
|
||||||
|
*/
|
||||||
|
@ServiceProvider(service = ArtifactContentViewer.class)
|
||||||
|
public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel implements ArtifactContentViewer {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Logger logger = Logger.getLogger(WebHistoryDetailsPanel.class.getName());
|
||||||
|
private BlackboardArtifact webHistoryArtifact;
|
||||||
|
private final GridBagLayout gridBagLayout = new GridBagLayout();
|
||||||
|
private final List<BlackboardAttribute> urlList = new ArrayList<>();
|
||||||
|
private final List<BlackboardAttribute> dateAccessedList = new ArrayList<>();
|
||||||
|
private final List<BlackboardAttribute> referrerUrlList = new ArrayList<>();
|
||||||
|
private final List<BlackboardAttribute> titleList = new ArrayList<>();
|
||||||
|
private final List<BlackboardAttribute> programNameList = new ArrayList<>();
|
||||||
|
private final List<BlackboardAttribute> domainList = new ArrayList<>();
|
||||||
|
private final List<BlackboardAttribute> otherList = new ArrayList<>();
|
||||||
|
private final GridBagConstraints gridBagConstraints = new GridBagConstraints();
|
||||||
|
private String dataSourceName;
|
||||||
|
private String sourceFileName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form WebHistoryDetailsPanel.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
public WebHistoryDetailsPanel() {
|
||||||
|
initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
@Override
|
||||||
|
public void setArtifact(BlackboardArtifact artifact) {
|
||||||
|
resetComponent();
|
||||||
|
if (artifact != null) {
|
||||||
|
try {
|
||||||
|
extractArtifactData(artifact);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.WARNING, "Unable to get attributes for artifact " + artifact.getArtifactID(), ex);
|
||||||
|
}
|
||||||
|
updateView();
|
||||||
|
}
|
||||||
|
this.setLayout(this.gridBagLayout);
|
||||||
|
this.revalidate();
|
||||||
|
this.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts data from the artifact to be displayed in the panel.
|
||||||
|
*
|
||||||
|
* @param artifact Artifact to show.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException {
|
||||||
|
|
||||||
|
webHistoryArtifact = artifact;
|
||||||
|
// Get all the attributes and group them by the section panels they go in
|
||||||
|
for (BlackboardAttribute bba : webHistoryArtifact.getAttributes()) {
|
||||||
|
if (bba.getAttributeType().getTypeName().startsWith("TSK_URL")) {
|
||||||
|
urlList.add(bba);
|
||||||
|
} else if (bba.getAttributeType().getTypeName().startsWith("TSK_PROG_NAME")) {
|
||||||
|
programNameList.add(bba);
|
||||||
|
} else if (bba.getAttributeType().getTypeName().startsWith("TSK_DOMAIN")) {
|
||||||
|
domainList.add(bba);
|
||||||
|
} else if (bba.getAttributeType().getTypeName().startsWith("TSK_REFERRER")) {
|
||||||
|
referrerUrlList.add(bba);
|
||||||
|
} else if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED")) {
|
||||||
|
dateAccessedList.add(bba);
|
||||||
|
} else if (bba.getAttributeType().getTypeName().startsWith("TSK_TITLE")) {
|
||||||
|
titleList.add(bba);
|
||||||
|
} else {
|
||||||
|
otherList.add(bba);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSourceName = webHistoryArtifact.getDataSource().getName();
|
||||||
|
sourceFileName = webHistoryArtifact.getParent().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the panel so that it is empty.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
private void resetComponent() {
|
||||||
|
// clear the panel
|
||||||
|
this.removeAll();
|
||||||
|
gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START;
|
||||||
|
gridBagConstraints.gridy = 0;
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.weighty = 0.0;
|
||||||
|
gridBagConstraints.weightx = 0.0; // keep components fixed horizontally.
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 12, 0, 0);
|
||||||
|
gridBagConstraints.fill = GridBagConstraints.NONE;
|
||||||
|
webHistoryArtifact = null;
|
||||||
|
dataSourceName = null;
|
||||||
|
sourceFileName = null;
|
||||||
|
urlList.clear();
|
||||||
|
dateAccessedList.clear();
|
||||||
|
referrerUrlList.clear();
|
||||||
|
titleList.clear();
|
||||||
|
programNameList.clear();
|
||||||
|
domainList.clear();
|
||||||
|
otherList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
@Override
|
||||||
|
public Component getComponent() {
|
||||||
|
// Slap a vertical scrollbar on the panel.
|
||||||
|
return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
@Override
|
||||||
|
public boolean isSupported(BlackboardArtifact artifact) {
|
||||||
|
return (artifact != null)
|
||||||
|
&& (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({"WebHistoryDetailsPanel.details.attrHeader=Attributes",
|
||||||
|
"WebHistoryDetailsPanel.details.sourceHeader=Source",
|
||||||
|
"WebHistoryDetailsPanel.details.dataSource=Data Source",
|
||||||
|
"WebHistoryDetailsPanel.details.file=File"})
|
||||||
|
/**
|
||||||
|
* 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")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
|
this.setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 400, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 300, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the view to reflect the current artifact's details.
|
||||||
|
*/
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
private void updateView() {
|
||||||
|
CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_attrHeader());
|
||||||
|
|
||||||
|
for (BlackboardAttribute bba : this.titleList) {
|
||||||
|
CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString());
|
||||||
|
}
|
||||||
|
for (BlackboardAttribute bba : dateAccessedList) {
|
||||||
|
CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString());
|
||||||
|
}
|
||||||
|
for (BlackboardAttribute bba : domainList) {
|
||||||
|
CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString());
|
||||||
|
}
|
||||||
|
for (BlackboardAttribute bba : urlList) {
|
||||||
|
CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString());
|
||||||
|
}
|
||||||
|
for (BlackboardAttribute bba : referrerUrlList) {
|
||||||
|
CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString());
|
||||||
|
}
|
||||||
|
for (BlackboardAttribute bba : programNameList) {
|
||||||
|
CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString());
|
||||||
|
}
|
||||||
|
for (BlackboardAttribute bba : otherList) {
|
||||||
|
CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString());
|
||||||
|
}
|
||||||
|
CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_sourceHeader());
|
||||||
|
CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_dataSource(), dataSourceName);
|
||||||
|
CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_file(), sourceFileName);
|
||||||
|
// add veritcal glue at the end
|
||||||
|
CommunicationArtifactViewerHelper.addPageEndGlue(this, gridBagLayout, this.gridBagConstraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -187,7 +187,6 @@ class Chunker implements Iterator<Chunk>, Iterable<Chunk> {
|
|||||||
private static StringBuilder sanitize(String s) {
|
private static StringBuilder sanitize(String s) {
|
||||||
String normStr = Normalizer.normalize(s, Normalizer.Form.NFKC);
|
String normStr = Normalizer.normalize(s, Normalizer.Form.NFKC);
|
||||||
return sanitizeToUTF8(replaceInvalidUTF16(normStr));
|
return sanitizeToUTF8(replaceInvalidUTF16(normStr));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -336,8 +335,9 @@ class Chunker implements Iterator<Chunk>, Iterable<Chunk> {
|
|||||||
String chunkSegment;
|
String chunkSegment;
|
||||||
if (Character.isHighSurrogate(ch)) {
|
if (Character.isHighSurrogate(ch)) {
|
||||||
//read another char into the buffer.
|
//read another char into the buffer.
|
||||||
charsRead = reader.read(tempChunkBuf, 1, 1);
|
int surrogateCharsRead = reader.read(tempChunkBuf, 1, 1);
|
||||||
if (charsRead == -1) {
|
charsRead += surrogateCharsRead;
|
||||||
|
if (surrogateCharsRead == -1) {
|
||||||
//this is the last chunk, so just drop the unpaired surrogate
|
//this is the last chunk, so just drop the unpaired surrogate
|
||||||
endOfReaderReached = true;
|
endOfReaderReached = true;
|
||||||
return;
|
return;
|
||||||
@ -352,17 +352,32 @@ class Chunker implements Iterator<Chunk>, Iterable<Chunk> {
|
|||||||
|
|
||||||
//cleanup any invalid utf-16 sequences
|
//cleanup any invalid utf-16 sequences
|
||||||
StringBuilder sanitizedChunkSegment = sanitize(chunkSegment);
|
StringBuilder sanitizedChunkSegment = sanitize(chunkSegment);
|
||||||
//check for whitespace.
|
//get the length in utf8 bytes of the read chars
|
||||||
whitespaceFound = Character.isWhitespace(sanitizedChunkSegment.codePointAt(0));
|
int segmentSize = chunkSegment.getBytes(UTF_8).length;
|
||||||
//add read chars to the chunk and update the length.
|
|
||||||
currentChunk.append(sanitizedChunkSegment);
|
|
||||||
chunkSizeBytes += sanitizedChunkSegment.toString().getBytes(UTF_8).length;
|
|
||||||
|
|
||||||
// lower case the string and get it's size. NOTE: lower casing can
|
// lower case the string and get it's size. NOTE: lower casing can
|
||||||
// change the size of the string.
|
// change the size of the string.
|
||||||
String lowerCasedSegment = sanitizedChunkSegment.toString().toLowerCase();
|
String lowerCasedSegment = sanitizedChunkSegment.toString().toLowerCase();
|
||||||
|
int lowerCasedSegmentSize = lowerCasedSegment.getBytes(UTF_8).length;
|
||||||
|
|
||||||
|
//if it will not put us past maxBytes
|
||||||
|
if ((chunkSizeBytes + segmentSize < maxBytes - MAX_CHAR_SIZE_INCREASE_IN_BYTES)
|
||||||
|
&& (lowerCasedChunkSizeBytes + lowerCasedSegmentSize < maxBytes - MAX_CHAR_SIZE_INCREASE_IN_BYTES)) {
|
||||||
|
|
||||||
|
//add read chars to the chunk and update the length.
|
||||||
|
currentChunk.append(sanitizedChunkSegment);
|
||||||
|
chunkSizeBytes += segmentSize;
|
||||||
|
|
||||||
lowerCasedChunk.append(lowerCasedSegment);
|
lowerCasedChunk.append(lowerCasedSegment);
|
||||||
lowerCasedChunkSizeBytes += lowerCasedSegment.getBytes(UTF_8).length;
|
lowerCasedChunkSizeBytes += lowerCasedSegmentSize;
|
||||||
|
|
||||||
|
//check for whitespace.
|
||||||
|
whitespaceFound = Character.isWhitespace(sanitizedChunkSegment.codePointAt(0));
|
||||||
|
} else {
|
||||||
|
//unread it, and break out of read loop.
|
||||||
|
reader.unread(tempChunkBuf, 0, charsRead);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ cache:
|
|||||||
- C:\ProgramData\chocolatey\lib
|
- C:\ProgramData\chocolatey\lib
|
||||||
- '%APPVEYOR_BUILD_FOLDER%\Core\test\qa-functional\data'
|
- '%APPVEYOR_BUILD_FOLDER%\Core\test\qa-functional\data'
|
||||||
|
|
||||||
|
|
||||||
image: Visual Studio 2015
|
image: Visual Studio 2015
|
||||||
platform: x64
|
platform: x64
|
||||||
environment:
|
environment:
|
||||||
@ -44,4 +43,6 @@ build_script:
|
|||||||
- cd %APPVEYOR_BUILD_FOLDER%
|
- cd %APPVEYOR_BUILD_FOLDER%
|
||||||
- cmd: ant -q build
|
- cmd: ant -q build
|
||||||
|
|
||||||
test: off
|
test_script:
|
||||||
|
- cd %APPVEYOR_BUILD_FOLDER%
|
||||||
|
- cmd: ant -q test-no-regression
|
||||||
|
32
build.xml
32
build.xml
@ -78,6 +78,38 @@
|
|||||||
</delete>
|
</delete>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<!-- This target is similar to the regular test target that calls test on all nbm's,
|
||||||
|
but this target excludes the Testing nbm which runs the regression tests -->
|
||||||
|
<target name="test-no-regression" depends="build" description="Runs tests for all modules in the suite excluding the regression tests of the Testing NBM.">
|
||||||
|
<!--taken from https://stackoverflow.com/a/10859103; remove "Testing" from the modules and provide 'modulesNoTesting' as result. -->
|
||||||
|
<property name="modulesBeforeChange" value="${modules}"/>
|
||||||
|
<script language="javascript">
|
||||||
|
<![CDATA[
|
||||||
|
var before = project.getProperty("modulesBeforeChange");
|
||||||
|
var separator = ":";
|
||||||
|
var testingNbm = "Testing";
|
||||||
|
var beforeSplit = before.split(separator);
|
||||||
|
var items = [];
|
||||||
|
for (var i = 0; i < beforeSplit.length; i++) {
|
||||||
|
if (beforeSplit[i].toUpperCase() !== testingNbm.toUpperCase()) {
|
||||||
|
items.push(beforeSplit[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var itemsJoined = items.join(separator);
|
||||||
|
project.setNewProperty("modulesNoTesting", itemsJoined);
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<sortsuitemodules unsortedmodules="${modulesNoTesting}" sortedmodulesproperty="modules.test.sorted" sorttests="true"/>
|
||||||
|
<!-- continue on fail -->
|
||||||
|
<property name="continue.after.failing.tests" value="true"/>
|
||||||
|
<subant target="test" buildpath="${modules.test.sorted}" inheritrefs="false" inheritall="false">
|
||||||
|
<property name="cluster.path.evaluated" value="${cluster.path.evaluated}"/> <!-- Just for speed of pre-7.0 projects -->
|
||||||
|
<property name="harness.taskdefs.done" value="${harness.taskdefs.done}"/> <!-- optimization -->
|
||||||
|
<property name="continue.after.failing.tests" value="${continue.after.failing.tests}"/>
|
||||||
|
</subant>
|
||||||
|
</target>
|
||||||
|
|
||||||
<!-- This target will create a custom ZIP file for us. It first uses the general
|
<!-- This target will create a custom ZIP file for us. It first uses the general
|
||||||
ZIP target and then opens it up and adds in any files that we want. This is where we customize the
|
ZIP target and then opens it up and adds in any files that we want. This is where we customize the
|
||||||
version number. -->
|
version number. -->
|
||||||
|
@ -464,6 +464,16 @@ def normalize_db_entry(line, files_table, vs_parts_table, vs_info_table, fs_info
|
|||||||
|
|
||||||
# remove object ID
|
# remove object ID
|
||||||
if files_index:
|
if files_index:
|
||||||
|
|
||||||
|
# Ignore TIFF size and hash if extracted from PDFs.
|
||||||
|
# See JIRA-6951 for more details.
|
||||||
|
# index -1 = last element in the list, which is extension
|
||||||
|
# index -3 = 3rd from the end, which is the parent path.
|
||||||
|
if fields_list[-1] == "'tif'" and fields_list[-3].endswith(".pdf/'"):
|
||||||
|
fields_list[15] = "'SIZE_IGNORED'"
|
||||||
|
fields_list[23] = "'MD5_IGNORED'"
|
||||||
|
fields_list[24] = "'SHA256_IGNORED'"
|
||||||
|
|
||||||
newLine = ('INSERT INTO "tsk_files" VALUES(' + ', '.join(fields_list[1:]) + ');')
|
newLine = ('INSERT INTO "tsk_files" VALUES(' + ', '.join(fields_list[1:]) + ');')
|
||||||
# Remove object ID from Unalloc file name
|
# Remove object ID from Unalloc file name
|
||||||
newLine = re.sub('Unalloc_[0-9]+_', 'Unalloc_', newLine)
|
newLine = re.sub('Unalloc_[0-9]+_', 'Unalloc_', newLine)
|
||||||
|
@ -70,6 +70,7 @@ sub processShellActivities {
|
|||||||
::rptMsg("");
|
::rptMsg("");
|
||||||
|
|
||||||
while ($offset < ($sz - 10)) {
|
while ($offset < ($sz - 10)) {
|
||||||
|
|
||||||
# Code to locate the appropriate identifier
|
# Code to locate the appropriate identifier
|
||||||
$tag = 1;
|
$tag = 1;
|
||||||
while ($tag) {
|
while ($tag) {
|
||||||
@ -78,9 +79,15 @@ sub processShellActivities {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$offset++;
|
$offset++;
|
||||||
|
# Check if at end of file and exit loop if it is
|
||||||
|
last if ($offset >= $sz );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check if at end of file and exit loop if it is
|
||||||
|
last if ($offset >= $sz );
|
||||||
|
|
||||||
|
|
||||||
$offset += 2;
|
$offset += 2;
|
||||||
$l = unpack("C",substr($data,$offset,1));
|
$l = unpack("C",substr($data,$offset,1));
|
||||||
# ::rptMsg("String Length: ".sprintf "0x%x",$l);
|
# ::rptMsg("String Length: ".sprintf "0x%x",$l);
|
||||||
|
@ -8,5 +8,19 @@ pushd bindings/java && ant -q dist && popd
|
|||||||
|
|
||||||
echo "Building Autopsy..." && echo -en 'travis_fold:start:script.build\\r'
|
echo "Building Autopsy..." && echo -en 'travis_fold:start:script.build\\r'
|
||||||
cd $TRAVIS_BUILD_DIR/
|
cd $TRAVIS_BUILD_DIR/
|
||||||
ant build
|
ant -q build
|
||||||
echo -en 'travis_fold:end:script.build\\r'
|
echo -en 'travis_fold:end:script.build\\r'
|
||||||
|
|
||||||
|
echo "Testing Autopsy..." && echo -en 'travis_fold:start:script.tests\\r'
|
||||||
|
echo "Free Space:"
|
||||||
|
echo `df -h .`
|
||||||
|
|
||||||
|
if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
||||||
|
# if os x, just run it
|
||||||
|
ant -q test-no-regression
|
||||||
|
elif [ "${TRAVIS_OS_NAME}" = "linux" ]; then
|
||||||
|
# if linux use xvfb
|
||||||
|
xvfb-run ant -q test-no-regression
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -en 'travis_fold:end:script.tests\\r'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user