Merge remote-tracking branch 'upstream/release-4.12.0' into 5153_logicalImagerDoc

This commit is contained in:
Ann Priestman 2019-07-02 08:32:13 -04:00
commit c45781d2df
9 changed files with 279 additions and 20 deletions

View File

@ -18,17 +18,15 @@
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
@ -124,6 +122,8 @@ public class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact>{
logger.log(Level.SEVERE, "Failed to load artifacts for relationship sources.", ex); //NON-NLS
}
list.sort(new DateComparator());
return true;
}
@ -132,4 +132,80 @@ public class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact>{
return new MessageNode(key, null, null);
}
/**
* A comparator class for comparing BlackboardArtifacts of type
* TSK_EMAIL_MSG, TSK_MESSAGE, and TSK_CALLLOG by their respective creation
* date-time.
*/
class DateComparator implements Comparator<BlackboardArtifact> {
@Override
public int compare(BlackboardArtifact bba1, BlackboardArtifact bba2) {
BlackboardAttribute attribute1 = null;
BlackboardAttribute attribute2 = null;
// Inializing to Long.MAX_VALUE so that if a BlackboardArtifact of
// any unexpected type is passed in, it will bubble to the top of
// the list.
long dateTime1 = Long.MAX_VALUE;
long dateTime2 = Long.MAX_VALUE;
if (bba1 != null) {
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba1.getArtifactTypeID());
if (fromID != null) {
try {
switch (fromID) {
case TSK_EMAIL_MSG:
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
break;
case TSK_MESSAGE:
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
break;
case TSK_CALLLOG:
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
break;
default:
attribute1 = null;
break;
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba1.getArtifactID()), ex);
}
}
}
if (bba2 != null) {
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba2.getArtifactTypeID());
if (fromID != null) {
try {
switch (fromID) {
case TSK_EMAIL_MSG:
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
break;
case TSK_MESSAGE:
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
break;
case TSK_CALLLOG:
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
break;
default:
attribute2 = null;
break;
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba2.getArtifactID()), ex);
}
}
}
if (attribute1 != null) {
dateTime1 = attribute1.getValueLong();
}
if (attribute2 != null) {
dateTime2 = attribute2.getValueLong();
}
return Long.compare(dateTime1, dateTime2);
}
}
}

View File

@ -18,6 +18,7 @@
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -29,13 +30,10 @@ import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
@ -144,15 +142,41 @@ final class ThreadChildNodeFactory extends ChildFactory<BlackboardArtifact> {
rootMessageMap.put(threadID, bba);
} else {
// Get the date of the message
BlackboardAttribute tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
BlackboardAttribute tableAttribute = null;
switch(fromID) {
case TSK_EMAIL_MSG:
tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
// put the earliest message into the table
if(tableAttribute != null
&& attribute != null
&& tableAttribute.getValueLong() > attribute.getValueLong()) {
rootMessageMap.put(threadID, bba);
}
break;
case TSK_MESSAGE:
tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
// put the earliest message into the table
if(tableAttribute != null
&& attribute != null
&& tableAttribute.getValueLong() < attribute.getValueLong()) {
rootMessageMap.put(threadID, bba);
}
break;
case TSK_CALLLOG:
tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
// put the earliest message into the table
if(tableAttribute != null
&& attribute != null
&& tableAttribute.getValueLong() > attribute.getValueLong()) {
rootMessageMap.put(threadID, bba);
}
break;
}
}
}
}
@ -161,6 +185,8 @@ final class ThreadChildNodeFactory extends ChildFactory<BlackboardArtifact> {
list.add(bba);
}
list.sort(new ThreadDateComparator());
return true;
}
@ -242,4 +268,80 @@ final class ThreadChildNodeFactory extends ChildFactory<BlackboardArtifact> {
return sheet;
}
}
/**
* A comparator class for comparing BlackboardArtifacts of type
* TSK_EMAIL_MSG, TSK_MESSAGE, and TSK_CALLLOG by their respective creation
* date-time.
*
* Nodes will be sorted newest to oldest.
*/
class ThreadDateComparator implements Comparator<BlackboardArtifact> {
@Override
public int compare(BlackboardArtifact bba1, BlackboardArtifact bba2) {
BlackboardAttribute attribute1 = null;
BlackboardAttribute attribute2 = null;
// Inializing to Long.MAX_VALUE so that if a BlackboardArtifact of
// any unexpected type is passed in, it will bubble to the top of
// the list.
long dateTime1 = Long.MAX_VALUE;
long dateTime2 = Long.MAX_VALUE;
if (bba1 != null) {
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba1.getArtifactTypeID());
if (fromID != null) {
try {
switch (fromID) {
case TSK_EMAIL_MSG:
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
break;
case TSK_MESSAGE:
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
break;
case TSK_CALLLOG:
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
break;
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba1.getArtifactID()), ex);
}
}
}
if (bba1 != null) {
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba2.getArtifactTypeID());
if (fromID != null) {
try {
switch (fromID) {
case TSK_EMAIL_MSG:
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
break;
case TSK_MESSAGE:
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
break;
case TSK_CALLLOG:
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
break;
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba2.getArtifactID()), ex);
}
}
}
if (attribute1 != null) {
dateTime1 = attribute1.getValueLong();
}
if (attribute2 != null) {
dateTime2 = attribute2.getValueLong();
}
return Long.compare(dateTime1, dateTime2) * -1;
}
}
}

View File

@ -18,11 +18,18 @@
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.util.logging.Level;
import javax.swing.Action;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT;
import org.sleuthkit.datamodel.TskCoreException;
/**
* An AbstractNode subclass which wraps a MessageNode object. Doing this allows
@ -31,6 +38,10 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
*/
final class ThreadNode extends AbstractNode{
private static final Logger logger = Logger.getLogger(ThreadNode.class.getName());
private final static int MAX_SUBJECT_LENGTH = 120;
final private MessageNode messageNode;
ThreadNode(BlackboardArtifact artifact, String threadID, Action preferredAction) {
@ -41,9 +52,38 @@ final class ThreadNode extends AbstractNode{
@Override
protected Sheet createSheet() {
BlackboardArtifact artifact = messageNode.getArtifact();
if(artifact == null) {
return messageNode.createSheet() ;
}
Sheet sheet = messageNode.createSheet();
BlackboardArtifact.ARTIFACT_TYPE artifactTypeID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
// If its a text message, replace the subject node which is probably
// an empty string with the firest 120 characters of the text message
if(artifactTypeID != null && artifactTypeID == TSK_MESSAGE) {
try {
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(TSK_TEXT.getTypeID())));
if(attribute != null) {
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
sheetSet.remove("Subject");
String msg = attribute.getDisplayString();
if(msg != null && msg.length() > MAX_SUBJECT_LENGTH) {
msg = msg.substring(0, MAX_SUBJECT_LENGTH) + "...";
}
sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "", msg)); //NON-NLS
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Unable to get the text message from message artifact %d", artifact.getId()), ex);
}
}
return sheet;
}
String getThreadID() {
return messageNode.getThreadID();
}

View File

@ -76,7 +76,7 @@ EditNonFullPathsRulePanel.modifiedDaysNotPositiveException=Modified days must be
EditNonFullPathsRulePanel.units.bytes=Bytes
EditNonFullPathsRulePanel.units.gigabytes=Gigabytes
EditNonFullPathsRulePanel.units.kilobytes=Kilobytes
EditNonFullPathsRulePanel.units.megabytes=MegaBytes
EditNonFullPathsRulePanel.units.megabytes=Megabytes
# {0} - fieldName
EditRulePanel.blankLineException={0} cannot have a blank line
EditRulePanel.emptyRuleName.message=Rule name cannot be empty

View File

@ -36,9 +36,9 @@ import java.util.logging.Level;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
@ -251,6 +251,9 @@ final class ConfigVisualPanel1 extends JPanel {
int firstRemovableDrive = -1;
int i = 0;
for (File root : roots) {
if (DriveListUtils.isNetworkDrive(root.toString().replace(":\\", ""))) {
continue;
}
String description = FileSystemView.getFileSystemView().getSystemTypeDescription(root);
long spaceInBytes = root.getTotalSpace();
String sizeWithUnit = DriveListUtils.humanReadableByteCount(spaceInBytes, false);

View File

@ -66,7 +66,7 @@ final class EditNonFullPathsRulePanel extends javax.swing.JPanel {
"EditNonFullPathsRulePanel.example=Example: ",
"EditNonFullPathsRulePanel.units.bytes=Bytes",
"EditNonFullPathsRulePanel.units.kilobytes=Kilobytes",
"EditNonFullPathsRulePanel.units.megabytes=MegaBytes",
"EditNonFullPathsRulePanel.units.megabytes=Megabytes",
"EditNonFullPathsRulePanel.units.gigabytes=Gigabytes"
})
EditNonFullPathsRulePanel(JButton okButton, JButton cancelButton, String ruleName, LogicalImagerRule rule, boolean editing) {

View File

@ -18,6 +18,12 @@
*/
package org.sleuthkit.autopsy.logicalimager.dsp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
/**
* Utility class for displaying a list of drives
*/
@ -48,4 +54,33 @@ public final class DriveListUtils {
private DriveListUtils() {
//empty private constructor for util class
}
/** Use the command <code>net</code> to determine what this drive is.
* <code>net use</code> will return an error for anything which isn't a share.
*/
public static boolean isNetworkDrive(String driveLetter) {
List<String> cmd = Arrays.asList("cmd", "/c", "net", "use", driveLetter + ":");
try {
Process p = new ProcessBuilder(cmd)
.redirectErrorStream(true)
.start();
p.getOutputStream().close();
StringBuilder consoleOutput = new StringBuilder();
String line;
try (BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
while ((line = in.readLine()) != null) {
consoleOutput.append(line).append("\r\n");
}
}
int rc = p.waitFor();
return rc == 0;
} catch(IOException | InterruptedException e) {
return false; // assume not a network drive
}
}
}

View File

@ -481,6 +481,9 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener {
int firstRemovableDrive = -1;
int i = 0;
for (File root : roots) {
if (DriveListUtils.isNetworkDrive(root.toString().replace(":\\", ""))) {
continue;
}
String description = FileSystemView.getFileSystemView().getSystemTypeDescription(root);
long spaceInBytes = root.getTotalSpace();
String sizeWithUnit = DriveListUtils.humanReadableByteCount(spaceInBytes, false);

View File

@ -6,8 +6,8 @@ app.name=${branding.token}
### if left unset, version will default to today's date
app.version=4.12.0
### build.type must be one of: DEVELOPMENT, RELEASE
#build.type=RELEASE
build.type=DEVELOPMENT
build.type=RELEASE
#build.type=DEVELOPMENT
project.org.netbeans.progress=org-netbeans-api-progress
project.org.sleuthkit.autopsy.experimental=Experimental