This commit is contained in:
U-BASIS\dgrove 2017-08-16 11:11:04 -04:00
commit 7254a25ff8
101 changed files with 1055 additions and 1016 deletions

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
<!-- for some information on what you could do (e.g. targets to override). -->
<!-- If you delete this file and reopen the project it will be recreated. -->
<project name="org.sleuthkit.autopsy.centralrepository" default="netbeans" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
<description>Builds, tests, and runs the project org.sleuthkit.autopsy.centralrepository.</description>
<import file="nbproject/build-impl.xml"/>
<import file="../BootstrapIvy.xml"/>
<property name="thirdparty.dir" value="${basedir}/../thirdparty" />
<property name="modules.dir" value="${basedir}/release/modules/" />
<property name="ext.dir" value="${modules.dir}/ext" />
<target name="resolve">
<ivy:settings file="ivysettings.xml" />
<ivy:resolve file="ivy.xml" conf="central-repository"/>
</target>
<target name="retrieve" depends="resolve">
<ivy:retrieve conf="central-repository" pattern="${basedir}/release/modules/ext/[artifact]-[revision](-[classifier]).[ext]" />
</target>
<target name="init" depends="retrieve, harness.init" />
<target name="clean" depends="projectized-common.clean">
<!--Override clean to delete jars, etc downloaded with Ivy
or copied in from thirdparty folder. This way we don't end up with
out-of-date/unneeded stuff in the installer-->
<delete dir="${basedir}/release"/>
</target>
</project>

View File

@ -1,6 +0,0 @@
Manifest-Version: 1.0
AutoUpdate-Show-In-Client: true
OpenIDE-Module: org.sleuthkit.autopsy.centralrepository
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/centralrepository/Bundle.properties
OpenIDE-Module-Specification-Version: 1.0
OpenIDE-Module-Install: org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.class

View File

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT ***
*** EDIT ../build.xml INSTEAD ***
-->
<project name="org.sleuthkit.autopsy.centralrepository-impl" basedir="..">
<fail message="Please build using Ant 1.7.1 or higher.">
<condition>
<not>
<antversion atleast="1.7.1"/>
</not>
</condition>
</fail>
<property file="nbproject/private/suite-private.properties"/>
<property file="nbproject/suite.properties"/>
<fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
<property file="${suite.dir}/nbproject/private/platform-private.properties"/>
<property file="${suite.dir}/nbproject/platform.properties"/>
<macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<property name="@{name}" value="${@{value}}"/>
</sequential>
</macrodef>
<macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
<attribute name="property"/>
<attribute name="value"/>
<sequential>
<property name="@{property}" value="@{value}"/>
</sequential>
</macrodef>
<property file="${user.properties.file}"/>
<nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
<condition>
<not>
<contains string="${cluster.path.evaluated}" substring="platform"/>
</not>
</condition>
</fail>
<import file="${harness.dir}/build.xml"/>
</project>

View File

@ -1,9 +0,0 @@
file.reference.commons-dbcp2-2.1.1.jar=release/modules/ext/commons-dbcp2-2.1.1.jar
file.reference.commons-logging-1.2.jar=release/modules/ext/commons-logging-1.2.jar
file.reference.commons-pool2-2.4.2.jar=release/modules/ext/commons-pool2-2.4.2.jar
file.reference.postgresql-42.1.1.jar=release/modules/ext/postgresql-42.1.1.jar
file.reference.sqlite-jdbc-3.16.1.jar=release/modules/ext/sqlite-jdbc-3.16.1.jar
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
license.file=../LICENSE-2.0.txt
nbm.homepage=http://www.sleuthkit.org/autopsy/

View File

@ -1,116 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.apisupport.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
<code-name-base>org.sleuthkit.autopsy.centralrepository</code-name-base>
<suite-component/>
<module-dependencies>
<dependency>
<code-name-base>org.netbeans.api.progress</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.47.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.modules.options.api</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.45.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.67.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.modules</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.48.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.nodes</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.45.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.7.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util.lookup</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.33.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util.ui</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.6.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.windows</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.75.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.sleuthkit.autopsy.core</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.8</specification-version>
</run-dependency>
</dependency>
</module-dependencies>
<public-packages/>
<class-path-extension>
<runtime-relative-path>ext/sqlite-jdbc-3.16.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\sqlite-jdbc-3.16.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-dbcp2-2.1.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-dbcp2-2.1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/postgresql-42.1.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\postgresql-42.1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-pool2-2.4.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-pool2-2.4.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-logging-1.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-logging-1.2.jar</binary-origin>
</class-path-extension>
</data>
</configuration>
</project>

View File

@ -1 +0,0 @@
suite.dir=${basedir}/..

View File

@ -19,5 +19,7 @@
<dependency conf="core->default" org="com.adobe.xmp" name="xmpcore" rev="5.1.2"/>
<dependency conf="core->default" org="org.apache.zookeeper" name="zookeeper" rev="3.4.6"/>
<dependency conf="core->default" org="org.apache.commons" name="commons-dbcp2" rev="2.1.1"/>
<dependency conf="core->default" org="org.apache.commons" name="commons-pool2" rev="2.4.2"/>
</dependencies>
</ivy-module>

View File

@ -362,6 +362,14 @@
<runtime-relative-path>ext/curator-framework-2.8.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/curator-framework-2.8.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-dbcp2-2.1.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-dbcp2-2.1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-pool2-2.4.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-pool2-2.4.2.jar</binary-origin>
</class-path-extension>
</data>
</configuration>
</project>

View File

@ -36,8 +36,10 @@ import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction;
import org.sleuthkit.datamodel.SpecialDirectory;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskFileRange;
import org.sleuthkit.datamodel.VirtualDirectory;
@ -45,6 +47,7 @@ import org.sleuthkit.datamodel.LocalFilesDataSource;
import org.sleuthkit.datamodel.TskDataException;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractContent;
import org.sleuthkit.datamodel.CarvingResult;
import org.sleuthkit.datamodel.TskData;
@ -295,7 +298,7 @@ public class FileManager implements Closeable {
* @param atime The accessed time of the file.
* @param mtime The modified time of the file.
* @param isFile True if a file, false if a directory.
* @param parentFile The parent file from which the file was derived.
* @param parentObj The parent object from which the file was derived.
* @param rederiveDetails The details needed to re-derive file (will be
* specific to the derivation method), currently
* unused.
@ -317,7 +320,7 @@ public class FileManager implements Closeable {
long size,
long ctime, long crtime, long atime, long mtime,
boolean isFile,
AbstractFile parentFile,
Content parentObj,
String rederiveDetails, String toolName, String toolVersion, String otherDetails,
TskData.EncodingType encodingType) throws TskCoreException {
if (null == caseDb) {
@ -325,7 +328,7 @@ public class FileManager implements Closeable {
}
return caseDb.addDerivedFile(fileName, localPath, size,
ctime, crtime, atime, mtime,
isFile, parentFile, rederiveDetails, toolName, toolVersion, otherDetails, encodingType);
isFile, parentObj, rederiveDetails, toolName, toolVersion, otherDetails, encodingType);
}
/**
@ -496,12 +499,9 @@ public class FileManager implements Closeable {
* database, recursively adding the contents of directories.
*
* @param trans A case database transaction.
* @param parentDirectory The root virtual direcotry of the data source.
* @param parentDirectory The root virtual directory of the data source or the parent local directory.
* @param localFile The local/logical file or directory.
* @param encodingType Type of encoding used when storing the file
*
* @returns File object of file added or new virtualdirectory for the
* directory.
* @param progressUpdater Called after each file/directory is added to
* the case database.
*
@ -510,14 +510,14 @@ public class FileManager implements Closeable {
* @throws TskCoreException If there is a problem completing a database
* operation.
*/
private AbstractFile addLocalFile(CaseDbTransaction trans, VirtualDirectory parentDirectory, java.io.File localFile,
private AbstractFile addLocalFile(CaseDbTransaction trans, SpecialDirectory parentDirectory, java.io.File localFile,
TskData.EncodingType encodingType, FileAddProgressUpdater progressUpdater) throws TskCoreException {
if (localFile.isDirectory()) {
/*
* Add the directory as a virtual directory.
* Add the directory as a local directory.
*/
VirtualDirectory virtualDirectory = caseDb.addVirtualDirectory(parentDirectory.getId(), localFile.getName(), trans);
progressUpdater.fileAdded(virtualDirectory);
LocalDirectory localDirectory = caseDb.addLocalDirectory(parentDirectory.getId(), localFile.getName(), trans);
progressUpdater.fileAdded(localDirectory);
/*
* Add its children, if any.
@ -525,11 +525,11 @@ public class FileManager implements Closeable {
final java.io.File[] childFiles = localFile.listFiles();
if (childFiles != null && childFiles.length > 0) {
for (java.io.File childFile : childFiles) {
addLocalFile(trans, virtualDirectory, childFile, progressUpdater);
addLocalFile(trans, localDirectory, childFile, progressUpdater);
}
}
return virtualDirectory;
return localDirectory;
} else {
return caseDb.addLocalFile(localFile.getName(), localFile.getAbsolutePath(), localFile.length(),
0, 0, 0, 0,
@ -677,13 +677,10 @@ public class FileManager implements Closeable {
* database, recursively adding the contents of directories.
*
* @param trans A case database transaction.
* @param parentDirectory The root virtual direcotry of the data source.
* @param parentDirectory The root virtual directory of the data source or the parent local directory.
* @param localFile The local/logical file or directory.
* @param progressUpdater notifier to receive progress notifications on
* folders added, or null if not used
*
* @returns File object of file added or new virtualdirectory for the
* directory.
* @param progressUpdater Called after each file/directory is added to
* the case database.
*
@ -695,7 +692,7 @@ public class FileManager implements Closeable {
* @deprecated Use the version with explicit EncodingType instead
*/
@Deprecated
private AbstractFile addLocalFile(CaseDbTransaction trans, VirtualDirectory parentDirectory, java.io.File localFile, FileAddProgressUpdater progressUpdater) throws TskCoreException {
private AbstractFile addLocalFile(CaseDbTransaction trans, SpecialDirectory parentDirectory, java.io.File localFile, FileAddProgressUpdater progressUpdater) throws TskCoreException {
return addLocalFile(trans, parentDirectory, localFile, TskData.EncodingType.NONE, progressUpdater);
}

View File

@ -1095,6 +1095,20 @@ public abstract class AbstractSqlEamDb implements EamDb {
preparedUpdate.executeUpdate();
} else {
// In this case, the user is tagging something that isn't in the database,
// which means the case and/or datasource may also not be in the database.
// We could improve effiency by keeping a list of all datasources and cases
// in the database, but we don't expect the user to be tagging large numbers
// of items (that didn't have the CE ingest module run on them) at once.
if(null == getCaseDetails(eamInstance.getEamCase().getCaseUUID())){
newCase(eamInstance.getEamCase());
}
if (null == getDataSourceDetails(eamInstance.getEamDataSource().getDeviceID())) {
newDataSource(eamInstance.getEamDataSource());
}
eamArtifact.getInstances().get(0).setKnownStatus(TskData.FileKnown.BAD);
addArtifact(eamArtifact);
}

View File

@ -35,6 +35,20 @@ public class Installer extends ModuleInstall {
private final PropertyChangeListener pcl = new CaseEventListener();
private final IngestEventsListener ieListener = new IngestEventsListener();
private static Installer instance;
public synchronized static Installer getDefault() {
if (instance == null) {
instance = new Installer();
}
return instance;
}
private Installer() {
super();
}
@Override
public void restored() {
Case.addPropertyChangeListener(pcl);

View File

@ -212,6 +212,7 @@ public class Installer extends ModuleInstall {
packageInstallers.add(org.sleuthkit.autopsy.corecomponents.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.datamodel.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.ingest.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.centralrepository.eventlisteners.Installer.getDefault());
}
/**

View File

@ -26,6 +26,7 @@ import java.awt.event.ActionListener;
import java.awt.datatransfer.StringSelection;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ExecutionException;
@ -456,12 +457,13 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
return false;
}
Content content = node.getLookup().lookup(Content.class);
if (content != null) {
for (Content content : node.getLookup().lookupAll(Content.class)) {
if ( (content != null) && (!(content instanceof BlackboardArtifact)) ){
try {
return content.getAllArtifactsCount() > 0;
} catch (TskException ex) {
logger.log(Level.WARNING, "Couldn't get count of BlackboardArtifacts for content", ex); //NON-NLS
logger.log(Level.SEVERE, "Couldn't get count of BlackboardArtifacts for content", ex); //NON-NLS
}
}
}
return false;
@ -693,21 +695,27 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
// blackboard artifact, if any.
Lookup lookup = selectedNode.getLookup();
// Get the content.
Content content = lookup.lookup(Content.class);
if (content == null) {
// Get the content. We may get BlackboardArtifacts, ignore those here.
ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
Collection<? extends Content> contents = lookup.lookupAll(Content.class);
if (contents.isEmpty()) {
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
}
Content underlyingContent = null;
for (Content content : contents) {
if ( (content != null) && (!(content instanceof BlackboardArtifact)) ) {
// Get all of the blackboard artifacts associated with the content. These are what this
// viewer displays.
ArrayList<BlackboardArtifact> artifacts;
try {
artifacts = content.getAllArtifacts();
underlyingContent = content;
break;
} catch (TskException ex) {
logger.log(Level.WARNING, "Couldn't get artifacts", ex); //NON-NLS
logger.log(Level.SEVERE, "Couldn't get artifacts", ex); //NON-NLS
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
}
}
}
if (isCancelled()) {
return null;
@ -716,7 +724,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
// Build the new artifact contents cache.
ArrayList<ResultsTableArtifact> artifactContents = new ArrayList<>();
for (BlackboardArtifact artifact : artifacts) {
artifactContents.add(new ResultsTableArtifact(artifact, content));
artifactContents.add(new ResultsTableArtifact(artifact, underlyingContent));
}
// If the node has an underlying blackboard artifact, show it. If not,

View File

@ -37,7 +37,6 @@ import java.util.TreeMap;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.prefs.Preferences;
import java.util.stream.Stream;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
@ -59,8 +58,6 @@ import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Node.Property;
import org.openide.nodes.NodeAdapter;
import org.openide.nodes.NodeMemberEvent;
import org.openide.util.NbBundle;
import org.openide.util.NbPreferences;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
@ -82,8 +79,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
private static final Logger logger = Logger.getLogger(DataResultViewerTable.class.getName());
@NbBundle.Messages("DataResultViewerTable.firstColLbl=Name")
static private final String FIRST_COLUMN_LABEL = Bundle.DataResultViewerTable_firstColLbl();
@NbBundle.Messages("DataResultViewerTable.pleasewaitNodeDisplayName=Please Wait...")
private static final String PLEASEWAIT_NODE_DISPLAY_NAME = Bundle.DataResultViewerTable_pleasewaitNodeDisplayName();
private static final Color TAGGED_COLOR = new Color(200, 210, 220);
/**
* The properties map:
@ -103,8 +98,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
*/
private final Map<String, ETableColumn> columnMap = new HashMap<>();
private final PleasewaitNodeListener pleasewaitNodeListener = new PleasewaitNodeListener();
private Node currentRoot;
/*
@ -218,15 +211,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
hasChildren = selectedNode.getChildren().getNodesCount() > 0;
}
Node oldNode = this.em.getRootContext();
if (oldNode != null) {
oldNode.removeNodeListener(pleasewaitNodeListener);
}
if (hasChildren) {
currentRoot = selectedNode;
pleasewaitNodeListener.reset();
currentRoot.addNodeListener(pleasewaitNodeListener);
em.setRootContext(currentRoot);
setupTable();
} else {
@ -764,35 +750,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
}
}
private class PleasewaitNodeListener extends NodeAdapter {
private volatile boolean load = true;
public void reset() {
load = true;
}
@Override
public void childrenAdded(final NodeMemberEvent nme) {
Node[] delta = nme.getDelta();
if (load && containsReal(delta)) {
load = false;
//JMTODO: this looks suspicious
if (SwingUtilities.isEventDispatchThread()) {
setupTable();
} else {
SwingUtilities.invokeLater(() -> setupTable());
}
}
}
private boolean containsReal(Node[] delta) {
return Stream.of(delta)
.map(Node::getDisplayName)
.noneMatch(PLEASEWAIT_NODE_DISPLAY_NAME::equals);
}
}
/**
* This custom renderer extends the renderer that was already being used by
* the outline table. This renderer colors a row if the tags property of the

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -22,17 +22,19 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import org.openide.nodes.Children;
import java.util.Map;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType.*;
import static org.sleuthkit.autopsy.datamodel.Bundle.*;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
import org.sleuthkit.datamodel.AbstractFile;
@ -47,27 +49,24 @@ import org.sleuthkit.datamodel.TskCoreException;
*/
public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends AbstractContentNode<T> {
private static final Logger LOGGER = Logger.getLogger(AbstractAbstractFileNode.class.getName());
private static final Logger logger = Logger.getLogger(AbstractAbstractFileNode.class.getName());
@NbBundle.Messages("AbstractAbstractFileNode.addFileProperty.desc=no description")
private static final String NO_DESCR = AbstractAbstractFileNode_addFileProperty_desc();
/**
* @param <T> type of the AbstractFile data to encapsulate
* @param abstractFile file to encapsulate
* @param abstractFile file to wrap
*/
AbstractAbstractFileNode(T abstractFile) {
super(abstractFile);
String name = abstractFile.getName();
int dotIndex = name.lastIndexOf(".");
if (dotIndex > 0) {
String ext = name.substring(dotIndex).toLowerCase();
String ext = abstractFile.getNameExtension();
if (StringUtils.isNotBlank(ext)) {
ext = "." + ext;
// If this is an archive file we will listen for ingest events
// that will notify us when new content has been identified.
for (String s : FileTypeExtensions.getArchiveExtensions()) {
if (ext.equals(s)) {
if (FileTypeExtensions.getArchiveExtensions().contains(ext)) {
IngestManager.getInstance().addIngestModuleEventListener(pcl);
}
}
}
// Listen for case events so that we can detect when case is closed
Case.addPropertyChangeListener(pcl);
}
@ -103,7 +102,6 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
} catch (NullPointerException ex) {
// Skip
}
}
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
if (evt.getNewValue() == null) {
@ -127,194 +125,125 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
this.setSheet(createSheet());
}
// Note: this order matters for the search result, changed it if the order of property headers on the "KeywordSearchNode"changed
public static enum AbstractFilePropertyType {
@NbBundle.Messages({"AbstractAbstractFileNode.nameColLbl=Name",
"AbstractAbstractFileNode.locationColLbl=Location",
"AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time",
"AbstractAbstractFileNode.changeTimeColLbl=Change Time",
"AbstractAbstractFileNode.accessTimeColLbl=Access Time",
"AbstractAbstractFileNode.createdTimeColLbl=Created Time",
"AbstractAbstractFileNode.sizeColLbl=Size",
"AbstractAbstractFileNode.flagsDirColLbl=Flags(Dir)",
"AbstractAbstractFileNode.flagsMetaColLbl=Flags(Meta)",
"AbstractAbstractFileNode.modeColLbl=Mode",
"AbstractAbstractFileNode.useridColLbl=UserID",
"AbstractAbstractFileNode.groupidColLbl=GroupID",
"AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.",
"AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.",
"AbstractAbstractFileNode.typeDirColLbl=Type(Dir)",
"AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)",
"AbstractAbstractFileNode.knownColLbl=Known",
"AbstractAbstractFileNode.inHashsetsColLbl=In Hashsets",
"AbstractAbstractFileNode.md5HashColLbl=MD5 Hash",
"AbstractAbstractFileNode.objectId=Object ID",
"AbstractAbstractFileNode.mimeType=MIME Type",
"AbstractAbstractFileNode.extensionColLbl=Extension"})
public enum AbstractFilePropertyType {
NAME {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.nameColLbl");
}
},
LOCATION {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.locationColLbl");
}
},
MOD_TIME {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.modifiedTimeColLbl");
}
},
CHANGED_TIME {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.changeTimeColLbl");
}
},
ACCESS_TIME {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.accessTimeColLbl");
}
},
CREATED_TIME {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.createdTimeColLbl");
}
},
SIZE {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.sizeColLbl");
}
},
FLAGS_DIR {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.flagsDirColLbl");
}
},
FLAGS_META {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.flagsMetaColLbl");
}
},
MODE {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.modeColLbl");
}
},
USER_ID {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.useridColLbl");
}
},
GROUP_ID {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.groupidColLbl");
}
},
META_ADDR {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.metaAddrColLbl");
}
},
ATTR_ADDR {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.attrAddrColLbl");
}
},
TYPE_DIR {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.typeDirColLbl");
}
},
TYPE_META {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.typeMetaColLbl");
}
},
KNOWN {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.knownColLbl");
}
},
HASHSETS {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.inHashsetsColLbl");
}
},
MD5HASH {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.md5HashColLbl");
}
},
ObjectID {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.objectId");
NAME(AbstractAbstractFileNode_nameColLbl()),
LOCATION(AbstractAbstractFileNode_locationColLbl()),
MOD_TIME(AbstractAbstractFileNode_modifiedTimeColLbl()),
CHANGED_TIME(AbstractAbstractFileNode_changeTimeColLbl()),
ACCESS_TIME(AbstractAbstractFileNode_accessTimeColLbl()),
CREATED_TIME(AbstractAbstractFileNode_createdTimeColLbl()),
SIZE(AbstractAbstractFileNode_sizeColLbl()),
FLAGS_DIR(AbstractAbstractFileNode_flagsDirColLbl()),
FLAGS_META(AbstractAbstractFileNode_flagsMetaColLbl()),
MODE(AbstractAbstractFileNode_modeColLbl()),
USER_ID(AbstractAbstractFileNode_useridColLbl()),
GROUP_ID(AbstractAbstractFileNode_groupidColLbl()),
META_ADDR(AbstractAbstractFileNode_metaAddrColLbl()),
ATTR_ADDR(AbstractAbstractFileNode_attrAddrColLbl()),
TYPE_DIR(AbstractAbstractFileNode_typeDirColLbl()),
TYPE_META(AbstractAbstractFileNode_typeMetaColLbl()),
KNOWN(AbstractAbstractFileNode_knownColLbl()),
HASHSETS(AbstractAbstractFileNode_inHashsetsColLbl()),
MD5HASH(AbstractAbstractFileNode_md5HashColLbl()),
ObjectID(AbstractAbstractFileNode_objectId()),
MIMETYPE(AbstractAbstractFileNode_mimeType()),
EXTENSION(AbstractAbstractFileNode_extensionColLbl());
final private String displayString;
private AbstractFilePropertyType(String displayString) {
this.displayString = displayString;
}
},
MIMETYPE {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.mimeType");
return displayString;
}
},
}
/**
* Fill map with AbstractFile properties
*
* @param map map with preserved ordering, where property names/values are
* put
* @param content to extract properties from
* @param map map with preserved ordering, where property names/values
* are put
* @param content The content to get properties for.
*/
public static void fillPropertyMap(Map<String, Object> map, AbstractFile content) {
String path = "";
try {
path = content.getUniquePath();
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Except while calling Content.getUniquePath() on {0}", content); //NON-NLS
}
map.put(AbstractFilePropertyType.NAME.toString(), AbstractAbstractFileNode.getContentDisplayName(content));
map.put(AbstractFilePropertyType.LOCATION.toString(), path);
map.put(AbstractFilePropertyType.MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content));
map.put(AbstractFilePropertyType.CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content));
map.put(AbstractFilePropertyType.ACCESS_TIME.toString(), ContentUtils.getStringTime(content.getAtime(), content));
map.put(AbstractFilePropertyType.CREATED_TIME.toString(), ContentUtils.getStringTime(content.getCrtime(), content));
map.put(AbstractFilePropertyType.SIZE.toString(), content.getSize());
map.put(AbstractFilePropertyType.FLAGS_DIR.toString(), content.getDirFlagAsString());
map.put(AbstractFilePropertyType.FLAGS_META.toString(), content.getMetaFlagsAsString());
map.put(AbstractFilePropertyType.MODE.toString(), content.getModesAsString());
map.put(AbstractFilePropertyType.USER_ID.toString(), content.getUid());
map.put(AbstractFilePropertyType.GROUP_ID.toString(), content.getGid());
map.put(AbstractFilePropertyType.META_ADDR.toString(), content.getMetaAddr());
map.put(AbstractFilePropertyType.ATTR_ADDR.toString(), Long.toString(content.getAttrType().getValue()) + "-" + content.getAttributeId());
map.put(AbstractFilePropertyType.TYPE_DIR.toString(), content.getDirType().getLabel());
map.put(AbstractFilePropertyType.TYPE_META.toString(), content.getMetaType().toString());
map.put(AbstractFilePropertyType.KNOWN.toString(), content.getKnown().getName());
map.put(AbstractFilePropertyType.HASHSETS.toString(), getHashSetHitsForFile(content));
map.put(AbstractFilePropertyType.MD5HASH.toString(), content.getMd5Hash() == null ? "" : content.getMd5Hash());
map.put(AbstractFilePropertyType.ObjectID.toString(), content.getId());
map.put(AbstractFilePropertyType.MIMETYPE.toString(), content.getMIMEType() == null ? "" : content.getMIMEType());
static public void fillPropertyMap(Map<String, Object> map, AbstractFile content) {
map.put(NAME.toString(), getContentDisplayName(content));
map.put(LOCATION.toString(), getContentPath(content));
map.put(MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content));
map.put(CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content));
map.put(ACCESS_TIME.toString(), ContentUtils.getStringTime(content.getAtime(), content));
map.put(CREATED_TIME.toString(), ContentUtils.getStringTime(content.getCrtime(), content));
map.put(SIZE.toString(), content.getSize());
map.put(FLAGS_DIR.toString(), content.getDirFlagAsString());
map.put(FLAGS_META.toString(), content.getMetaFlagsAsString());
map.put(MODE.toString(), content.getModesAsString());
map.put(USER_ID.toString(), content.getUid());
map.put(GROUP_ID.toString(), content.getGid());
map.put(META_ADDR.toString(), content.getMetaAddr());
map.put(ATTR_ADDR.toString(), content.getAttrType().getValue() + "-" + content.getAttributeId());
map.put(TYPE_DIR.toString(), content.getDirType().getLabel());
map.put(TYPE_META.toString(), content.getMetaType().toString());
map.put(KNOWN.toString(), content.getKnown().getName());
map.put(HASHSETS.toString(), getHashSetHitsForFile(content));
map.put(MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash()));
map.put(ObjectID.toString(), content.getId());
map.put(MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType()));
map.put(EXTENSION.toString(), content.getNameExtension());
}
/**
* Used by subclasses of AbstractAbstractFileNode to add the tags property
* to their sheets.
* @param ss the modifiable Sheet.Set returned by Sheet.get(Sheet.PROPERTIES)
*
* @param ss the modifiable Sheet.Set returned by
* Sheet.get(Sheet.PROPERTIES)
*/
@NbBundle.Messages("AbstractAbstractFileNode.tagsProperty.displayName=Tags")
protected void addTagProperty(Sheet.Set ss) {
final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc");
List<ContentTag> tags;
List<ContentTag> tags = new ArrayList<>();
try {
tags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content);
tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content));
} catch (TskCoreException ex) {
tags = new ArrayList<>();
LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex);
logger.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex);
}
ss.put(new NodeProperty<>("Tags", AbstractAbstractFileNode_tagsProperty_displayName(),
NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName())
.distinct()
.collect(Collectors.joining(", "))));
}
private static String getContentPath(AbstractFile file) {
try {
return file.getUniquePath();
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Except while calling Content.getUniquePath() on " + file, ex); //NON-NLS
return ""; //NON-NLS
}
ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"),
NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", "))));
}
static String getContentDisplayName(AbstractFile file) {
@ -330,12 +259,11 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
}
}
@SuppressWarnings("deprecation")
private static String getHashSetHitsForFile(AbstractFile content) {
private static String getHashSetHitsForFile(AbstractFile file) {
try {
return StringUtils.join(content.getHashSetNames(), ", ");
return StringUtils.join(file.getHashSetNames(), ", ");
} catch (TskCoreException tskCoreException) {
LOGGER.log(Level.WARNING, "Error getting hashset hits: ", tskCoreException); //NON-NLS
logger.log(Level.WARNING, "Error getting hashset hits: ", tskCoreException); //NON-NLS
return "";
}
}

View File

@ -25,6 +25,7 @@ import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
import org.sleuthkit.autopsy.datamodel.accounts.Accounts.AccountsRootNode;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.Directory;
@ -32,6 +33,7 @@ import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.SleuthkitItemVisitor;
import org.sleuthkit.datamodel.SleuthkitVisitableItem;
@ -112,11 +114,21 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
return new VirtualDirectoryNode(ld);
}
@Override
public AbstractContentNode<? extends Content> visit(LocalDirectory ld) {
return new LocalDirectoryNode(ld);
}
@Override
public AbstractContentNode<? extends Content> visit(SlackFile sf) {
return new SlackFileNode(sf);
}
@Override
public AbstractContentNode<? extends Content> visit(BlackboardArtifact art) {
return new BlackboardArtifactNode(art);
}
@Override
protected AbstractContentNode<? extends Content> defaultVisit(SleuthkitVisitableItem di) {
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(),

View File

@ -21,8 +21,8 @@ package org.sleuthkit.autopsy.datamodel;
import java.util.List;
import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
@ -48,8 +48,18 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
* @param content Underlying Content instances
*/
AbstractContentNode(T content) {
this(content, Lookups.singleton(content) );
}
/**
* Handles aspects that depend on the Content object
*
* @param content Underlying Content instances
* @param lookup The Lookup object for the node.
*/
AbstractContentNode(T content, Lookup lookup) {
//TODO consider child factory for the content children
super(new ContentChildren(content), Lookups.singleton(content));
super(new ContentChildren(content), lookup);
this.content = content;
//super.setName(ContentUtils.getSystemName(content));
super.setName("content_" + Long.toString(content.getId())); //NON-NLS
@ -66,8 +76,7 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
@Override
public void setName(String name) {
throw new UnsupportedOperationException(
NbBundle.getMessage(this.getClass(), "AbstractContentNode.exception.cannotChangeSysName.msg"));
super.setName(name);
}
@Override

View File

@ -69,14 +69,11 @@ public abstract class AbstractFsContentNode<T extends AbstractFile> extends Abst
s.put(ss);
}
Map<String, Object> map = new LinkedHashMap<String, Object>();
AbstractAbstractFileNode.fillPropertyMap(map, content);
Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, getContent());
AbstractFilePropertyType[] fsTypes = AbstractFilePropertyType.values();
final int FS_PROPS_LEN = fsTypes.length;
final String NO_DESCR = NbBundle.getMessage(this.getClass(), "AbstractFsContentNode.noDesc.text");
for (int i = 0; i < FS_PROPS_LEN; ++i) {
final AbstractFilePropertyType propType = AbstractFilePropertyType.values()[i];
for (AbstractFilePropertyType propType : AbstractFilePropertyType.values()) {
final String propString = propType.toString();
ss.put(new NodeProperty<>(propString, propString, NO_DESCR, map.get(propString)));
}

View File

@ -25,6 +25,7 @@ import java.beans.PropertyChangeListener;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -34,6 +35,7 @@ import java.util.logging.Level;
import java.util.stream.Collectors;
import javax.swing.Action;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
@ -43,9 +45,11 @@ import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import static org.sleuthkit.autopsy.datamodel.DataModelActionsFactory.VIEW_IN_NEW_WINDOW;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
import org.sleuthkit.datamodel.AbstractFile;
@ -61,7 +65,7 @@ import org.sleuthkit.datamodel.TskCoreException;
* Node wrapping a blackboard artifact object. This is generated from several
* places in the tree.
*/
public class BlackboardArtifactNode extends DisplayableItemNode {
public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifact> {
private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName());
@ -70,8 +74,9 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
build();
private final BlackboardArtifact artifact;
private final Content associated;
private Content associated = null;
private List<NodeProperty<? extends Object>> customProperties;
/*
* Artifact types which should have the full unique path of the associated
* content as a property.
@ -130,11 +135,18 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
* @param iconPath icon to use for the artifact
*/
public BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath) {
super(Children.LEAF, createLookup(artifact));
super(artifact, createLookup(artifact));
this.artifact = artifact;
//this.associated = getAssociatedContent(artifact);
this.associated = this.getLookup().lookup(Content.class);
// Look for associated Content i.e. the source file for the artifact
for (Content content : this.getLookup().lookupAll(Content.class)) {
if ( (content != null) && (!(content instanceof BlackboardArtifact)) ){
this.associated = content;
break;
}
}
this.setName(Long.toString(artifact.getArtifactID()));
this.setDisplayName();
this.setIconBaseWithExtension(iconPath);
@ -148,20 +160,18 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
* @param artifact artifact to encapsulate
*/
public BlackboardArtifactNode(BlackboardArtifact artifact) {
super(Children.LEAF, createLookup(artifact));
this.artifact = artifact;
this.associated = this.getLookup().lookup(Content.class);
this.setName(Long.toString(artifact.getArtifactID()));
this.setDisplayName();
this.setIconBaseWithExtension(ExtractedContent.getIconFilePath(artifact.getArtifactTypeID())); //NON-NLS
Case.addPropertyChangeListener(pcl);
this(artifact, ExtractedContent.getIconFilePath(artifact.getArtifactTypeID()));
}
private void removeListeners() {
Case.removePropertyChangeListener(pcl);
}
public BlackboardArtifact getArtifact() {
return this.artifact;
}
@Override
@NbBundle.Messages({
"BlackboardArtifactNode.getAction.errorTitle=Error getting actions",
@ -211,9 +221,6 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
*/
private void setDisplayName() {
String displayName = ""; //NON-NLS
if (associated != null) {
displayName = associated.getName();
}
// If this is a node for a keyword hit on an artifact, we set the
// display name to be the artifact type name followed by " Artifact"
@ -238,9 +245,30 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
// Do nothing since the display name will be set to the file name.
}
}
this.setDisplayName(displayName);
if (displayName.isEmpty() && artifact != null) {
displayName = artifact.getName();
}
this.setDisplayName(displayName);
}
/**
* Return the name of the associated source file/content
*
* @return source file/content name
*/
public String getSrcName() {
String srcName = "";
if (associated != null) {
srcName = associated.getName();
}
return srcName;
}
@NbBundle.Messages({
"BlackboardArtifactNode.createSheet.artifactType.displayName=Artifact Type",
"BlackboardArtifactNode.createSheet.artifactType.name=Artifact Type",
@ -264,7 +292,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"),
NO_DESCR,
this.getDisplayName()));
this.getSrcName()));
if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
try {
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
@ -555,4 +583,9 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
public String getItemType() {
return getClass().getName();
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
}
}

View File

@ -1,24 +1,4 @@
OpenIDE-Module-Name=DataModel
AbstractAbstractFileNode.nameColLbl=Name
AbstractAbstractFileNode.locationColLbl=Location
AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time
AbstractAbstractFileNode.changeTimeColLbl=Change Time
AbstractAbstractFileNode.accessTimeColLbl=Access Time
AbstractAbstractFileNode.createdTimeColLbl=Created Time
AbstractAbstractFileNode.sizeColLbl=Size
AbstractAbstractFileNode.flagsDirColLbl=Flags(Dir)
AbstractAbstractFileNode.flagsMetaColLbl=Flags(Meta)
AbstractAbstractFileNode.modeColLbl=Mode
AbstractAbstractFileNode.useridColLbl=UserID
AbstractAbstractFileNode.groupidColLbl=GroupID
AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.
AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.
AbstractAbstractFileNode.typeDirColLbl=Type(Dir)
AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)
AbstractAbstractFileNode.knownColLbl=Known
AbstractAbstractFileNode.inHashsetsColLbl=In Hashsets
AbstractAbstractFileNode.md5HashColLbl=MD5 Hash
AbstractAbstractFileNode.mimeType = MIME Type
AbstractContentChildren.CreateTSKNodeVisitor.exception.noNodeMsg=No Node defined for the given SleuthkitItem
AbstractContentChildren.createAutopsyNodeVisitor.exception.noNodeMsg=No Node defined for the given DisplayableItem
AbstractContentNode.exception.cannotChangeSysName.msg=Cannot change the system name.
@ -80,17 +60,6 @@ DataSourcesNode.name=Data Sources
DataSourcesNode.createSheet.name.name=Name
DataSourcesNode.createSheet.name.displayName=Name
DataSourcesNode.createSheet.name.desc=no description
DeletedContent.fsDelFilter.text=File System
DeletedContent.allDelFilter.text=All
DeletedContent.deletedContentsNode.name=Deleted Files
DeletedContent.createSheet.name.name=Name
DeletedContent.createSheet.name.displayName=Name
DeletedContent.createSheet.name.desc=no description
DeletedContent.createSheet.filterType.name=Type
DeletedContent.createSheet.filterType.displayName=Type
DeletedContent.createSheet.filterType.desc=no description
DeletedContent.createKeys.maxObjects.msg=There are more Deleted Files than can be displayed. Only the first {0} Deleted Files will be shown.
DeletedContent.createNodeForKey.typeNotSupported.msg=Not supported for this type of Displayable Item\: {0}
DirectoryNode.parFolder.text=[parent folder]
DirectoryNode.curFolder.text=[current folder]
DirectoryNode.getActions.viewFileInDir.text=View File in Directory
@ -233,16 +202,12 @@ VolumeNode.createSheet.description.desc=no description
VolumeNode.createSheet.flags.name=Flags
VolumeNode.createSheet.flags.displayName=Flags
VolumeNode.createSheet.flags.desc=no description
AbstractAbstractFileNode.objectId=Object ID
ArtifactStringContent.getStr.artifactId.text=Artifact ID
DeleteReportAction.actionDisplayName.singleReport=Delete Report
DeleteReportAction.actionDisplayName.multipleReports=Delete Reports
DeleteReportAction.actionPerformed.showConfirmDialog.title=Confirm Deletion
DeleteReportAction.actionPerformed.showConfirmDialog.single.msg=Do you want to delete 1 report from the case?
DeleteReportAction.actionPerformed.showConfirmDialog.multiple.msg=Do you want to delete {0} reports from the case?
AbstractAbstractFileNode.addFileProperty.desc=no description
AbstractAbstractFileNode.addFileProperty.tags.name=Tags
AbstractAbstractFileNode.addFileProperty.tags.displayName=Tags
BlackboardArtifactNode.createSheet.tags.name=Tags
BlackboardArtifactNode.createSheet.tags.displayName=Tags
FileTypeExtensionFilters.tskImgFilter.text=Images

View File

@ -32,6 +32,8 @@ interface ContentNodeVisitor<T> {
T visit(VirtualDirectoryNode lcn);
T visit(LocalDirectoryNode ldn);
T visit(VolumeNode vn);
T visit(DirectoryNode dn);
@ -44,6 +46,9 @@ interface ContentNodeVisitor<T> {
T visit(SlackFileNode sfn);
T visit(BlackboardArtifactNode bban);
/**
* Visitor with an implementable default behavior for all types. Override
* specific visit types to not use the default behavior.
@ -96,9 +101,19 @@ interface ContentNodeVisitor<T> {
return defaultVisit(ldn);
}
@Override
public T visit(LocalDirectoryNode ldn) {
return defaultVisit(ldn);
}
@Override
public T visit(SlackFileNode sfn) {
return defaultVisit(sfn);
}
@Override
public T visit(BlackboardArtifactNode bban) {
return defaultVisit(bban);
}
}
}

View File

@ -42,6 +42,7 @@ import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.TskException;
@ -379,6 +380,11 @@ public final class ContentUtils {
return visitDir(dir);
}
@Override
public Void visit(LocalDirectory dir) {
return visitDir(dir);
}
private java.io.File getFsContentDest(Content fsc) {
String path = dest.getAbsolutePath() + java.io.File.separator
+ fsc.getName();

View File

@ -44,6 +44,7 @@ import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.VirtualDirectory;
@ -230,6 +231,38 @@ public class DataModelActionsFactory {
return actionsList;
}
public static List<Action> getActions(LocalDirectory directory, boolean isArtifactSource) {
List<Action> actionsList = new ArrayList<>();
actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), directory));
LocalDirectoryNode directoryNode = new LocalDirectoryNode(directory);
actionsList.add(null); // creates a menu separator
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode));
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode));
actionsList.add(null); // creates a menu separator
actionsList.add(ExtractAction.getInstance());
actionsList.add(null); // creates a menu separator
actionsList.add(AddContentTagAction.getInstance());
if (isArtifactSource) {
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
}
final Collection<AbstractFile> selectedFilesList =
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
if(selectedFilesList.size() == 1) {
actionsList.add(DeleteFileContentTagAction.getInstance());
}
if(isArtifactSource) {
final Collection<BlackboardArtifact> selectedArtifactsList =
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
if(selectedArtifactsList.size() == 1) {
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
}
}
actionsList.addAll(ContextMenuExtensionPoint.getActions());
return actionsList;
}
public static List<Action> getActions(LocalFile file, boolean isArtifactSource) {
List<Action> actionsList = new ArrayList<>();
actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file));

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2017 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -39,6 +39,7 @@ import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datamodel.Bundle.*;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
@ -58,14 +59,15 @@ public class DeletedContent implements AutopsyVisitableItem {
private SleuthkitCase skCase;
@NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System",
"DeletedContent.allDelFilter.text=All"})
public enum DeletedContentFilter implements AutopsyVisitableItem {
FS_DELETED_FILTER(0,
"FS_DELETED_FILTER", //NON-NLS
NbBundle.getMessage(DeletedContent.class, "DeletedContent.fsDelFilter.text")),
ALL_DELETED_FILTER(1,
"ALL_DELETED_FILTER", //NON-NLS
NbBundle.getMessage(DeletedContent.class, "DeletedContent.allDelFilter.text"));
FS_DELETED_FILTER(0, "FS_DELETED_FILTER", //NON-NLS
Bundle.DeletedContent_fsDelFilter_text()),
ALL_DELETED_FILTER(1, "ALL_DELETED_FILTER", //NON-NLS
Bundle.DeletedContent_allDelFilter_text());
private int id;
private String name;
private String displayName;
@ -110,15 +112,13 @@ public class DeletedContent implements AutopsyVisitableItem {
public static class DeletedContentsNode extends DisplayableItemNode {
private static final String NAME = NbBundle.getMessage(DeletedContent.class,
"DeletedContent.deletedContentsNode.name");
private SleuthkitCase skCase;
@NbBundle.Messages("DeletedContent.deletedContentsNode.name=Deleted Files")
private static final String NAME = Bundle.DeletedContent_deletedContentsNode_name();
DeletedContentsNode(SleuthkitCase skCase) {
super(Children.create(new DeletedContentsChildren(skCase), true), Lookups.singleton(NAME));
super.setName(NAME);
super.setDisplayName(NAME);
this.skCase = skCase;
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
}
@ -133,6 +133,9 @@ public class DeletedContent implements AutopsyVisitableItem {
}
@Override
@NbBundle.Messages({
"DeletedContent.createSheet.name.displayName=Name",
"DeletedContent.createSheet.name.desc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
@ -141,9 +144,9 @@ public class DeletedContent implements AutopsyVisitableItem {
s.put(ss);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.name.desc"),
ss.put(new NodeProperty<>("Name", //NON-NLS
Bundle.DeletedContent_createSheet_name_displayName(),
Bundle.DeletedContent_createSheet_name_desc(),
NAME));
return s;
}
@ -303,6 +306,9 @@ public class DeletedContent implements AutopsyVisitableItem {
}
@Override
@NbBundle.Messages({
"DeletedContent.createSheet.filterType.displayName=Type",
"DeletedContent.createSheet.filterType.desc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
@ -311,10 +317,9 @@ public class DeletedContent implements AutopsyVisitableItem {
s.put(ss);
}
ss.put(new NodeProperty<>(
NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.filterType.name"),
NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.filterType.displayName"),
NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.filterType.desc"),
ss.put(new NodeProperty<>("Type", //NON_NLS
Bundle.DeletedContent_createSheet_filterType_displayName(),
Bundle.DeletedContent_createSheet_filterType_desc(),
filter.getDisplayName()));
return s;
@ -375,6 +380,10 @@ public class DeletedContent implements AutopsyVisitableItem {
}
@Override
@NbBundle.Messages({"# {0} - The deleted files threshold",
"DeletedContent.createKeys.maxObjects.msg="
+ "There are more Deleted Files than can be displayed."
+ " Only the first {0} Deleted Files will be shown."})
protected boolean createKeys(List<AbstractFile> list) {
List<AbstractFile> queryList = runFsQuery();
if (queryList.size() == MAX_OBJECTS) {
@ -382,14 +391,10 @@ public class DeletedContent implements AutopsyVisitableItem {
// only show the dialog once - not each time we refresh
if (maxFilesDialogShown == false) {
maxFilesDialogShown = true;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), NbBundle.getMessage(this.getClass(),
"DeletedContent.createKeys.maxObjects.msg",
MAX_OBJECTS - 1));
}
});
SwingUtilities.invokeLater(()
-> JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
DeletedContent_createKeys_maxObjects_msg(MAX_OBJECTS - 1))
);
}
}
list.addAll(queryList);
@ -429,13 +434,12 @@ public class DeletedContent implements AutopsyVisitableItem {
}
if(UserPreferences.hideKnownFilesInViewsTree()) {
if (UserPreferences.hideKnownFilesInViewsTree()) {
query += " AND (known != " + TskData.FileKnown.KNOWN.getFileKnownValue() //NON-NLS
+ " OR known IS NULL)"; //NON-NLS
}
query += " LIMIT " + MAX_OBJECTS; //NON-NLS
return query;
}
@ -456,6 +460,9 @@ public class DeletedContent implements AutopsyVisitableItem {
/**
* Get children count without actually loading all nodes
*
* @param sleuthkitCase
* @param filter
*
* @return
*/
static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter) {
@ -495,9 +502,7 @@ public class DeletedContent implements AutopsyVisitableItem {
@Override
protected AbstractNode defaultVisit(Content di) {
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(),
"DeletedContent.createNodeForKey.typeNotSupported.msg",
di.toString()));
throw new UnsupportedOperationException("Not supported for this type of Displayable Item: " + di.toString());
}
});
}

View File

@ -42,6 +42,8 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(VirtualDirectoryNode ldn);
T visit(LocalDirectoryNode ldn);
T visit(DirectoryNode dn);
T visit(FileNode fn);
@ -370,6 +372,11 @@ public interface DisplayableItemNodeVisitor<T> {
return defaultVisit(ldn);
}
@Override
public T visit(LocalDirectoryNode ldn) {
return defaultVisit(ldn);
}
@Override
public T visit(Tags.RootNode node) {
return defaultVisit(node);

View File

@ -428,7 +428,7 @@ public class EmailExtracted implements AutopsyVisitableItem {
@Override
public boolean isLeafTypeNode() {
return true;
return false;
}
@Override

View File

@ -353,29 +353,14 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
throw new IllegalArgumentException("Empty filter list passed to createQuery()"); // NON-NLS
}
String query = "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
+ (UserPreferences.hideKnownFilesInViewsTree() ? " AND (known IS NULL OR known != "
+ TskData.FileKnown.KNOWN.getFileKnownValue() + ")" : " ")
+ " AND (NULL "; //NON-NLS
if (skCase.getDatabaseType().equals(TskData.DbType.POSTGRESQL)) {
// For PostgreSQL we get a more efficient query by using builtin
// regular expression support and or'ing all extensions. We also
// escape the dot at the beginning of the extension.
// We will end up with a query that looks something like this:
// OR LOWER(name) ~ '(\.zip|\.rar|\.7zip|\.cab|\.jar|\.cpio|\.ar|\.gz|\.tgz|\.bz2)$')
query += "OR LOWER(name) ~ '(\\";
query += StringUtils.join(filter.getFilter().stream()
.map(String::toLowerCase).collect(Collectors.toList()), "|\\");
query += ")$'";
} else {
for (String s : filter.getFilter()) {
query += "OR LOWER(name) LIKE '%" + s.toLowerCase() + "'"; // NON-NLS
}
}
query += ')';
return query;
return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
+ (UserPreferences.hideKnownFilesInViewsTree()
? " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")"
: " ")
+ " AND (extension IN (" + filter.getFilter().stream()
.map(String::toLowerCase)
.map(s -> "'"+StringUtils.substringAfter(s, ".")+"'")
.collect(Collectors.joining(", ")) + "))";
}
/**

View File

@ -79,7 +79,7 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
}
Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, content);
fillPropertyMap(map);
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.name.displayName"),
@ -134,11 +134,12 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
}
actionsList.addAll(ContextMenuExtensionPoint.getActions());
return actionsList.toArray(new Action[0]);
return actionsList.toArray(new Action[actionsList.size()]);
}
private static void fillPropertyMap(Map<String, Object> map, LayoutFile content) {
AbstractAbstractFileNode.fillPropertyMap(map, content);
void fillPropertyMap(Map<String, Object> map) {
AbstractAbstractFileNode.fillPropertyMap(map, getContent());
map.put(LayoutContentPropertyType.PARTS.toString(), content.getNumParts());
}

View File

@ -0,0 +1,86 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.datamodel;
import java.util.LinkedHashMap;
import java.util.Map;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.sleuthkit.datamodel.LocalDirectory;
/**
* Node for a local directory
*/
public class LocalDirectoryNode extends SpecialDirectoryNode {
public static String nameForLocalDir(LocalDirectory ld) {
return ld.getName();
}
public LocalDirectoryNode(LocalDirectory ld) {
super(ld);
this.setDisplayName(nameForLocalDir(ld));
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/Folder-icon.png"); //NON-NLS
}
@Override
@NbBundle.Messages({
"LocalDirectoryNode.createSheet.name.name=Name",
"LocalDirectoryNode.createSheet.name.displayName=Name",
"LocalDirectoryNode.createSheet.name.desc=no description",
"LocalDirectoryNode.createSheet.noDesc=no description"})
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
}
ss.put(new NodeProperty<>(Bundle.LocalDirectoryNode_createSheet_name_name(),
Bundle.LocalDirectoryNode_createSheet_name_displayName(),
Bundle.LocalDirectoryNode_createSheet_name_desc(),
getName()));
// At present, a LocalDirectory will never be a datasource - the top level of a logical
// file set is a VirtualDirectory
Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, getContent());
final String NO_DESCR = Bundle.LocalDirectoryNode_createSheet_noDesc();
for (Map.Entry<String, Object> entry : map.entrySet()) {
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
}
addTagProperty(ss);
return s;
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
}
}

View File

@ -71,7 +71,7 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
}
Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, content);
fillPropertyMap(map, getContent());
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "LocalFileNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "LocalFileNode.createSheet.name.displayName"),

View File

@ -0,0 +1,82 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.datamodel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.Action;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.directorytree.ExtractAction;
import org.sleuthkit.autopsy.directorytree.FileSearchAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SpecialDirectory;
/**
* Parent class for special directory types (Local and Virtual)
*/
public abstract class SpecialDirectoryNode extends AbstractAbstractFileNode<SpecialDirectory> {
public SpecialDirectoryNode(SpecialDirectory sd) {
super(sd);
}
/**
* Right click action for this node
*
* @param popup
*
* @return
*/
@Override
@NbBundle.Messages({"SpecialDirectoryNode.action.runIngestMods.text=Run Ingest Modules",
"SpecialDirectoryNode.getActions.viewInNewWin.text=View in New Window"
})
public Action[] getActions(boolean popup) {
List<Action> actions = new ArrayList<>();
for (Action a : super.getActions(true)) {
actions.add(a);
}
actions.add(new NewWindowViewAction(
Bundle.SpecialDirectoryNode_action_runIngestMods_text(), this));
actions.add(null); // creates a menu separator
actions.add(ExtractAction.getInstance());
actions.add(null); // creates a menu separator
actions.add(new FileSearchAction(
Bundle.ImageNode_getActions_openFileSearchByAttr_text()));
actions.add(new RunIngestModulesAction(Collections.<Content>singletonList(content)));
actions.addAll(ContextMenuExtensionPoint.getActions());
return actions.toArray(new Action[0]);
}
@Override
public boolean isLeafTypeNode() {
return false;
}
@Override
public String getItemType() {
// use content.isDataSource if different column settings are desired
return DisplayableItemNode.FILE_PARENT_NODE_KEY;
}
}

View File

@ -20,91 +20,47 @@ package org.sleuthkit.autopsy.datamodel;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.swing.Action;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.directorytree.ExtractAction;
import org.sleuthkit.autopsy.directorytree.FileSearchAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.VirtualDirectory;
/**
* Node for layout dir
* Node for a virtual directory
*/
public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirectory> {
public class VirtualDirectoryNode extends SpecialDirectoryNode {
private static final Logger logger = Logger.getLogger(VirtualDirectoryNode.class.getName());
//prefix for special VirtualDirectory root nodes grouping local files
public final static String LOGICAL_FILE_SET_PREFIX = "LogicalFileSet"; //NON-NLS
public static String nameForLayoutFile(VirtualDirectory ld) {
public static String nameForVirtualDirectory(VirtualDirectory ld) {
return ld.getName();
}
public VirtualDirectoryNode(VirtualDirectory ld) {
super(ld);
this.setDisplayName(nameForLayoutFile(ld));
this.setDisplayName(nameForVirtualDirectory(ld));
String name = ld.getName();
//set icon for name, special case for some built-ins
if (name.equals(VirtualDirectory.NAME_UNALLOC)) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-deleted.png"); //NON-NLS
} else if (ld.isDataSource()) {
//set icon for name, special case for logical file set
if (ld.isDataSource()) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS
} else if (name.equals(VirtualDirectory.NAME_CARVED)) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/Folder-icon.png"); //TODO NON-NLS
} else {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/Folder-icon.png"); //NON-NLS
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-virtual.png"); //TODO NON-NLS
}
}
/**
* Right click action for this node
*
* @param popup
*
* @return
*/
@Override
@NbBundle.Messages({"VirtualDirectoryNode.action.runIngestMods.text=Run Ingest Modules"})
public Action[] getActions(boolean popup) {
List<Action> actions = new ArrayList<>();
for (Action a : super.getActions(true)) {
actions.add(a);
}
actions.add(new NewWindowViewAction(
NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.getActions.viewInNewWin.text"), this));
actions.add(null); // creates a menu separator
actions.add(ExtractAction.getInstance());
actions.add(null); // creates a menu separator
actions.add(new FileSearchAction(
Bundle.ImageNode_getActions_openFileSearchByAttr_text()));
actions.add(new RunIngestModulesAction(Collections.<Content>singletonList(content)));
actions.addAll(ContextMenuExtensionPoint.getActions());
return actions.toArray(new Action[0]);
}
@Override
@Messages({"VirtualDirectoryNode.createSheet.size.name=Size (Bytes)",
@NbBundle.Messages({"VirtualDirectoryNode.createSheet.size.name=Size (Bytes)",
"VirtualDirectoryNode.createSheet.size.displayName=Size (Bytes)",
"VirtualDirectoryNode.createSheet.size.desc=Size of the data source in bytes.",
"VirtualDirectoryNode.createSheet.type.name=Type",
@ -133,7 +89,7 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
if (!this.content.isDataSource()) {
Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, content);
fillPropertyMap(map, getContent());
final String NO_DESCR = NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.noDesc");
for (Map.Entry<String, Object> entry : map.entrySet()) {
@ -186,39 +142,4 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
}
@Override
public boolean isLeafTypeNode() {
return false;
}
/**
* Convert meta flag long to user-readable string / label
*
* @param metaFlag to convert
*
* @return string formatted meta flag representation
*/
public static String metaFlagToString(short metaFlag) {
String result = "";
short allocFlag = TskData.TSK_FS_META_FLAG_ENUM.ALLOC.getValue();
short unallocFlag = TskData.TSK_FS_META_FLAG_ENUM.UNALLOC.getValue();
if ((metaFlag & allocFlag) == allocFlag) {
result = TskData.TSK_FS_META_FLAG_ENUM.ALLOC.toString();
}
if ((metaFlag & unallocFlag) == unallocFlag) {
result = TskData.TSK_FS_META_FLAG_ENUM.UNALLOC.toString();
}
return result;
}
@Override
public String getItemType() {
// use content.isDataSource if different column settings are desired
return DisplayableItemNode.FILE_PARENT_NODE_KEY;
}
}

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.directorytree;
import java.awt.event.ActionEvent;
import java.beans.PropertyVetoException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@ -43,6 +44,7 @@ import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
@ -53,10 +55,12 @@ import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
import org.sleuthkit.autopsy.datamodel.LocalDirectoryNode;
import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo;
import org.sleuthkit.autopsy.datamodel.Reports;
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import static org.sleuthkit.autopsy.directorytree.Bundle.*;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
@ -66,11 +70,13 @@ import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.VirtualDirectory;
import static org.sleuthkit.autopsy.directorytree.Bundle.*;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A node used to wrap another node before passing it to the result viewers. The
@ -210,6 +216,26 @@ public class DataResultFilterNode extends FilterNode {
return propertySets;
}
/**
* Gets the display name for the wrapped node.
*
* OutlineView used in the DataResult table uses getDisplayName() to populate
* the first column, which is Source File.
*
* Hence this override to return the 'correct' displayName for the wrapped node.
*
* @return The display name for the node.
*/
@Override
public String getDisplayName() {
final Node orig = getOriginal();
String name = orig.getDisplayName();
if ((orig instanceof BlackboardArtifactNode)) {
name = ((BlackboardArtifactNode) orig).getSrcName();
}
return name;
}
/**
* Adds information about which child node of this node, if any, should be
* selected. Can be null.
@ -248,16 +274,20 @@ public class DataResultFilterNode extends FilterNode {
private boolean filterKnown;
private boolean filterSlack;
private boolean filterArtifacts; // display message artifacts in the DataSource subtree
/**
* the constructor
*/
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
super(arg);
this.filterArtifacts = false;
switch (SelectionContext.getSelectionContext(arg)) {
case DATA_SOURCES:
filterSlack = filterSlackFromDataSources;
filterKnown = filterKnownFromDataSources;
filterArtifacts = true;
break;
case VIEWS:
filterSlack = filterSlackFromViews;
@ -291,6 +321,16 @@ public class DataResultFilterNode extends FilterNode {
return new Node[]{};
}
}
// filter out all non-message artifacts, if displaying the results from the Data Source tree
BlackboardArtifact art = key.getLookup().lookup(BlackboardArtifact.class);
if (art != null && filterArtifacts) {
if ( (art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) &&
(art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) ) {
return new Node[]{};
}
}
return new Node[]{new DataResultFilterNode(key, sourceEm, filterKnown, filterSlack)};
}
}
@ -350,6 +390,8 @@ public class DataResultFilterNode extends FilterNode {
n = new DirectoryNode((Directory) c);
} else if ((c = ban.getLookup().lookup(VirtualDirectory.class)) != null) {
n = new VirtualDirectoryNode((VirtualDirectory) c);
} else if ((c = ban.getLookup().lookup(LocalDirectory.class)) != null) {
n = new LocalDirectoryNode((LocalDirectory) c);
} else if ((c = ban.getLookup().lookup(LayoutFile.class)) != null) {
n = new LayoutFileNode((LayoutFile) c);
} else if ((c = ban.getLookup().lookup(LocalFile.class)) != null
@ -459,6 +501,18 @@ public class DataResultFilterNode extends FilterNode {
@Override
public AbstractAction visit(BlackboardArtifactNode ban) {
BlackboardArtifact artifact = ban.getArtifact();
try {
if ( (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) ||
(artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) ) {
if (artifact.hasChildren()) {
return openChild(ban);
}
}
}
catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting children from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
}
return new ViewContextAction(
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInDir.text"), ban);
}

View File

@ -26,16 +26,19 @@ import org.sleuthkit.autopsy.datamodel.DirectoryNode;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
import org.sleuthkit.autopsy.datamodel.LocalDirectoryNode;
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import org.sleuthkit.autopsy.datamodel.VolumeNode;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.LayoutFile;
@ -198,7 +201,7 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
List<Content> derivedChildren = node.getContentChildren();
//child of a file, must be a (derived) file too
for (Content childContent : derivedChildren) {
if (((AbstractFile) childContent).isDir()) {
if ((childContent instanceof AbstractFile) && ((AbstractFile) childContent).isDir()) {
return false;
} else {
try {
@ -244,11 +247,26 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
//return ! vdn.hasContentChildren();
}
@Override
public Boolean visit(LocalDirectoryNode ldn) {
return visitDeep(ldn);
}
@Override
public Boolean visit(FileTypesNode ft) {
return defaultVisit(ft);
}
@Override
public Boolean visit(BlackboardArtifactNode bbafn) {
// Only show Message arttifacts with children
if ( (bbafn.getArtifact().getArtifactTypeID() == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) ||
(bbafn.getArtifact().getArtifactTypeID() == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) ) {
return bbafn.hasContentChildren();
}
return false;
}
}
private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default<Boolean> {
@ -292,10 +310,28 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
//return vdn.hasContentChildren();
}
@Override
public Boolean visit(LocalDirectoryNode ldn) {
return true;
}
@Override
public Boolean visit(FileTypesNode fileTypes) {
return defaultVisit(fileTypes);
}
@Override
public Boolean visit(BlackboardArtifactNode bbafn) {
// Only show Message arttifacts with children
if ( (bbafn.getArtifact().getArtifactTypeID() == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) ||
(bbafn.getArtifact().getArtifactTypeID() == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) ) {
return bbafn.hasContentChildren();
}
return false;
}
}
}

View File

@ -25,14 +25,17 @@ import java.util.logging.Level;
import javax.swing.Action;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.AbstractContentNode;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.Image;
@ -77,7 +80,7 @@ class DirectoryTreeFilterNode extends FilterNode {
String name = orig.getDisplayName();
if (orig instanceof AbstractContentNode) {
AbstractFile file = getLookup().lookup(AbstractFile.class);
if (file != null) {
if ((file != null) && (false == (orig instanceof BlackboardArtifactNode)) ){
try {
int numVisibleChildren = getVisibleChildCount(file);
@ -92,6 +95,15 @@ class DirectoryTreeFilterNode extends FilterNode {
logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex); //NON-NLS
}
}
else if (orig instanceof BlackboardArtifactNode) {
BlackboardArtifact artifact = ((BlackboardArtifactNode) orig).getArtifact();
try {
int numAttachments = artifact.getChildrenCount();
name = name + " \u200E(\u200E" + numAttachments + ")\u200E"; //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting chidlren count for atifact: " + artifact, ex); //NON-NLS
}
}
}
return name;
}
@ -115,13 +127,17 @@ class DirectoryTreeFilterNode extends FilterNode {
if (purgeKnownFiles || purgeSlackFiles) {
// Purge known and/or slack files from the file count
for (int i = 0; i < childList.size(); i++) {
AbstractFile childFile = (AbstractFile) childList.get(i);
Content child = childList.get(i);
if (child instanceof AbstractFile) {
AbstractFile childFile = (AbstractFile) child;
if ((purgeKnownFiles && childFile.getKnown() == TskData.FileKnown.KNOWN)
|| (purgeSlackFiles && childFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
numVisibleChildren--;
}
}
}
}
return numVisibleChildren;
}

View File

@ -38,6 +38,7 @@ import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.FileSystem;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.VirtualDirectory;
import org.sleuthkit.datamodel.Volume;
@ -120,6 +121,23 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
return actionsList;
}
@Override
public List<? extends Action> visit(final LocalDirectory d) {
List<Action> actionsList = new ArrayList<>();
if (!d.isDataSource()) {
actionsList.add(AddContentTagAction.getInstance());
final Collection<AbstractFile> selectedFilesList =
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
if(selectedFilesList.size() == 1) {
actionsList.add(DeleteFileContentTagAction.getInstance());
}
}
actionsList.add(ExtractAction.getInstance());
actionsList.addAll(ContextMenuExtensionPoint.getActions());
return actionsList;
}
@Override
public List<? extends Action> visit(final DerivedFile d) {
List<Action> actionsList = new ArrayList<>();

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

View File

@ -28,6 +28,7 @@ import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.VirtualDirectory;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.Volume;
import org.sleuthkit.datamodel.VolumeSystem;
@ -44,6 +45,11 @@ abstract class GetFilesContentVisitor implements ContentVisitor<Collection<Abstr
return getAllFromChildren(ld);
}
@Override
public Collection<AbstractFile> visit(LocalDirectory ld) {
return getAllFromChildren(ld);
}
@Override
public Collection<AbstractFile> visit(Directory drctr) {
return getAllFromChildren(drctr);

View File

@ -21,12 +21,14 @@ package org.sleuthkit.autopsy.ingest;
import java.util.ArrayList;
import java.util.Collection;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.FileSystem;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.VirtualDirectory;
@ -38,13 +40,21 @@ final class GetRootDirectoryVisitor extends GetFilesContentVisitor {
@Override
public Collection<AbstractFile> visit(VirtualDirectory ld) {
//case when we hit a layout directoryor local file container, not under a real FS
//case when we hit a layout directory or local file container, not under a real FS
//or when root virt dir is scheduled
Collection<AbstractFile> ret = new ArrayList<>();
ret.add(ld);
return ret;
}
@Override
public Collection<AbstractFile> visit(LocalDirectory ld) {
//case when we hit a local directory
Collection<AbstractFile> ret = new ArrayList<>();
ret.add(ld);
return ret;
}
@Override
public Collection<AbstractFile> visit(LayoutFile lf) {
//case when we hit a layout file, not under a real FS
@ -93,4 +103,8 @@ final class GetRootDirectoryVisitor extends GetFilesContentVisitor {
return getAllFromChildren(slackFile);
}
@Override
public Collection<AbstractFile> visit(BlackboardArtifact art) {
return getAllFromChildren(art);
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -39,7 +39,7 @@ class AutoIngestCase implements Comparable<AutoIngestCase> {
private final String caseName;
private final Path metadataFilePath;
private final Date createDate;
private Date lastModfiedDate;
private final Date lastAccessedDate;
/**
* Constructs a representation of case created by automated ingest.
@ -58,10 +58,10 @@ class AutoIngestCase implements Comparable<AutoIngestCase> {
}
if (null != fileAttrs) {
createDate = new Date(fileAttrs.creationTime().toMillis());
lastModfiedDate = new Date(fileAttrs.lastModifiedTime().toMillis());
lastAccessedDate = new Date(fileAttrs.lastAccessTime().toMillis());
} else {
createDate = new Date();
lastModfiedDate = new Date();
lastAccessedDate = new Date();
}
}
@ -94,19 +94,13 @@ class AutoIngestCase implements Comparable<AutoIngestCase> {
}
/**
* Gets the last accessed date for the case, defined as the last modified
* Gets the last accessed date for the case, defined as the last accessed
* time of the case metadata file.
*
* @return The last accessed date.
*/
Date getLastAccessedDate() {
try {
BasicFileAttributes fileAttrs = Files.readAttributes(metadataFilePath, BasicFileAttributes.class);
lastModfiedDate = new Date(fileAttrs.lastModifiedTime().toMillis());
} catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error reading file attributes of case metadata file in %s, lastModfiedDate time not updated", caseDirectoryPath), ex);
}
return lastModfiedDate;
return this.lastAccessedDate;
}
/**
@ -162,7 +156,7 @@ class AutoIngestCase implements Comparable<AutoIngestCase> {
*/
@Override
public int compareTo(AutoIngestCase other) {
return -this.lastModfiedDate.compareTo(other.getLastAccessedDate());
return -this.lastAccessedDate.compareTo(other.getLastAccessedDate());
}
/**

View File

@ -27,44 +27,53 @@
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Component id="bnOpen" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="bnRefresh" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="bnShowLog" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="panelFilter" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="scrollPaneTable" pref="1007" max="32767" attributes="0"/>
<Component id="rbGroupLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="rbDays" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="rbWeeks" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="rbMonths" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="panelFilter" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="bnRefresh" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
</Group>
<Component id="scrollPaneTable" pref="1007" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="43" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Component id="scrollPaneTable" min="-2" pref="450" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="32767" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="panelFilter" min="-2" pref="130" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="bnOpen" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnRefresh" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnShowLog" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="36" max="-2" attributes="0"/>
<Component id="bnRefresh" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="103" alignment="1" groupAlignment="3" attributes="0">
<Component id="rbDays" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="rbWeeks" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="rbMonths" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="rbGroupLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="panelFilter" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -122,32 +131,16 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="rbGroupLabel" min="-2" max="-2" attributes="0"/>
<Component id="rbAllCases" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="rbMonths" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="rbWeeks" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="rbDays" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="34" max="32767" attributes="0"/>
<Component id="rbAllCases" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="rbGroupLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="rbDays" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="rbWeeks" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="rbMonths" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="rbAllCases" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -167,56 +160,6 @@
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="rbAllCasesItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="rbMonths">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="rbGroupHistoryLength"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbMonths.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="rbMonthsItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="rbWeeks">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="rbGroupHistoryLength"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbWeeks.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="rbWeeksItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="rbDays">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="rbGroupHistoryLength"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbDays.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="name" type="java.lang.String" value="" noResource="true"/>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="rbDaysItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="rbGroupLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="12" style="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbGroupLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="bnShowLog">
@ -233,5 +176,55 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnShowLogActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="rbDays">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="rbGroupHistoryLength"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbDays.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="name" type="java.lang.String" value="" noResource="true"/>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="rbDaysItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="rbWeeks">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="rbGroupHistoryLength"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbWeeks.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="rbWeeksItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="rbMonths">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="rbGroupHistoryLength"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbMonths.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="rbMonthsItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="rbGroupLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="12" style="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbGroupLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -63,7 +63,7 @@ public final class AutoIngestCasePanel extends JPanel {
private static final int STATUS_COL_MAX_WIDTH = 250;
private static final int STATUS_COL_PREFERRED_WIDTH = 60;
private static final int MILLIS_TO_WAIT_BEFORE_STARTING = 500;
private static final int MILLIS_TO_WAIT_BETWEEN_UPDATES = 30000;
private static final int MILLIS_TO_WAIT_BETWEEN_UPDATES = 300000;
private ScheduledThreadPoolExecutor casesTableRefreshExecutor;
/*
@ -105,6 +105,14 @@ public final class AutoIngestCasePanel extends JPanel {
public boolean isCellEditable(int row, int column) {
return false;
}
@Override
public Class<?> getColumnClass(int col) {
if (this.getColumnName(col).equals(CREATEDTIME_HEADER) || this.getColumnName(col).equals(COMPLETEDTIME_HEADER)) {
return Date.class;
} else {
return super.getColumnClass(col);
}
}
};
initComponents();
@ -384,11 +392,11 @@ public final class AutoIngestCasePanel extends JPanel {
bnRefresh = new javax.swing.JButton();
panelFilter = new javax.swing.JPanel();
rbAllCases = new javax.swing.JRadioButton();
rbMonths = new javax.swing.JRadioButton();
rbWeeks = new javax.swing.JRadioButton();
rbDays = new javax.swing.JRadioButton();
rbGroupLabel = new javax.swing.JLabel();
bnShowLog = new javax.swing.JButton();
rbDays = new javax.swing.JRadioButton();
rbWeeks = new javax.swing.JRadioButton();
rbMonths = new javax.swing.JRadioButton();
rbGroupLabel = new javax.swing.JLabel();
setName("Completed Cases"); // NOI18N
@ -428,19 +436,27 @@ public final class AutoIngestCasePanel extends JPanel {
}
});
rbGroupHistoryLength.add(rbMonths);
org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbMonths.text")); // NOI18N
rbMonths.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbMonthsItemStateChanged(evt);
}
});
javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter);
panelFilter.setLayout(panelFilterLayout);
panelFilterLayout.setHorizontalGroup(
panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFilterLayout.createSequentialGroup()
.addComponent(rbAllCases)
.addGap(0, 0, Short.MAX_VALUE))
);
panelFilterLayout.setVerticalGroup(
panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelFilterLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(rbAllCases))
);
rbGroupHistoryLength.add(rbWeeks);
org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbWeeks.text")); // NOI18N
rbWeeks.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbWeeksItemStateChanged(evt);
org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.text")); // NOI18N
bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.toolTipText")); // NOI18N
bnShowLog.setEnabled(false);
bnShowLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnShowLogActionPerformed(evt);
}
});
@ -453,48 +469,25 @@ public final class AutoIngestCasePanel extends JPanel {
}
});
rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbGroupLabel.text")); // NOI18N
javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter);
panelFilter.setLayout(panelFilterLayout);
panelFilterLayout.setHorizontalGroup(
panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFilterLayout.createSequentialGroup()
.addContainerGap()
.addGroup(panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(rbGroupLabel)
.addComponent(rbAllCases)
.addComponent(rbMonths)
.addComponent(rbWeeks)
.addComponent(rbDays))
.addContainerGap(34, Short.MAX_VALUE))
);
panelFilterLayout.setVerticalGroup(
panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelFilterLayout.createSequentialGroup()
.addContainerGap()
.addComponent(rbGroupLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(rbDays)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(rbWeeks)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(rbMonths)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rbAllCases)
.addContainerGap())
);
org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.text")); // NOI18N
bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.toolTipText")); // NOI18N
bnShowLog.setEnabled(false);
bnShowLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnShowLogActionPerformed(evt);
rbGroupHistoryLength.add(rbWeeks);
org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbWeeks.text")); // NOI18N
rbWeeks.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbWeeksItemStateChanged(evt);
}
});
rbGroupHistoryLength.add(rbMonths);
org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbMonths.text")); // NOI18N
rbMonths.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbMonthsItemStateChanged(evt);
}
});
rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbGroupLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@ -503,35 +496,45 @@ public final class AutoIngestCasePanel extends JPanel {
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(13, 13, 13)
.addGap(4, 4, 4)
.addComponent(bnOpen, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(bnRefresh)
.addGap(18, 18, 18)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnShowLog)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(rbGroupLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rbDays)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rbWeeks)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rbMonths)
.addGap(0, 0, 0)
.addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(20, 20, 20))
.addGroup(layout.createSequentialGroup()
.addComponent(scrollPaneTable, javax.swing.GroupLayout.DEFAULT_SIZE, 1007, Short.MAX_VALUE)
.addContainerGap())))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnRefresh)
.addGap(4, 4, 4))
.addComponent(scrollPaneTable, javax.swing.GroupLayout.DEFAULT_SIZE, 1007, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(43, 43, 43)
.addGap(6, 6, 6)
.addComponent(scrollPaneTable, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnOpen)
.addComponent(bnRefresh)
.addComponent(bnShowLog))
.addGap(36, 36, 36))))
.addComponent(bnRefresh)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(rbDays)
.addComponent(rbWeeks)
.addComponent(rbMonths)
.addComponent(rbGroupLabel))
.addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, 0))
);
}// </editor-fold>//GEN-END:initComponents

View File

@ -1,4 +1,11 @@
CTL_OpenAction=Open Case...
AutoIngestDashboard.bnRefresh.text=&Refresh
AutoIngestDashboard.lbCompleted.text=Completed Jobs
AutoIngestDashboard.lbRunning.text=Running Jobs
AutoIngestDashboard.lbPending.text=Pending Jobs
AutoIngestDashboard.bnCancelModule.text=Cancel &Module
AutoIngestDashboard.bnExit.text=&Exit
AutoIngestDashboard.bnOptions.text=&Options
AutoIngestDashboard.JobsTableModel.ColumnHeader.Case=Case
AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder=Data Source
AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName=Host Name
@ -8,12 +15,23 @@ AutoIngestDashboard.JobsTableModel.ColumnHeader.CompletedTime=Job Completed
AutoIngestDashboard.JobsTableModel.ColumnHeader.Stage=Stage
AutoIngestDashboard.JobsTableModel.ColumnHeader.Status=Status
AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path
AutoIngestDashboard.bnShowProgress.text=Ingest Progress
AutoIngestDashboard.bnResume.text=Resume
AutoIngestDashboard.bnPause.text=Pause
AutoIngestDashboard.bnPause.confirmHeader=Are you sure you want to pause?
AutoIngestDashboard.bnPause.warningText=Pause will occur after the current job completes processing. This could take a long time. Continue?
AutoIngestDashboard.bnPause.toolTipText=Suspend processing of Pending Jobs
AutoIngestDashboard.bnPause.toolTipTextResume=Resume processing of Pending Jobs
AutoIngestDashboard.bnPause.pausing=Pausing after current job completes...
AutoIngestDashboard.bnRefresh.toolTipText=Refresh displayed tables
AutoIngestDashboard.bnShowProgress.toolTipText=Show the progress of the currently running Job. This functionality is only available for jobs running on current AIM node.
AutoIngestDashboard.bnCancelModule.toolTipText=Cancel processing of the current module within the Job and move on to the next module within the Job. This functionality is only available for jobs running on current AIM node.
AutoIngestDashboard.bnExit.toolTipText=Exit Application
AutoIngestDashboard.Cancelling=Cancelling...
AutoIngestDashboard.bnOptions.toolTipText=Display options panel. All processing must be paused to open the options panel.
AutoIngestDashboard.pendingTable.toolTipText=The Pending table displays the order upcoming Jobs will be processed with the top of the list first
AutoIngestDashboard.runningTable.toolTipText=The Running table displays the currently running Job and information about it
AutoIngestDashboard.completedTable.toolTipText=The Completed table shows all Jobs that have been processed already
AutoIngestDashboard.JobsTableModel.ColumnHeader.StageTime=Time in Stage
AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder=Case Folder
AutoIngestDashboard.JobsTableModel.ColumnHeader.LocalJob= Local Job?
@ -145,12 +163,20 @@ CopyFilesPanel.ConfirmCopyAdd=exists. Do you really want to copy more files to t
CopyFilesPanel.ConfirmCopyYes=Copy
CopyFilesPanel.ConfirmCopyNo=Do not copy
ConfirmationDialog.ConfirmUnlockHeader=Confirm Case Unlock
AutoIngestDashboard.bnPrioritizeCase.toolTipText=Move all images associated with a case to top of Pending queue.
AutoIngestDashboard.bnPrioritizeCase.text=Prioriti&ze Case
AutoIngestDashboard.bnShowCaseLog.toolTipText=Display case log file for selected case
AutoIngestDashboard.bnShowCaseLog.text=Show Case &Log
CopyFilesPanel.bnCancelPendingJob.text=Ca&ncel
CopyFilesPanel.tbDestinationCase.text=
CopyFilesPanel.cbThrottleNetwork.text=&Throttle Network
CopyFilesPanel.cbThrottleNetwork.toolTipText=<html>Select this box if a low-bandwidth network connection is involved in this copy job.<br>\nSelecting this box will artificially limit the transfer speed by inserting strategic delays.<br>\nThis helps copy files across low-bandwidth networks where the transfer would<br>\notherwise fail. Only select this if you are having problems copying across the network.</html>
CopyFilesPanel.bnShowCurrentLog.text=Show &Log
CopyFilesPanel.bnShowCurrentLog.text=Show &Log
AutoIngestDashboard.bnCancelJob.toolTipText=Cancel processing of the current Job and move on to the next Job. This functionality is only available for jobs running on current AIM node.
AutoIngestDashboard.bnCancelJob.text=&Cancel Job
AutoIngestDashboard.bnDeleteCase.toolTipText=Delete the selected Case in its entirety
AutoIngestDashboard.bnDeleteCase.text=&Delete Case
CopyFilesPanel.lbCaseName.text=Case Name
CaseStatusIconCellRenderer.tooltiptext.ok=Images processed successfully
CaseStatusIconCellRenderer.tooltiptext.warning=An error occurred or processing was canceled for at least one image - please check the log
@ -173,6 +199,7 @@ CaseImportPanel.Error=Error
CaseImportPanel.Complete=Complete
CaseImportPanel.Blank=
CaseImportPanel.DeleteWarning=Make sure no important files are in the case source directory
AutoIngestDashboard.lbStatus.text=Status:
SingleUserCaseImporter.NonUniqueOutputFolder=Output folder not unique. Skipping
SingleUserCaseImporter.WillImport=Will import:
SingleUserCaseImporter.None=None
@ -195,6 +222,9 @@ ReviewModeCasePanel.StatusIconHeaderText=Status
ReviewModeCasePanel.OutputFolderHeaderText=Output Folder
ReviewModeCasePanel.LastAccessedTimeHeaderText=Last Accessed Time
CopyFilesPanel.bnOptions.text=&Options
AutoIngestDashboard.lbServicesStatus.text=Services Status:
AutoIngestDashboard.tbServicesStatusMessage.text=
AutoIngestDashboard.tbStatusMessage.text=
FileExporterSettingsPanel.ChooseRootDirectory=Choose a root directory for file output
FileExporterSettingsPanel.ChooseReportDirectory=Choose a report directory
FileExporterSettingsPanel.RuleName=Rule Name
@ -253,7 +283,12 @@ FileExporterSettingsPanel.BrowseReportTooltip_1=Browse for the Reports Folder
FileExporterSettingsPanel.NewRuleTooltip_1=Clear the rule editor to begin a new rule
FileExporterSettingsPanel.DeleteTooltip_1=Delete the selected rule
FileExporterSettingsPanel.SaveTooltip_1=Save the current rule
AutoIngestDashboard.bnOpenLogDir.text=Open System Logs Directory
AutoIngestDashboard.bnPrioritizeJob.text=Prioritize Job
AutoIngestDashboard.bnPrioritizeJob.toolTipText=Move this folder to the top of the Pending queue.
AutoIngestDashboard.bnReprocessJob.text=Reprocess Job
AutoIngestDashboard.bnPrioritizeFolder.label=<AutoIngestDashboard.bnPrioritizeJob.text>
AutoIngestDashboard.bnPrioritizeJob.actionCommand=<AutoIngestDashboard.bnPrioritizeJob.text>
AutoIngestCasePanel.rbDays.text=Days
AutoIngestCasePanel.rbWeeks.text=Weeks
AutoIngestCasePanel.rbMonths.text=Months
@ -262,74 +297,4 @@ AutoIngestCasePanel.bnRefresh.text=&Refresh
AutoIngestCasePanel.bnOpen.text=&Open
AutoIngestCasePanel.bnShowLog.toolTipText=Display case log file for selected case
AutoIngestCasePanel.bnShowLog.text=&Show Log
AutoIngestCasePanel.rbGroupLabel.text=Show Last 10:
AutoIngestLegacyDashboard.tbStatusMessage.text=
AutoIngestLegacyDashboard.bnShowCaseLog.toolTipText=Display case log file for selected case
AutoIngestLegacyDashboard.bnShowCaseLog.text=Show Case &Log
AutoIngestLegacyDashboard.bnDeleteCase.toolTipText=Delete the selected Case in its entirety
AutoIngestLegacyDashboard.bnDeleteCase.text=&Delete Case
AutoIngestLegacyDashboard.bnCancelJob.toolTipText=Cancel processing of the current Job and move on to the next Job. This functionality is only available for jobs running on current AIM node.
AutoIngestLegacyDashboard.bnCancelJob.text=&Cancel Job
AutoIngestLegacyDashboard.completedTable.toolTipText=The Completed table shows all Jobs that have been processed already
AutoIngestLegacyDashboard.runningTable.toolTipText=The Running table displays the currently running Job and information about it
AutoIngestLegacyDashboard.pendingTable.toolTipText=The Pending table displays the order upcoming Jobs will be processed with the top of the list first
AutoIngestLegacyDashboard.bnPrioritizeCase.toolTipText=Move all images associated with a case to top of Pending queue.
AutoIngestLegacyDashboard.bnPrioritizeCase.text=Prioriti&ze Case
AutoIngestLegacyDashboard.bnPause.toolTipText=Suspend processing of Pending Jobs
AutoIngestLegacyDashboard.bnPause.text=Pause
AutoIngestLegacyDashboard.bnShowProgress.toolTipText=Show the progress of the currently running Job. This functionality is only available for jobs running on current AIM node.
AutoIngestLegacyDashboard.bnShowProgress.text=Ingest Progress
AutoIngestLegacyDashboard.bnOptions.toolTipText=Display options panel. All processing must be paused to open the options panel.
AutoIngestLegacyDashboard.bnOptions.text=&Options
AutoIngestLegacyDashboard.bnExit.toolTipText=Exit Application
AutoIngestLegacyDashboard.bnExit.text=&Exit
AutoIngestLegacyDashboard.bnCancelModule.toolTipText=Cancel processing of the current module within the Job and move on to the next module within the Job. This functionality is only available for jobs running on current AIM node.
AutoIngestLegacyDashboard.bnCancelModule.text=Cancel &Module
AutoIngestLegacyDashboard.bnRefresh.toolTipText=Refresh displayed tables
AutoIngestLegacyDashboard.bnRefresh.text=&Refresh
AutoIngestLegacyDashboard.lbCompleted.text=Completed Jobs
AutoIngestLegacyDashboard.lbRunning.text=Running Jobs
AutoIngestLegacyDashboard.lbPending.text=Pending Jobs
AutoIngestLegacyDashboard.bnReprocessJob.text=Reprocess Job
AutoIngestLegacyDashboard.bnOpenLogDir.text=Open System Logs Directory
AutoIngestLegacyDashboard.tbServicesStatusMessage.text=
AutoIngestLegacyDashboard.lbServicesStatus.text=Services Status:
AutoIngestLegacyDashboard.bnPrioritizeJob.actionCommand=<AutoIngestDashboard.bnPrioritizeJob.text>
AutoIngestLegacyDashboard.bnPrioritizeJob.toolTipText=Move this folder to the top of the Pending queue.
AutoIngestLegacyDashboard.bnPrioritizeJob.text=Prioritize Job
AutoIngestLegacyDashboard.lbStatus.text=Status:
AutoIngestDashboard.bnRefresh.text=&Refresh
AutoIngestDashboard.lbCompleted.text=Completed Jobs
AutoIngestDashboard.lbRunning.text=Running Jobs
AutoIngestDashboard.lbPending.text=Pending Jobs
AutoIngestDashboard.bnDeleteCase.toolTipText=Delete the selected Case in its entirety
AutoIngestDashboard.bnDeleteCase.text=&Delete Case
AutoIngestDashboard.bnCancelJob.toolTipText=Cancel processing of the current Job and move on to the next Job. This functionality is only available for jobs running on current AIM node.
AutoIngestDashboard.bnCancelJob.text=&Cancel Job
AutoIngestDashboard.completedTable.toolTipText=The Completed table shows all Jobs that have been processed already
AutoIngestDashboard.bnReprocessJob.text=Reprocess Job
AutoIngestDashboard.bnOpenLogDir.text=Open System Logs Directory
AutoIngestDashboard.runningTable.toolTipText=The Running table displays the currently running Job and information about it
AutoIngestDashboard.tbServicesStatusMessage.text=
AutoIngestDashboard.pendingTable.toolTipText=The Pending table displays the order upcoming Jobs will be processed with the top of the list first
AutoIngestDashboard.lbServicesStatus.text=Services Status:
AutoIngestDashboard.bnPrioritizeJob.actionCommand=<AutoIngestDashboard.bnPrioritizeJob.text>
AutoIngestDashboard.bnPrioritizeJob.toolTipText=Move this folder to the top of the Pending queue.
AutoIngestDashboard.bnPrioritizeJob.text=Prioritize Job
AutoIngestDashboard.lbStatus.text=Status:
AutoIngestDashboard.tbStatusMessage.text=
AutoIngestDashboard.bnShowCaseLog.toolTipText=Display case log file for selected case
AutoIngestDashboard.bnShowCaseLog.text=Show Case &Log
AutoIngestDashboard.bnPrioritizeCase.toolTipText_1=Move all images associated with a case to top of Pending queue.
AutoIngestDashboard.bnPrioritizeCase.text_1=Prioriti&ze Case
AutoIngestDashboard.bnPause.toolTipText=Suspend processing of Pending Jobs
AutoIngestDashboard.bnPause.text=Pause
AutoIngestDashboard.bnShowProgress.toolTipText=Show the progress of the currently running Job. This functionality is only available for jobs running on current AIM node.
AutoIngestDashboard.bnShowProgress.text=Ingest Progress
AutoIngestDashboard.bnOptions.toolTipText=Display options panel. All processing must be paused to open the options panel.
AutoIngestDashboard.bnOptions.text=&Options
AutoIngestDashboard.bnExit.toolTipText=Exit Application
AutoIngestDashboard.bnExit.text=&Exit
AutoIngestDashboard.bnCancelModule.toolTipText=Cancel processing of the current module within the Job and move on to the next module within the Job. This functionality is only available for jobs running on current AIM node.
AutoIngestDashboard.bnCancelModule.text=Cancel &Module
AutoIngestDashboard.bnRefresh.toolTipText=Refresh displayed tables
AutoIngestCasePanel.rbGroupLabel.text=Show cases accessed in the last 10:

View File

@ -35,6 +35,7 @@ import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.SleuthkitItemVisitor;
@ -206,7 +207,6 @@ class Ingester {
// but does this really mean we don't want to index it?
//skip the file, image id unknown
//JMTODO: does this need to ne internationalized?
String msg = NbBundle.getMessage(Ingester.class,
"Ingester.ingest.exception.unknownImgId.msg", sourceName); //JMTODO: does this need to ne internationalized?
logger.log(Level.SEVERE, msg);
@ -273,6 +273,11 @@ class Ingester {
return getCommonAndMACTimeFields(d);
}
@Override
public Map<String, String> visit(LocalDirectory ld){
return getCommonAndMACTimeFields(ld);
}
@Override
public Map<String, String> visit(LayoutFile lf) {
// layout files do not have times

View File

@ -10,7 +10,6 @@ app.version=4.4.1
build.type=DEVELOPMENT
project.org.netbeans.progress=org-netbeans-api-progress
project.org.sleuthkit.autopsy.centralrepository=CentralRepository
project.org.sleuthkit.autopsy.experimental=Experimental
project.org.sleuthkit.autopsy.imagegallery=ImageGallery
update_versions=false
@ -32,8 +31,7 @@ modules=\
${project.org.sleuthkit.autopsy.core}:\
${project.org.sleuthkit.autopsy.corelibs}:\
${project.org.sleuthkit.autopsy.imagegallery}:\
${project.org.sleuthkit.autopsy.experimental}:\
${project.org.sleuthkit.autopsy.centralrepository}
${project.org.sleuthkit.autopsy.experimental}
project.org.sleuthkit.autopsy.core=Core
project.org.sleuthkit.autopsy.corelibs=CoreLibs
project.org.sleuthkit.autopsy.keywordsearch=KeywordSearch

View File

@ -6,12 +6,25 @@ List of tags:
image: An image to be ingested
build: the path to the build.xml file
indir: the path to input directory
outdir: the path to output directory
singleUser_outdir: the path to single-user case output directory
global_csv: path to global csv file
golddir: the path to gold directory
singleUser_golddir: the path to single-user case gold directory
timing: can be set to True or False. If enabled, record the timing.
userCaseType: set this value to do single-user, multi-user or both tests
NOTE: Make sure to use windows style for paths!
List of tags for multi-user case:
multiUser_outdir: a path to multi-user case output directory
multiUser_golddir: a path to multi-user case gold directory
dbHost: PostgreSQL database host name
dbPort: PostgreSQL database port number
dbUserName: PostgreSQL database username
dbPassword: PostgreSQL database password
solrHost: Solr server host name
solrPort: Solr server port number
messageServiceHost: ActiveMQ server hostname
messageServicePort: ActiveMQ server port number
NOTE: Make sure to use UNC path for mutliUser_outdir, use windows style for other paths!
None of these tags are mandatory, and if nothing is provided the file will be
looked over and ignored.

View File

@ -300,11 +300,14 @@ class TskDbDiff(object):
os.chmod (backup_db_file, 0o777)
conn = sqlite3.connect(backup_db_file)
id_path_table = build_id_table(conn.cursor())
id_files_table = build_id_files_table(conn.cursor())
id_vs_parts_table = build_id_vs_parts_table(conn.cursor())
id_vs_info_table = build_id_vs_info_table(conn.cursor())
id_fs_info_table = build_id_fs_info_table(conn.cursor())
id_objects_table = build_id_objects_table(conn.cursor())
id_artifact_types_table = build_id_artifact_types_table(conn.cursor())
id_obj_path_table = build_id_obj_path_table(id_files_table, id_objects_table, id_artifact_types_table)
conn.text_factory = lambda x: x.decode("utf-8", "ignore")
# Delete the blackboard tables
@ -314,7 +317,7 @@ class TskDbDiff(object):
# Write to the database dump
with codecs.open(dump_file, "wb", "utf_8") as db_log:
for line in conn.iterdump():
line = normalize_db_entry(line, id_path_table, id_vs_parts_table, id_vs_info_table, id_fs_info_table, id_objects_table)
line = normalize_db_entry(line, id_obj_path_table, id_vs_parts_table, id_vs_info_table, id_fs_info_table, id_objects_table)
db_log.write('%s\n' % line)
# Now sort the file
@ -346,12 +349,12 @@ class TskDbDiff(object):
class TskDbDiffException(Exception):
pass
def normalize_db_entry(line, table, vs_parts_table, vs_info_table, fs_info_table, objects_table):
def normalize_db_entry(line, files_table, vs_parts_table, vs_info_table, fs_info_table, objects_table):
""" Make testing more consistent and reasonable by doctoring certain db entries.
Args:
line: a String, the line to remove the object id from.
table: a map from object ids to file paths.
files_table: a map from object ids to file paths.
"""
files_index = line.find('INSERT INTO "tsk_files"')
@ -361,31 +364,35 @@ def normalize_db_entry(line, table, vs_parts_table, vs_info_table, fs_info_table
layout_index = line.find('INSERT INTO "tsk_file_layout"')
data_source_info_index = line.find('INSERT INTO "data_source_info"')
ingest_job_index = line.find('INSERT INTO "ingest_jobs"')
parens = line[line.find('(') + 1 : line.rfind(')')]
fields_list = parens.replace(" ", "").split(',')
# remove object ID
if (files_index != -1):
obj_id = fields_list[0]
path = table[int(obj_id)]
path = files_table[int(obj_id)]
newLine = ('INSERT INTO "tsk_files" VALUES(' + ', '.join(fields_list[1:]) + ');')
return newLine
# remove object ID
elif (path_index != -1):
obj_id = fields_list[0]
objValue = table[int(obj_id)]
par_obj_id = objects_table[int(obj_id)]
par_obj_value = table[par_obj_id]
par_obj_name = par_obj_value[par_obj_value.rfind('/')+1:]
#check the par_id that we insert to the path name when we create uniqueName
pathValue = re.sub(par_obj_name + '_' + str(par_obj_id), par_obj_name, fields_list[1])
obj_id = int(fields_list[0])
objValue = files_table[obj_id]
# remove the obj_id from ModuleOutput/EmbeddedFileExtractor directory
idx_pre = fields_list[1].find('EmbeddedFileExtractor') + len('EmbeddedFileExtractor')
if idx_pre > -1:
idx_pos = fields_list[1].find('\\', idx_pre + 2)
dir_to_replace = fields_list[1][idx_pre + 1 : idx_pos] # +1 to skip the file seperator
dir_to_replace = dir_to_replace[0:dir_to_replace.rfind('_')]
pathValue = fields_list[1][:idx_pre+1] + dir_to_replace + fields_list[1][idx_pos:]
else:
pathValue = fields_list[1]
newLine = ('INSERT INTO "tsk_files_path" VALUES(' + objValue + ', ' + pathValue + ', ' + ', '.join(fields_list[2:]) + ');')
return newLine
# remove object ID
elif (layout_index != -1):
obj_id = fields_list[0]
path= table[int(obj_id)]
path= files_table[int(obj_id)]
newLine = ('INSERT INTO "tsk_file_layout" VALUES(' + path + ', ' + ', '.join(fields_list[1:]) + ');')
return newLine
# remove object ID
@ -403,8 +410,8 @@ def normalize_db_entry(line, table, vs_parts_table, vs_info_table, fs_info_table
except Exception as e:
return line
if obj_id in table.keys():
path = table[obj_id]
if obj_id in files_table.keys():
path = files_table[obj_id]
elif obj_id in vs_parts_table.keys():
path = vs_parts_table[obj_id]
elif obj_id in vs_info_table.keys():
@ -412,8 +419,8 @@ def normalize_db_entry(line, table, vs_parts_table, vs_info_table, fs_info_table
elif obj_id in fs_info_table.keys():
path = fs_info_table[obj_id]
if parent_id in table.keys():
parent_path = table[parent_id]
if parent_id in files_table.keys():
parent_path = files_table[parent_id]
elif parent_id in vs_parts_table.keys():
parent_path = vs_parts_table[parent_id]
elif parent_id in vs_info_table.keys():
@ -467,60 +474,95 @@ def getAssociatedArtifactType(db_file, artifact_id):
return "File path: " + info[0] + " Artifact Type: " + info[1]
def build_id_table(artifact_cursor):
def build_id_files_table(db_cursor):
"""Build the map of object ids to file paths.
Args:
artifact_cursor: the database cursor
db_cursor: the database cursor
"""
# for each row in the db, take the object id, parent path, and name, then create a tuple in the dictionary
# with the object id as the key and the full file path (parent + name) as the value
mapping = dict([(row[0], str(row[1]) + str(row[2])) for row in artifact_cursor.execute("SELECT obj_id, parent_path, name FROM tsk_files")])
mapping = dict([(row[0], str(row[1]) + str(row[2])) for row in db_cursor.execute("SELECT obj_id, parent_path, name FROM tsk_files")])
return mapping
def build_id_vs_parts_table(artifact_cursor):
def build_id_vs_parts_table(db_cursor):
"""Build the map of object ids to vs_parts.
Args:
artifact_cursor: the database cursor
db_cursor: the database cursor
"""
# for each row in the db, take the object id, addr, and start, then create a tuple in the dictionary
# with the object id as the key and (addr + start) as the value
mapping = dict([(row[0], str(row[1]) + '_' + str(row[2])) for row in artifact_cursor.execute("SELECT obj_id, addr, start FROM tsk_vs_parts")])
mapping = dict([(row[0], str(row[1]) + '_' + str(row[2])) for row in db_cursor.execute("SELECT obj_id, addr, start FROM tsk_vs_parts")])
return mapping
def build_id_vs_info_table(artifact_cursor):
def build_id_vs_info_table(db_cursor):
"""Build the map of object ids to vs_info.
Args:
artifact_cursor: the database cursor
db_cursor: the database cursor
"""
# for each row in the db, take the object id, vs_type, and img_offset, then create a tuple in the dictionary
# with the object id as the key and (vs_type + img_offset) as the value
mapping = dict([(row[0], str(row[1]) + '_' + str(row[2])) for row in artifact_cursor.execute("SELECT obj_id, vs_type, img_offset FROM tsk_vs_info")])
mapping = dict([(row[0], str(row[1]) + '_' + str(row[2])) for row in db_cursor.execute("SELECT obj_id, vs_type, img_offset FROM tsk_vs_info")])
return mapping
def build_id_fs_info_table(artifact_cursor):
def build_id_fs_info_table(db_cursor):
"""Build the map of object ids to fs_info.
Args:
artifact_cursor: the database cursor
db_cursor: the database cursor
"""
# for each row in the db, take the object id, img_offset, and fs_type, then create a tuple in the dictionary
# with the object id as the key and (img_offset + fs_type) as the value
mapping = dict([(row[0], str(row[1]) + '_' + str(row[2])) for row in artifact_cursor.execute("SELECT obj_id, img_offset, fs_type FROM tsk_fs_info")])
mapping = dict([(row[0], str(row[1]) + '_' + str(row[2])) for row in db_cursor.execute("SELECT obj_id, img_offset, fs_type FROM tsk_fs_info")])
return mapping
def build_id_objects_table(artifact_cursor):
def build_id_objects_table(db_cursor):
"""Build the map of object ids to par_id.
Args:
artifact_cursor: the database cursor
db_cursor: the database cursor
"""
# for each row in the db, take the object id, par_obj_id, then create a tuple in the dictionary
# with the object id as the key and par_obj_id as the value
mapping = dict([(row[0], row[1]) for row in artifact_cursor.execute("SELECT obj_id, par_obj_id FROM tsk_objects")])
# with the object id as the key and par_obj_id, type as the value
mapping = dict([(row[0], [row[1], row[2]]) for row in db_cursor.execute("SELECT * FROM tsk_objects")])
return mapping
def build_id_artifact_types_table(db_cursor):
"""Build the map of object ids to artifact ids.
Args:
db_cursor: the database cursor
"""
# for each row in the db, take the object id, par_obj_id, then create a tuple in the dictionary
# with the object id as the key and artifact type as the value
mapping = dict([(row[0], row[1]) for row in db_cursor.execute("SELECT blackboard_artifacts.artifact_obj_id, blackboard_artifact_types.type_name FROM blackboard_artifacts INNER JOIN blackboard_artifact_types ON blackboard_artifact_types.artifact_type_id = blackboard_artifacts.artifact_type_id ")])
return mapping
def build_id_obj_path_table(files_table, objects_table, artifacts_table):
"""Build the map of object ids to artifact ids.
Args:
files_table: obj_id, path
objects_table: obj_id, par_obj_id, type
artifacts_table: obj_id, artifact_type_name
"""
# make a copy of files_table and updated it with new data from artifats_table
mapping = files_table.copy()
for k, v in objects_table.items():
if k not in mapping.keys(): # If the mapping table doesn't have data for obj_id(k), we use it's par_obj_id's path+name plus it's artifact_type name as path
if k in artifacts_table.keys():
par_obj_id = v[0]
path = mapping[par_obj_id]
mapping[k] = path + "/" + artifacts_table[k]
elif v[0] not in mapping.keys():
if v[0] in artifacts_table.keys():
par_obj_id = objects_table[v[0]]
path = mapping[par_obj_id]
mapping[k] = path + "/" + artifacts_table[v[0]]
return mapping
def main():

Some files were not shown because too many files have changed in this diff Show More