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="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.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> </dependencies>
</ivy-module> </ivy-module>

View File

@ -362,6 +362,14 @@
<runtime-relative-path>ext/curator-framework-2.8.0.jar</runtime-relative-path> <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> <binary-origin>release/modules/ext/curator-framework-2.8.0.jar</binary-origin>
</class-path-extension> </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> </data>
</configuration> </configuration>
</project> </project>

View File

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

View File

@ -1095,6 +1095,20 @@ public abstract class AbstractSqlEamDb implements EamDb {
preparedUpdate.executeUpdate(); preparedUpdate.executeUpdate();
} else { } 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); eamArtifact.getInstances().get(0).setKnownStatus(TskData.FileKnown.BAD);
addArtifact(eamArtifact); addArtifact(eamArtifact);
} }

View File

@ -35,6 +35,20 @@ public class Installer extends ModuleInstall {
private final PropertyChangeListener pcl = new CaseEventListener(); private final PropertyChangeListener pcl = new CaseEventListener();
private final IngestEventsListener ieListener = new IngestEventsListener(); 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 @Override
public void restored() { public void restored() {
Case.addPropertyChangeListener(pcl); 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.corecomponents.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.datamodel.Installer.getDefault()); packageInstallers.add(org.sleuthkit.autopsy.datamodel.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.ingest.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.awt.datatransfer.StringSelection;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -456,12 +457,13 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
return false; return false;
} }
Content content = node.getLookup().lookup(Content.class); for (Content content : node.getLookup().lookupAll(Content.class)) {
if (content != null) { if ( (content != null) && (!(content instanceof BlackboardArtifact)) ){
try { try {
return content.getAllArtifactsCount() > 0; return content.getAllArtifactsCount() > 0;
} catch (TskException ex) { } 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; return false;
@ -693,22 +695,28 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
// blackboard artifact, if any. // blackboard artifact, if any.
Lookup lookup = selectedNode.getLookup(); Lookup lookup = selectedNode.getLookup();
// Get the content. // Get the content. We may get BlackboardArtifacts, ignore those here.
Content content = lookup.lookup(Content.class); ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
if (content == null) { Collection<? extends Content> contents = lookup.lookupAll(Content.class);
if (contents.isEmpty()) {
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT); return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
} }
Content underlyingContent = null;
// Get all of the blackboard artifacts associated with the content. These are what this for (Content content : contents) {
// viewer displays. if ( (content != null) && (!(content instanceof BlackboardArtifact)) ) {
ArrayList<BlackboardArtifact> artifacts; // Get all of the blackboard artifacts associated with the content. These are what this
try { // viewer displays.
artifacts = content.getAllArtifacts(); try {
} catch (TskException ex) { artifacts = content.getAllArtifacts();
logger.log(Level.WARNING, "Couldn't get artifacts", ex); //NON-NLS underlyingContent = content;
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT); break;
} catch (TskException ex) {
logger.log(Level.SEVERE, "Couldn't get artifacts", ex); //NON-NLS
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
}
}
} }
if (isCancelled()) { if (isCancelled()) {
return null; return null;
} }
@ -716,7 +724,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
// Build the new artifact contents cache. // Build the new artifact contents cache.
ArrayList<ResultsTableArtifact> artifactContents = new ArrayList<>(); ArrayList<ResultsTableArtifact> artifactContents = new ArrayList<>();
for (BlackboardArtifact artifact : artifacts) { 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, // 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.TreeSet;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import java.util.stream.Stream;
import javax.swing.JTable; import javax.swing.JTable;
import javax.swing.ListSelectionModel; import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@ -59,8 +58,6 @@ import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.nodes.Node.Property; 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.NbBundle;
import org.openide.util.NbPreferences; import org.openide.util.NbPreferences;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; 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()); private static final Logger logger = Logger.getLogger(DataResultViewerTable.class.getName());
@NbBundle.Messages("DataResultViewerTable.firstColLbl=Name") @NbBundle.Messages("DataResultViewerTable.firstColLbl=Name")
static private final String FIRST_COLUMN_LABEL = Bundle.DataResultViewerTable_firstColLbl(); 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); private static final Color TAGGED_COLOR = new Color(200, 210, 220);
/** /**
* The properties map: * The properties map:
@ -103,8 +98,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
*/ */
private final Map<String, ETableColumn> columnMap = new HashMap<>(); private final Map<String, ETableColumn> columnMap = new HashMap<>();
private final PleasewaitNodeListener pleasewaitNodeListener = new PleasewaitNodeListener();
private Node currentRoot; private Node currentRoot;
/* /*
@ -218,15 +211,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
hasChildren = selectedNode.getChildren().getNodesCount() > 0; hasChildren = selectedNode.getChildren().getNodesCount() > 0;
} }
Node oldNode = this.em.getRootContext();
if (oldNode != null) {
oldNode.removeNodeListener(pleasewaitNodeListener);
}
if (hasChildren) { if (hasChildren) {
currentRoot = selectedNode; currentRoot = selectedNode;
pleasewaitNodeListener.reset();
currentRoot.addNodeListener(pleasewaitNodeListener);
em.setRootContext(currentRoot); em.setRootContext(currentRoot);
setupTable(); setupTable();
} else { } 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 * 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 * the outline table. This renderer colors a row if the tags property of the

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -22,17 +22,19 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.openide.nodes.Children;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.coreutils.Logger; 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.IngestManager;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -47,25 +49,22 @@ import org.sleuthkit.datamodel.TskCoreException;
*/ */
public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends AbstractContentNode<T> { 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 wrap
* @param abstractFile file to encapsulate
*/ */
AbstractAbstractFileNode(T abstractFile) { AbstractAbstractFileNode(T abstractFile) {
super(abstractFile); super(abstractFile);
String name = abstractFile.getName(); String ext = abstractFile.getNameExtension();
int dotIndex = name.lastIndexOf("."); if (StringUtils.isNotBlank(ext)) {
if (dotIndex > 0) { ext = "." + ext;
String ext = name.substring(dotIndex).toLowerCase();
// If this is an archive file we will listen for ingest events // If this is an archive file we will listen for ingest events
// that will notify us when new content has been identified. // that will notify us when new content has been identified.
for (String s : FileTypeExtensions.getArchiveExtensions()) { if (FileTypeExtensions.getArchiveExtensions().contains(ext)) {
if (ext.equals(s)) { IngestManager.getInstance().addIngestModuleEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
}
} }
} }
// Listen for case events so that we can detect when case is closed // Listen for case events so that we can detect when case is closed
@ -103,7 +102,6 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
} catch (NullPointerException ex) { } catch (NullPointerException ex) {
// Skip // Skip
} }
} }
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
if (evt.getNewValue() == null) { if (evt.getNewValue() == null) {
@ -127,194 +125,125 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
this.setSheet(createSheet()); this.setSheet(createSheet());
} }
// Note: this order matters for the search result, changed it if the order of property headers on the "KeywordSearchNode"changed @NbBundle.Messages({"AbstractAbstractFileNode.nameColLbl=Name",
public static enum AbstractFilePropertyType { "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 { NAME(AbstractAbstractFileNode_nameColLbl()),
@Override LOCATION(AbstractAbstractFileNode_locationColLbl()),
public String toString() { MOD_TIME(AbstractAbstractFileNode_modifiedTimeColLbl()),
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.nameColLbl"); CHANGED_TIME(AbstractAbstractFileNode_changeTimeColLbl()),
} ACCESS_TIME(AbstractAbstractFileNode_accessTimeColLbl()),
}, CREATED_TIME(AbstractAbstractFileNode_createdTimeColLbl()),
LOCATION { SIZE(AbstractAbstractFileNode_sizeColLbl()),
@Override FLAGS_DIR(AbstractAbstractFileNode_flagsDirColLbl()),
public String toString() { FLAGS_META(AbstractAbstractFileNode_flagsMetaColLbl()),
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.locationColLbl"); MODE(AbstractAbstractFileNode_modeColLbl()),
} USER_ID(AbstractAbstractFileNode_useridColLbl()),
}, GROUP_ID(AbstractAbstractFileNode_groupidColLbl()),
MOD_TIME { META_ADDR(AbstractAbstractFileNode_metaAddrColLbl()),
@Override ATTR_ADDR(AbstractAbstractFileNode_attrAddrColLbl()),
public String toString() { TYPE_DIR(AbstractAbstractFileNode_typeDirColLbl()),
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.modifiedTimeColLbl"); TYPE_META(AbstractAbstractFileNode_typeMetaColLbl()),
} KNOWN(AbstractAbstractFileNode_knownColLbl()),
}, HASHSETS(AbstractAbstractFileNode_inHashsetsColLbl()),
CHANGED_TIME { MD5HASH(AbstractAbstractFileNode_md5HashColLbl()),
@Override ObjectID(AbstractAbstractFileNode_objectId()),
public String toString() { MIMETYPE(AbstractAbstractFileNode_mimeType()),
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.changeTimeColLbl"); EXTENSION(AbstractAbstractFileNode_extensionColLbl());
}
},
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");
} final private String displayString;
},
MIMETYPE {
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.mimeType");
} private AbstractFilePropertyType(String displayString) {
}, this.displayString = displayString;
}
@Override
public String toString() {
return displayString;
}
} }
/** /**
* Fill map with AbstractFile properties * Fill map with AbstractFile properties
* *
* @param map map with preserved ordering, where property names/values are * @param map map with preserved ordering, where property names/values
* put * are put
* @param content to extract properties from * @param content The content to get properties for.
*/ */
public static void fillPropertyMap(Map<String, Object> map, AbstractFile content) { static public void fillPropertyMap(Map<String, Object> map, AbstractFile content) {
map.put(NAME.toString(), getContentDisplayName(content));
String path = ""; map.put(LOCATION.toString(), getContentPath(content));
try { map.put(MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content));
path = content.getUniquePath(); map.put(CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content));
} catch (TskCoreException ex) { map.put(ACCESS_TIME.toString(), ContentUtils.getStringTime(content.getAtime(), content));
LOGGER.log(Level.SEVERE, "Except while calling Content.getUniquePath() on {0}", content); //NON-NLS 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(AbstractFilePropertyType.NAME.toString(), AbstractAbstractFileNode.getContentDisplayName(content)); map.put(FLAGS_META.toString(), content.getMetaFlagsAsString());
map.put(AbstractFilePropertyType.LOCATION.toString(), path); map.put(MODE.toString(), content.getModesAsString());
map.put(AbstractFilePropertyType.MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content)); map.put(USER_ID.toString(), content.getUid());
map.put(AbstractFilePropertyType.CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content)); map.put(GROUP_ID.toString(), content.getGid());
map.put(AbstractFilePropertyType.ACCESS_TIME.toString(), ContentUtils.getStringTime(content.getAtime(), content)); map.put(META_ADDR.toString(), content.getMetaAddr());
map.put(AbstractFilePropertyType.CREATED_TIME.toString(), ContentUtils.getStringTime(content.getCrtime(), content)); map.put(ATTR_ADDR.toString(), content.getAttrType().getValue() + "-" + content.getAttributeId());
map.put(AbstractFilePropertyType.SIZE.toString(), content.getSize()); map.put(TYPE_DIR.toString(), content.getDirType().getLabel());
map.put(AbstractFilePropertyType.FLAGS_DIR.toString(), content.getDirFlagAsString()); map.put(TYPE_META.toString(), content.getMetaType().toString());
map.put(AbstractFilePropertyType.FLAGS_META.toString(), content.getMetaFlagsAsString()); map.put(KNOWN.toString(), content.getKnown().getName());
map.put(AbstractFilePropertyType.MODE.toString(), content.getModesAsString()); map.put(HASHSETS.toString(), getHashSetHitsForFile(content));
map.put(AbstractFilePropertyType.USER_ID.toString(), content.getUid()); map.put(MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash()));
map.put(AbstractFilePropertyType.GROUP_ID.toString(), content.getGid()); map.put(ObjectID.toString(), content.getId());
map.put(AbstractFilePropertyType.META_ADDR.toString(), content.getMetaAddr()); map.put(MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType()));
map.put(AbstractFilePropertyType.ATTR_ADDR.toString(), Long.toString(content.getAttrType().getValue()) + "-" + content.getAttributeId()); map.put(EXTENSION.toString(), content.getNameExtension());
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());
} }
/** /**
* Used by subclasses of AbstractAbstractFileNode to add the tags property * Used by subclasses of AbstractAbstractFileNode to add the tags property
* to their sheets. * 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) { protected void addTagProperty(Sheet.Set ss) {
final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc"); List<ContentTag> tags = new ArrayList<>();
List<ContentTag> tags;
try { try {
tags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content); tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content));
} catch (TskCoreException ex) { } 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) { 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 file) {
private static String getHashSetHitsForFile(AbstractFile content) {
try { try {
return StringUtils.join(content.getHashSetNames(), ", "); return StringUtils.join(file.getHashSetNames(), ", ");
} catch (TskCoreException tskCoreException) { } 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 ""; return "";
} }
} }

View File

@ -25,6 +25,7 @@ import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
import org.sleuthkit.autopsy.datamodel.accounts.Accounts; import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
import org.sleuthkit.autopsy.datamodel.accounts.Accounts.AccountsRootNode; import org.sleuthkit.autopsy.datamodel.accounts.Accounts.AccountsRootNode;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.Directory;
@ -32,6 +33,7 @@ import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.SleuthkitItemVisitor; import org.sleuthkit.datamodel.SleuthkitItemVisitor;
import org.sleuthkit.datamodel.SleuthkitVisitableItem; import org.sleuthkit.datamodel.SleuthkitVisitableItem;
@ -112,11 +114,21 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
return new VirtualDirectoryNode(ld); return new VirtualDirectoryNode(ld);
} }
@Override
public AbstractContentNode<? extends Content> visit(LocalDirectory ld) {
return new LocalDirectoryNode(ld);
}
@Override @Override
public AbstractContentNode<? extends Content> visit(SlackFile sf) { public AbstractContentNode<? extends Content> visit(SlackFile sf) {
return new SlackFileNode(sf); return new SlackFileNode(sf);
} }
@Override
public AbstractContentNode<? extends Content> visit(BlackboardArtifact art) {
return new BlackboardArtifactNode(art);
}
@Override @Override
protected AbstractContentNode<? extends Content> defaultVisit(SleuthkitVisitableItem di) { protected AbstractContentNode<? extends Content> defaultVisit(SleuthkitVisitableItem di) {
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(), 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.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -48,13 +48,23 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
* @param content Underlying Content instances * @param content Underlying Content instances
*/ */
AbstractContentNode(T content) { AbstractContentNode(T content) {
//TODO consider child factory for the content children this(content, Lookups.singleton(content) );
super(new ContentChildren(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), lookup);
this.content = content; this.content = content;
//super.setName(ContentUtils.getSystemName(content)); //super.setName(ContentUtils.getSystemName(content));
super.setName("content_" + Long.toString(content.getId())); //NON-NLS super.setName("content_" + Long.toString(content.getId())); //NON-NLS
} }
/** /**
* Return the content data associated with this node * Return the content data associated with this node
* *
@ -66,8 +76,7 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
@Override @Override
public void setName(String name) { public void setName(String name) {
throw new UnsupportedOperationException( super.setName(name);
NbBundle.getMessage(this.getClass(), "AbstractContentNode.exception.cannotChangeSysName.msg"));
} }
@Override @Override

View File

@ -69,14 +69,11 @@ public abstract class AbstractFsContentNode<T extends AbstractFile> extends Abst
s.put(ss); s.put(ss);
} }
Map<String, Object> map = new LinkedHashMap<String, Object>(); Map<String, Object> map = new LinkedHashMap<>();
AbstractAbstractFileNode.fillPropertyMap(map, content); 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"); final String NO_DESCR = NbBundle.getMessage(this.getClass(), "AbstractFsContentNode.noDesc.text");
for (int i = 0; i < FS_PROPS_LEN; ++i) { for (AbstractFilePropertyType propType : AbstractFilePropertyType.values()) {
final AbstractFilePropertyType propType = AbstractFilePropertyType.values()[i];
final String propString = propType.toString(); final String propString = propType.toString();
ss.put(new NodeProperty<>(propString, propString, NO_DESCR, map.get(propString))); 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.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -34,6 +35,7 @@ import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.swing.Action; import javax.swing.Action;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.NbBundle; 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.BlackBoardArtifactTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; 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.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked; 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.ViewArtifactInTimelineAction;
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
import org.sleuthkit.datamodel.AbstractFile; 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 * Node wrapping a blackboard artifact object. This is generated from several
* places in the tree. * 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()); private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName());
@ -70,8 +74,9 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
build(); build();
private final BlackboardArtifact artifact; private final BlackboardArtifact artifact;
private final Content associated; private Content associated = null;
private List<NodeProperty<? extends Object>> customProperties; private List<NodeProperty<? extends Object>> customProperties;
/* /*
* Artifact types which should have the full unique path of the associated * Artifact types which should have the full unique path of the associated
* content as a property. * content as a property.
@ -130,11 +135,18 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
* @param iconPath icon to use for the artifact * @param iconPath icon to use for the artifact
*/ */
public BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath) { public BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath) {
super(Children.LEAF, createLookup(artifact)); super(artifact, createLookup(artifact));
this.artifact = 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.setName(Long.toString(artifact.getArtifactID()));
this.setDisplayName(); this.setDisplayName();
this.setIconBaseWithExtension(iconPath); this.setIconBaseWithExtension(iconPath);
@ -148,20 +160,18 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
* @param artifact artifact to encapsulate * @param artifact artifact to encapsulate
*/ */
public BlackboardArtifactNode(BlackboardArtifact artifact) { public BlackboardArtifactNode(BlackboardArtifact artifact) {
super(Children.LEAF, createLookup(artifact));
this(artifact, ExtractedContent.getIconFilePath(artifact.getArtifactTypeID()));
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);
} }
private void removeListeners() { private void removeListeners() {
Case.removePropertyChangeListener(pcl); Case.removePropertyChangeListener(pcl);
} }
public BlackboardArtifact getArtifact() {
return this.artifact;
}
@Override @Override
@NbBundle.Messages({ @NbBundle.Messages({
"BlackboardArtifactNode.getAction.errorTitle=Error getting actions", "BlackboardArtifactNode.getAction.errorTitle=Error getting actions",
@ -211,10 +221,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
*/ */
private void setDisplayName() { private void setDisplayName() {
String displayName = ""; //NON-NLS 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 // 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" // display name to be the artifact type name followed by " Artifact"
// e.g. "Messages Artifact". // e.g. "Messages Artifact".
@ -238,9 +245,30 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
// Do nothing since the display name will be set to the file name. // Do nothing since the display name will be set to the file name.
} }
} }
if (displayName.isEmpty() && artifact != null) {
displayName = artifact.getName();
}
this.setDisplayName(displayName); 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({ @NbBundle.Messages({
"BlackboardArtifactNode.createSheet.artifactType.displayName=Artifact Type", "BlackboardArtifactNode.createSheet.artifactType.displayName=Artifact Type",
"BlackboardArtifactNode.createSheet.artifactType.name=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"), ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"),
NO_DESCR, NO_DESCR,
this.getDisplayName())); this.getSrcName()));
if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) { if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
try { try {
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)); BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
@ -555,4 +583,9 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
public String getItemType() { public String getItemType() {
return getClass().getName(); 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 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.CreateTSKNodeVisitor.exception.noNodeMsg=No Node defined for the given SleuthkitItem
AbstractContentChildren.createAutopsyNodeVisitor.exception.noNodeMsg=No Node defined for the given DisplayableItem AbstractContentChildren.createAutopsyNodeVisitor.exception.noNodeMsg=No Node defined for the given DisplayableItem
AbstractContentNode.exception.cannotChangeSysName.msg=Cannot change the system name. 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.name=Name
DataSourcesNode.createSheet.name.displayName=Name DataSourcesNode.createSheet.name.displayName=Name
DataSourcesNode.createSheet.name.desc=no description 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.parFolder.text=[parent folder]
DirectoryNode.curFolder.text=[current folder] DirectoryNode.curFolder.text=[current folder]
DirectoryNode.getActions.viewFileInDir.text=View File in Directory 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.name=Flags
VolumeNode.createSheet.flags.displayName=Flags VolumeNode.createSheet.flags.displayName=Flags
VolumeNode.createSheet.flags.desc=no description VolumeNode.createSheet.flags.desc=no description
AbstractAbstractFileNode.objectId=Object ID
ArtifactStringContent.getStr.artifactId.text=Artifact ID ArtifactStringContent.getStr.artifactId.text=Artifact ID
DeleteReportAction.actionDisplayName.singleReport=Delete Report DeleteReportAction.actionDisplayName.singleReport=Delete Report
DeleteReportAction.actionDisplayName.multipleReports=Delete Reports DeleteReportAction.actionDisplayName.multipleReports=Delete Reports
DeleteReportAction.actionPerformed.showConfirmDialog.title=Confirm Deletion DeleteReportAction.actionPerformed.showConfirmDialog.title=Confirm Deletion
DeleteReportAction.actionPerformed.showConfirmDialog.single.msg=Do you want to delete 1 report from the case? 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? 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.name=Tags
BlackboardArtifactNode.createSheet.tags.displayName=Tags BlackboardArtifactNode.createSheet.tags.displayName=Tags
FileTypeExtensionFilters.tskImgFilter.text=Images FileTypeExtensionFilters.tskImgFilter.text=Images
@ -255,4 +220,4 @@ FileTypeExtensionFilters.autDocHtmlFilter.text=HTML
FileTypeExtensionFilters.autDocOfficeFilter.text=Office FileTypeExtensionFilters.autDocOfficeFilter.text=Office
FileTypeExtensionFilters.autoDocPdfFilter.text=PDF FileTypeExtensionFilters.autoDocPdfFilter.text=PDF
FileTypeExtensionFilters.autDocTxtFilter.text=Plain Text FileTypeExtensionFilters.autDocTxtFilter.text=Plain Text
FileTypeExtensionFilters.autDocRtfFilter.text=Rich Text FileTypeExtensionFilters.autDocRtfFilter.text=Rich Text

View File

@ -31,6 +31,8 @@ interface ContentNodeVisitor<T> {
T visit(ImageNode in); T visit(ImageNode in);
T visit(VirtualDirectoryNode lcn); T visit(VirtualDirectoryNode lcn);
T visit(LocalDirectoryNode ldn);
T visit(VolumeNode vn); T visit(VolumeNode vn);
@ -43,6 +45,9 @@ interface ContentNodeVisitor<T> {
T visit(LocalFileNode dfn); T visit(LocalFileNode dfn);
T visit(SlackFileNode sfn); T visit(SlackFileNode sfn);
T visit(BlackboardArtifactNode bban);
/** /**
* Visitor with an implementable default behavior for all types. Override * Visitor with an implementable default behavior for all types. Override
@ -96,9 +101,19 @@ interface ContentNodeVisitor<T> {
return defaultVisit(ldn); return defaultVisit(ldn);
} }
@Override
public T visit(LocalDirectoryNode ldn) {
return defaultVisit(ldn);
}
@Override @Override
public T visit(SlackFileNode sfn) { public T visit(SlackFileNode sfn) {
return defaultVisit(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.Image;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
@ -378,6 +379,11 @@ public final class ContentUtils {
public Void visit(VirtualDirectory dir) { public Void visit(VirtualDirectory dir) {
return visitDir(dir); return visitDir(dir);
} }
@Override
public Void visit(LocalDirectory dir) {
return visitDir(dir);
}
private java.io.File getFsContentDest(Content fsc) { private java.io.File getFsContentDest(Content fsc) {
String path = dest.getAbsolutePath() + java.io.File.separator String path = dest.getAbsolutePath() + java.io.File.separator

View File

@ -44,6 +44,7 @@ import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.VirtualDirectory;
@ -229,6 +230,38 @@ public class DataModelActionsFactory {
actionsList.addAll(ContextMenuExtensionPoint.getActions()); actionsList.addAll(ContextMenuExtensionPoint.getActions());
return actionsList; 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) { public static List<Action> getActions(LocalFile file, boolean isArtifactSource) {
List<Action> actionsList = new ArrayList<>(); List<Action> actionsList = new ArrayList<>();

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-2017 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -39,6 +39,7 @@ import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datamodel.Bundle.*;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
@ -58,14 +59,15 @@ public class DeletedContent implements AutopsyVisitableItem {
private SleuthkitCase skCase; private SleuthkitCase skCase;
@NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System",
"DeletedContent.allDelFilter.text=All"})
public enum DeletedContentFilter implements AutopsyVisitableItem { public enum DeletedContentFilter implements AutopsyVisitableItem {
FS_DELETED_FILTER(0, FS_DELETED_FILTER(0, "FS_DELETED_FILTER", //NON-NLS
"FS_DELETED_FILTER", //NON-NLS Bundle.DeletedContent_fsDelFilter_text()),
NbBundle.getMessage(DeletedContent.class, "DeletedContent.fsDelFilter.text")), ALL_DELETED_FILTER(1, "ALL_DELETED_FILTER", //NON-NLS
ALL_DELETED_FILTER(1, Bundle.DeletedContent_allDelFilter_text());
"ALL_DELETED_FILTER", //NON-NLS
NbBundle.getMessage(DeletedContent.class, "DeletedContent.allDelFilter.text"));
private int id; private int id;
private String name; private String name;
private String displayName; private String displayName;
@ -110,15 +112,13 @@ public class DeletedContent implements AutopsyVisitableItem {
public static class DeletedContentsNode extends DisplayableItemNode { public static class DeletedContentsNode extends DisplayableItemNode {
private static final String NAME = NbBundle.getMessage(DeletedContent.class, @NbBundle.Messages("DeletedContent.deletedContentsNode.name=Deleted Files")
"DeletedContent.deletedContentsNode.name"); private static final String NAME = Bundle.DeletedContent_deletedContentsNode_name();
private SleuthkitCase skCase;
DeletedContentsNode(SleuthkitCase skCase) { DeletedContentsNode(SleuthkitCase skCase) {
super(Children.create(new DeletedContentsChildren(skCase), true), Lookups.singleton(NAME)); super(Children.create(new DeletedContentsChildren(skCase), true), Lookups.singleton(NAME));
super.setName(NAME); super.setName(NAME);
super.setDisplayName(NAME); super.setDisplayName(NAME);
this.skCase = skCase;
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
} }
@ -133,6 +133,9 @@ public class DeletedContent implements AutopsyVisitableItem {
} }
@Override @Override
@NbBundle.Messages({
"DeletedContent.createSheet.name.displayName=Name",
"DeletedContent.createSheet.name.desc=no description"})
protected Sheet createSheet() { protected Sheet createSheet() {
Sheet s = super.createSheet(); Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES); Sheet.Set ss = s.get(Sheet.PROPERTIES);
@ -141,9 +144,9 @@ public class DeletedContent implements AutopsyVisitableItem {
s.put(ss); s.put(ss);
} }
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.name.name"), ss.put(new NodeProperty<>("Name", //NON-NLS
NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.name.displayName"), Bundle.DeletedContent_createSheet_name_displayName(),
NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.name.desc"), Bundle.DeletedContent_createSheet_name_desc(),
NAME)); NAME));
return s; return s;
} }
@ -303,6 +306,9 @@ public class DeletedContent implements AutopsyVisitableItem {
} }
@Override @Override
@NbBundle.Messages({
"DeletedContent.createSheet.filterType.displayName=Type",
"DeletedContent.createSheet.filterType.desc=no description"})
protected Sheet createSheet() { protected Sheet createSheet() {
Sheet s = super.createSheet(); Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES); Sheet.Set ss = s.get(Sheet.PROPERTIES);
@ -311,10 +317,9 @@ public class DeletedContent implements AutopsyVisitableItem {
s.put(ss); s.put(ss);
} }
ss.put(new NodeProperty<>( ss.put(new NodeProperty<>("Type", //NON_NLS
NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.filterType.name"), Bundle.DeletedContent_createSheet_filterType_displayName(),
NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.filterType.displayName"), Bundle.DeletedContent_createSheet_filterType_desc(),
NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.filterType.desc"),
filter.getDisplayName())); filter.getDisplayName()));
return s; return s;
@ -334,7 +339,7 @@ public class DeletedContent implements AutopsyVisitableItem {
return DisplayableItemNode.FILE_PARENT_NODE_KEY; return DisplayableItemNode.FILE_PARENT_NODE_KEY;
} }
} }
static class DeletedContentChildren extends ChildFactory.Detachable<AbstractFile> { static class DeletedContentChildren extends ChildFactory.Detachable<AbstractFile> {
private final SleuthkitCase skCase; private final SleuthkitCase skCase;
@ -375,6 +380,10 @@ public class DeletedContent implements AutopsyVisitableItem {
} }
@Override @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) { protected boolean createKeys(List<AbstractFile> list) {
List<AbstractFile> queryList = runFsQuery(); List<AbstractFile> queryList = runFsQuery();
if (queryList.size() == MAX_OBJECTS) { if (queryList.size() == MAX_OBJECTS) {
@ -382,14 +391,10 @@ public class DeletedContent implements AutopsyVisitableItem {
// only show the dialog once - not each time we refresh // only show the dialog once - not each time we refresh
if (maxFilesDialogShown == false) { if (maxFilesDialogShown == false) {
maxFilesDialogShown = true; maxFilesDialogShown = true;
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(()
@Override -> JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
public void run() { DeletedContent_createKeys_maxObjects_msg(MAX_OBJECTS - 1))
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), NbBundle.getMessage(this.getClass(), );
"DeletedContent.createKeys.maxObjects.msg",
MAX_OBJECTS - 1));
}
});
} }
} }
list.addAll(queryList); list.addAll(queryList);
@ -428,14 +433,13 @@ public class DeletedContent implements AutopsyVisitableItem {
logger.log(Level.SEVERE, "Unsupported filter type to get deleted content: {0}", filter); //NON-NLS logger.log(Level.SEVERE, "Unsupported filter type to get deleted content: {0}", filter); //NON-NLS
} }
if(UserPreferences.hideKnownFilesInViewsTree()) { if (UserPreferences.hideKnownFilesInViewsTree()) {
query += " AND (known != " + TskData.FileKnown.KNOWN.getFileKnownValue() //NON-NLS query += " AND (known != " + TskData.FileKnown.KNOWN.getFileKnownValue() //NON-NLS
+ " OR known IS NULL)"; //NON-NLS + " OR known IS NULL)"; //NON-NLS
} }
query += " LIMIT " + MAX_OBJECTS; //NON-NLS query += " LIMIT " + MAX_OBJECTS; //NON-NLS
return query; return query;
} }
@ -456,6 +460,9 @@ public class DeletedContent implements AutopsyVisitableItem {
/** /**
* Get children count without actually loading all nodes * Get children count without actually loading all nodes
* *
* @param sleuthkitCase
* @param filter
*
* @return * @return
*/ */
static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter) { static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter) {
@ -495,9 +502,7 @@ public class DeletedContent implements AutopsyVisitableItem {
@Override @Override
protected AbstractNode defaultVisit(Content di) { protected AbstractNode defaultVisit(Content di) {
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(), throw new UnsupportedOperationException("Not supported for this type of Displayable Item: " + di.toString());
"DeletedContent.createNodeForKey.typeNotSupported.msg",
di.toString()));
} }
}); });
} }

View File

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

View File

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

View File

@ -353,29 +353,14 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
throw new IllegalArgumentException("Empty filter list passed to createQuery()"); // NON-NLS throw new IllegalArgumentException("Empty filter list passed to createQuery()"); // NON-NLS
} }
String query = "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")" return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
+ (UserPreferences.hideKnownFilesInViewsTree() ? " AND (known IS NULL OR known != " + (UserPreferences.hideKnownFilesInViewsTree()
+ TskData.FileKnown.KNOWN.getFileKnownValue() + ")" : " ") ? " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")"
+ " AND (NULL "; //NON-NLS : " ")
+ " AND (extension IN (" + filter.getFilter().stream()
if (skCase.getDatabaseType().equals(TskData.DbType.POSTGRESQL)) { .map(String::toLowerCase)
// For PostgreSQL we get a more efficient query by using builtin .map(s -> "'"+StringUtils.substringAfter(s, ".")+"'")
// regular expression support and or'ing all extensions. We also .collect(Collectors.joining(", ")) + "))";
// 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;
} }
/** /**

View File

@ -79,7 +79,7 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
} }
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, content); fillPropertyMap(map);
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.name.name"), ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.name.displayName"), NbBundle.getMessage(this.getClass(), "LayoutFileNode.createSheet.name.displayName"),
@ -134,11 +134,12 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
} }
actionsList.addAll(ContextMenuExtensionPoint.getActions()); 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()); 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<>(); Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, content); fillPropertyMap(map, getContent());
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "LocalFileNode.createSheet.name.name"), ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "LocalFileNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "LocalFileNode.createSheet.name.displayName"), 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.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.Action;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger; 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.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.VirtualDirectory; 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()); private static final Logger logger = Logger.getLogger(VirtualDirectoryNode.class.getName());
//prefix for special VirtualDirectory root nodes grouping local files //prefix for special VirtualDirectory root nodes grouping local files
public final static String LOGICAL_FILE_SET_PREFIX = "LogicalFileSet"; //NON-NLS 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(); return ld.getName();
} }
public VirtualDirectoryNode(VirtualDirectory ld) { public VirtualDirectoryNode(VirtualDirectory ld) {
super(ld); super(ld);
this.setDisplayName(nameForLayoutFile(ld)); this.setDisplayName(nameForVirtualDirectory(ld));
String name = ld.getName(); String name = ld.getName();
//set icon for name, special case for some built-ins //set icon for name, special case for logical file set
if (name.equals(VirtualDirectory.NAME_UNALLOC)) { if (ld.isDataSource()) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-deleted.png"); //NON-NLS
} else if (ld.isDataSource()) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS 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 { } 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 @Override
@NbBundle.Messages({"VirtualDirectoryNode.action.runIngestMods.text=Run Ingest Modules"}) @NbBundle.Messages({"VirtualDirectoryNode.createSheet.size.name=Size (Bytes)",
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)",
"VirtualDirectoryNode.createSheet.size.displayName=Size (Bytes)", "VirtualDirectoryNode.createSheet.size.displayName=Size (Bytes)",
"VirtualDirectoryNode.createSheet.size.desc=Size of the data source in bytes.", "VirtualDirectoryNode.createSheet.size.desc=Size of the data source in bytes.",
"VirtualDirectoryNode.createSheet.type.name=Type", "VirtualDirectoryNode.createSheet.type.name=Type",
@ -133,7 +89,7 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
if (!this.content.isDataSource()) { if (!this.content.isDataSource()) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, content); fillPropertyMap(map, getContent());
final String NO_DESCR = NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.noDesc"); final String NO_DESCR = NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.noDesc");
for (Map.Entry<String, Object> entry : map.entrySet()) { 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) { public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this); 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.awt.event.ActionEvent;
import java.beans.PropertyVetoException; import java.beans.PropertyVetoException;
import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
@ -43,6 +44,7 @@ import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; 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.FileTypes.FileTypesNode;
import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode;
import org.sleuthkit.autopsy.datamodel.LocalDirectoryNode;
import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo; import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo;
import org.sleuthkit.autopsy.datamodel.Reports; import org.sleuthkit.autopsy.datamodel.Reports;
import org.sleuthkit.autopsy.datamodel.SlackFileNode; import org.sleuthkit.autopsy.datamodel.SlackFileNode;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import static org.sleuthkit.autopsy.directorytree.Bundle.*;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
@ -66,11 +70,13 @@ import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.VirtualDirectory; 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 * 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; 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 * Adds information about which child node of this node, if any, should be
* selected. Can be null. * selected. Can be null.
@ -248,16 +274,20 @@ public class DataResultFilterNode extends FilterNode {
private boolean filterKnown; private boolean filterKnown;
private boolean filterSlack; private boolean filterSlack;
private boolean filterArtifacts; // display message artifacts in the DataSource subtree
/** /**
* the constructor * the constructor
*/ */
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) { private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
super(arg); super(arg);
this.filterArtifacts = false;
switch (SelectionContext.getSelectionContext(arg)) { switch (SelectionContext.getSelectionContext(arg)) {
case DATA_SOURCES: case DATA_SOURCES:
filterSlack = filterSlackFromDataSources; filterSlack = filterSlackFromDataSources;
filterKnown = filterKnownFromDataSources; filterKnown = filterKnownFromDataSources;
filterArtifacts = true;
break; break;
case VIEWS: case VIEWS:
filterSlack = filterSlackFromViews; filterSlack = filterSlackFromViews;
@ -291,6 +321,16 @@ public class DataResultFilterNode extends FilterNode {
return new Node[]{}; 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)}; return new Node[]{new DataResultFilterNode(key, sourceEm, filterKnown, filterSlack)};
} }
} }
@ -350,6 +390,8 @@ public class DataResultFilterNode extends FilterNode {
n = new DirectoryNode((Directory) c); n = new DirectoryNode((Directory) c);
} else if ((c = ban.getLookup().lookup(VirtualDirectory.class)) != null) { } else if ((c = ban.getLookup().lookup(VirtualDirectory.class)) != null) {
n = new VirtualDirectoryNode((VirtualDirectory) c); 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) { } else if ((c = ban.getLookup().lookup(LayoutFile.class)) != null) {
n = new LayoutFileNode((LayoutFile) c); n = new LayoutFileNode((LayoutFile) c);
} else if ((c = ban.getLookup().lookup(LocalFile.class)) != null } else if ((c = ban.getLookup().lookup(LocalFile.class)) != null
@ -459,8 +501,20 @@ public class DataResultFilterNode extends FilterNode {
@Override @Override
public AbstractAction visit(BlackboardArtifactNode ban) { public AbstractAction visit(BlackboardArtifactNode ban) {
return new ViewContextAction( BlackboardArtifact artifact = ban.getArtifact();
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInDir.text"), ban); 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);
} }
@Override @Override

View File

@ -26,16 +26,19 @@ import org.sleuthkit.autopsy.datamodel.DirectoryNode;
import org.openide.nodes.FilterNode; import org.openide.nodes.FilterNode;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode;
import org.sleuthkit.autopsy.datamodel.LocalDirectoryNode;
import org.sleuthkit.autopsy.datamodel.SlackFileNode; import org.sleuthkit.autopsy.datamodel.SlackFileNode;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import org.sleuthkit.autopsy.datamodel.VolumeNode; import org.sleuthkit.autopsy.datamodel.VolumeNode;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
@ -198,7 +201,7 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
List<Content> derivedChildren = node.getContentChildren(); List<Content> derivedChildren = node.getContentChildren();
//child of a file, must be a (derived) file too //child of a file, must be a (derived) file too
for (Content childContent : derivedChildren) { for (Content childContent : derivedChildren) {
if (((AbstractFile) childContent).isDir()) { if ((childContent instanceof AbstractFile) && ((AbstractFile) childContent).isDir()) {
return false; return false;
} else { } else {
try { try {
@ -244,11 +247,26 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
//return ! vdn.hasContentChildren(); //return ! vdn.hasContentChildren();
} }
@Override
public Boolean visit(LocalDirectoryNode ldn) {
return visitDeep(ldn);
}
@Override @Override
public Boolean visit(FileTypesNode ft) { public Boolean visit(FileTypesNode ft) {
return defaultVisit(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> { private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default<Boolean> {
@ -292,10 +310,28 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
//return vdn.hasContentChildren(); //return vdn.hasContentChildren();
} }
@Override
public Boolean visit(LocalDirectoryNode ldn) {
return true;
}
@Override @Override
public Boolean visit(FileTypesNode fileTypes) { public Boolean visit(FileTypesNode fileTypes) {
return defaultVisit(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 javax.swing.Action;
import org.openide.nodes.FilterNode; import org.openide.nodes.FilterNode;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup; import org.openide.util.lookup.ProxyLookup;
import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.AbstractContentNode; import org.sleuthkit.autopsy.datamodel.AbstractContentNode;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction; import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.Image;
@ -77,7 +80,7 @@ class DirectoryTreeFilterNode extends FilterNode {
String name = orig.getDisplayName(); String name = orig.getDisplayName();
if (orig instanceof AbstractContentNode) { if (orig instanceof AbstractContentNode) {
AbstractFile file = getLookup().lookup(AbstractFile.class); AbstractFile file = getLookup().lookup(AbstractFile.class);
if (file != null) { if ((file != null) && (false == (orig instanceof BlackboardArtifactNode)) ){
try { try {
int numVisibleChildren = getVisibleChildCount(file); 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 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; return name;
} }
@ -115,13 +127,17 @@ class DirectoryTreeFilterNode extends FilterNode {
if (purgeKnownFiles || purgeSlackFiles) { if (purgeKnownFiles || purgeSlackFiles) {
// Purge known and/or slack files from the file count // Purge known and/or slack files from the file count
for (int i = 0; i < childList.size(); i++) { for (int i = 0; i < childList.size(); i++) {
AbstractFile childFile = (AbstractFile) childList.get(i); Content child = childList.get(i);
if ((purgeKnownFiles && childFile.getKnown() == TskData.FileKnown.KNOWN) if (child instanceof AbstractFile) {
|| (purgeSlackFiles && childFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) { AbstractFile childFile = (AbstractFile) child;
numVisibleChildren--; if ((purgeKnownFiles && childFile.getKnown() == TskData.FileKnown.KNOWN)
|| (purgeSlackFiles && childFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
numVisibleChildren--;
}
} }
} }
} }
return numVisibleChildren; return numVisibleChildren;
} }

View File

@ -38,6 +38,7 @@ import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.FileSystem; import org.sleuthkit.datamodel.FileSystem;
import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.VirtualDirectory;
import org.sleuthkit.datamodel.Volume; import org.sleuthkit.datamodel.Volume;
@ -119,6 +120,23 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
actionsList.addAll(ContextMenuExtensionPoint.getActions()); actionsList.addAll(ContextMenuExtensionPoint.getActions());
return actionsList; 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 @Override
public List<? extends Action> visit(final DerivedFile d) { public List<? extends Action> visit(final DerivedFile d) {

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

View File

@ -21,12 +21,14 @@ package org.sleuthkit.autopsy.ingest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.FileSystem; import org.sleuthkit.datamodel.FileSystem;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.VirtualDirectory;
@ -38,12 +40,20 @@ final class GetRootDirectoryVisitor extends GetFilesContentVisitor {
@Override @Override
public Collection<AbstractFile> visit(VirtualDirectory ld) { 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 //or when root virt dir is scheduled
Collection<AbstractFile> ret = new ArrayList<>(); Collection<AbstractFile> ret = new ArrayList<>();
ret.add(ld); ret.add(ld);
return ret; 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 @Override
public Collection<AbstractFile> visit(LayoutFile lf) { public Collection<AbstractFile> visit(LayoutFile lf) {
@ -93,4 +103,8 @@ final class GetRootDirectoryVisitor extends GetFilesContentVisitor {
return getAllFromChildren(slackFile); return getAllFromChildren(slackFile);
} }
@Override
public Collection<AbstractFile> visit(BlackboardArtifact art) {
return getAllFromChildren(art);
}
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * 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 String caseName;
private final Path metadataFilePath; private final Path metadataFilePath;
private final Date createDate; private final Date createDate;
private Date lastModfiedDate; private final Date lastAccessedDate;
/** /**
* Constructs a representation of case created by automated ingest. * Constructs a representation of case created by automated ingest.
@ -58,10 +58,10 @@ class AutoIngestCase implements Comparable<AutoIngestCase> {
} }
if (null != fileAttrs) { if (null != fileAttrs) {
createDate = new Date(fileAttrs.creationTime().toMillis()); createDate = new Date(fileAttrs.creationTime().toMillis());
lastModfiedDate = new Date(fileAttrs.lastModifiedTime().toMillis()); lastAccessedDate = new Date(fileAttrs.lastAccessTime().toMillis());
} else { } else {
createDate = new Date(); 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. * time of the case metadata file.
* *
* @return The last accessed date. * @return The last accessed date.
*/ */
Date getLastAccessedDate() { Date getLastAccessedDate() {
try { return this.lastAccessedDate;
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;
} }
/** /**
@ -162,7 +156,7 @@ class AutoIngestCase implements Comparable<AutoIngestCase> {
*/ */
@Override @Override
public int compareTo(AutoIngestCase other) { 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"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" 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"/> <Component id="bnOpen" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="bnRefresh" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="bnShowLog" min="-2" max="-2" attributes="0"/> <Component id="bnShowLog" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/> <EmptySpace max="32767" attributes="0"/>
<Component id="panelFilter" min="-2" max="-2" attributes="0"/> <Component id="rbGroupLabel" 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"/>
<EmptySpace 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> </Group>
<Component id="scrollPaneTable" pref="1007" max="32767" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" 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"/> <Component id="scrollPaneTable" min="-2" pref="450" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="32767" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="panelFilter" min="-2" pref="130" max="-2" attributes="0"/> <Component id="bnOpen" alignment="3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <Component id="bnShowLog" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="1" attributes="0"> <Component id="bnRefresh" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
<Component id="bnOpen" alignment="3" min="-2" max="-2" attributes="0"/> <Group type="103" alignment="1" groupAlignment="3" attributes="0">
<Component id="bnRefresh" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="rbDays" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnShowLog" 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> </Group>
<EmptySpace min="-2" pref="36" max="-2" attributes="0"/> <Component id="panelFilter" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -122,32 +131,16 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <Component id="rbAllCases" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <EmptySpace min="0" pref="0" max="32767" 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"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" 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"/>
<Component id="rbAllCases" min="-2" max="-2" attributes="0"/> <Component id="rbAllCases" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -167,56 +160,6 @@
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="rbAllCasesItemStateChanged"/> <EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="rbAllCasesItemStateChanged"/>
</Events> </Events>
</Component> </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> </SubComponents>
</Container> </Container>
<Component class="javax.swing.JButton" name="bnShowLog"> <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"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnShowLogActionPerformed"/>
</Events> </Events>
</Component> </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> </SubComponents>
</Form> </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_MAX_WIDTH = 250;
private static final int STATUS_COL_PREFERRED_WIDTH = 60; 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_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; private ScheduledThreadPoolExecutor casesTableRefreshExecutor;
/* /*
@ -105,6 +105,14 @@ public final class AutoIngestCasePanel extends JPanel {
public boolean isCellEditable(int row, int column) { public boolean isCellEditable(int row, int column) {
return false; 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(); initComponents();
@ -384,11 +392,11 @@ public final class AutoIngestCasePanel extends JPanel {
bnRefresh = new javax.swing.JButton(); bnRefresh = new javax.swing.JButton();
panelFilter = new javax.swing.JPanel(); panelFilter = new javax.swing.JPanel();
rbAllCases = new javax.swing.JRadioButton(); 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(); 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 setName("Completed Cases"); // NOI18N
@ -428,19 +436,27 @@ public final class AutoIngestCasePanel extends JPanel {
} }
}); });
rbGroupHistoryLength.add(rbMonths); javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter);
org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbMonths.text")); // NOI18N panelFilter.setLayout(panelFilterLayout);
rbMonths.addItemListener(new java.awt.event.ItemListener() { panelFilterLayout.setHorizontalGroup(
public void itemStateChanged(java.awt.event.ItemEvent evt) { panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
rbMonthsItemStateChanged(evt); .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(bnShowLog, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbWeeks.text")); // NOI18N bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.toolTipText")); // NOI18N
rbWeeks.addItemListener(new java.awt.event.ItemListener() { bnShowLog.setEnabled(false);
public void itemStateChanged(java.awt.event.ItemEvent evt) { bnShowLog.addActionListener(new java.awt.event.ActionListener() {
rbWeeksItemStateChanged(evt); 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 rbGroupHistoryLength.add(rbWeeks);
org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbGroupLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbWeeks.text")); // NOI18N
rbWeeks.addItemListener(new java.awt.event.ItemListener() {
javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter); public void itemStateChanged(java.awt.event.ItemEvent evt) {
panelFilter.setLayout(panelFilterLayout); rbWeeksItemStateChanged(evt);
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(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); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
@ -503,35 +496,45 @@ public final class AutoIngestCasePanel extends JPanel {
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(13, 13, 13) .addGap(4, 4, 4)
.addComponent(bnOpen, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(bnOpen, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnRefresh)
.addGap(18, 18, 18)
.addComponent(bnShowLog) .addComponent(bnShowLog)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .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) .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(20, 20, 20)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createSequentialGroup() .addComponent(bnRefresh)
.addComponent(scrollPaneTable, javax.swing.GroupLayout.DEFAULT_SIZE, 1007, Short.MAX_VALUE) .addGap(4, 4, 4))
.addContainerGap()))) .addComponent(scrollPaneTable, javax.swing.GroupLayout.DEFAULT_SIZE, 1007, Short.MAX_VALUE))
.addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(43, 43, 43) .addGap(6, 6, 6)
.addComponent(scrollPaneTable, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE) .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) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(bnOpen)
.addContainerGap()) .addComponent(bnShowLog))
.addGroup(layout.createSequentialGroup() .addComponent(bnRefresh)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnOpen) .addComponent(rbDays)
.addComponent(bnRefresh) .addComponent(rbWeeks)
.addComponent(bnShowLog)) .addComponent(rbMonths)
.addGap(36, 36, 36)))) .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 }// </editor-fold>//GEN-END:initComponents

View File

@ -1,4 +1,11 @@
CTL_OpenAction=Open Case... 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.Case=Case
AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder=Data Source AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder=Data Source
AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName=Host Name AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName=Host Name
@ -8,12 +15,23 @@ AutoIngestDashboard.JobsTableModel.ColumnHeader.CompletedTime=Job Completed
AutoIngestDashboard.JobsTableModel.ColumnHeader.Stage=Stage AutoIngestDashboard.JobsTableModel.ColumnHeader.Stage=Stage
AutoIngestDashboard.JobsTableModel.ColumnHeader.Status=Status AutoIngestDashboard.JobsTableModel.ColumnHeader.Status=Status
AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path
AutoIngestDashboard.bnShowProgress.text=Ingest Progress
AutoIngestDashboard.bnResume.text=Resume AutoIngestDashboard.bnResume.text=Resume
AutoIngestDashboard.bnPause.text=Pause
AutoIngestDashboard.bnPause.confirmHeader=Are you sure you want to 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.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.toolTipTextResume=Resume processing of Pending Jobs
AutoIngestDashboard.bnPause.pausing=Pausing after current job completes... 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.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.StageTime=Time in Stage
AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder=Case Folder AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder=Case Folder
AutoIngestDashboard.JobsTableModel.ColumnHeader.LocalJob= Local Job? 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.ConfirmCopyYes=Copy
CopyFilesPanel.ConfirmCopyNo=Do not copy CopyFilesPanel.ConfirmCopyNo=Do not copy
ConfirmationDialog.ConfirmUnlockHeader=Confirm Case Unlock 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.bnCancelPendingJob.text=Ca&ncel
CopyFilesPanel.tbDestinationCase.text= CopyFilesPanel.tbDestinationCase.text=
CopyFilesPanel.cbThrottleNetwork.text=&Throttle Network 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.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
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 CopyFilesPanel.lbCaseName.text=Case Name
CaseStatusIconCellRenderer.tooltiptext.ok=Images processed successfully 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 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.Complete=Complete
CaseImportPanel.Blank= CaseImportPanel.Blank=
CaseImportPanel.DeleteWarning=Make sure no important files are in the case source directory 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.NonUniqueOutputFolder=Output folder not unique. Skipping
SingleUserCaseImporter.WillImport=Will import: SingleUserCaseImporter.WillImport=Will import:
SingleUserCaseImporter.None=None SingleUserCaseImporter.None=None
@ -195,6 +222,9 @@ ReviewModeCasePanel.StatusIconHeaderText=Status
ReviewModeCasePanel.OutputFolderHeaderText=Output Folder ReviewModeCasePanel.OutputFolderHeaderText=Output Folder
ReviewModeCasePanel.LastAccessedTimeHeaderText=Last Accessed Time ReviewModeCasePanel.LastAccessedTimeHeaderText=Last Accessed Time
CopyFilesPanel.bnOptions.text=&Options 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.ChooseRootDirectory=Choose a root directory for file output
FileExporterSettingsPanel.ChooseReportDirectory=Choose a report directory FileExporterSettingsPanel.ChooseReportDirectory=Choose a report directory
FileExporterSettingsPanel.RuleName=Rule Name 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.NewRuleTooltip_1=Clear the rule editor to begin a new rule
FileExporterSettingsPanel.DeleteTooltip_1=Delete the selected rule FileExporterSettingsPanel.DeleteTooltip_1=Delete the selected rule
FileExporterSettingsPanel.SaveTooltip_1=Save the current 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.bnPrioritizeFolder.label=<AutoIngestDashboard.bnPrioritizeJob.text>
AutoIngestDashboard.bnPrioritizeJob.actionCommand=<AutoIngestDashboard.bnPrioritizeJob.text>
AutoIngestCasePanel.rbDays.text=Days AutoIngestCasePanel.rbDays.text=Days
AutoIngestCasePanel.rbWeeks.text=Weeks AutoIngestCasePanel.rbWeeks.text=Weeks
AutoIngestCasePanel.rbMonths.text=Months AutoIngestCasePanel.rbMonths.text=Months
@ -262,74 +297,4 @@ AutoIngestCasePanel.bnRefresh.text=&Refresh
AutoIngestCasePanel.bnOpen.text=&Open AutoIngestCasePanel.bnOpen.text=&Open
AutoIngestCasePanel.bnShowLog.toolTipText=Display case log file for selected case AutoIngestCasePanel.bnShowLog.toolTipText=Display case log file for selected case
AutoIngestCasePanel.bnShowLog.text=&Show Log AutoIngestCasePanel.bnShowLog.text=&Show Log
AutoIngestCasePanel.rbGroupLabel.text=Show Last 10: AutoIngestCasePanel.rbGroupLabel.text=Show cases accessed in the 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

View File

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

View File

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

View File

@ -6,12 +6,25 @@ List of tags:
image: An image to be ingested image: An image to be ingested
build: the path to the build.xml file build: the path to the build.xml file
indir: the path to input directory 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 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. 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 None of these tags are mandatory, and if nothing is provided the file will be
looked over and ignored. looked over and ignored.

View File

@ -300,11 +300,14 @@ class TskDbDiff(object):
os.chmod (backup_db_file, 0o777) os.chmod (backup_db_file, 0o777)
conn = sqlite3.connect(backup_db_file) 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_parts_table = build_id_vs_parts_table(conn.cursor())
id_vs_info_table = build_id_vs_info_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_fs_info_table = build_id_fs_info_table(conn.cursor())
id_objects_table = build_id_objects_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") conn.text_factory = lambda x: x.decode("utf-8", "ignore")
# Delete the blackboard tables # Delete the blackboard tables
@ -314,7 +317,7 @@ class TskDbDiff(object):
# Write to the database dump # Write to the database dump
with codecs.open(dump_file, "wb", "utf_8") as db_log: with codecs.open(dump_file, "wb", "utf_8") as db_log:
for line in conn.iterdump(): 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) db_log.write('%s\n' % line)
# Now sort the file # Now sort the file
@ -346,12 +349,12 @@ class TskDbDiff(object):
class TskDbDiffException(Exception): class TskDbDiffException(Exception):
pass 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. """ Make testing more consistent and reasonable by doctoring certain db entries.
Args: Args:
line: a String, the line to remove the object id from. 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"') 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"') layout_index = line.find('INSERT INTO "tsk_file_layout"')
data_source_info_index = line.find('INSERT INTO "data_source_info"') data_source_info_index = line.find('INSERT INTO "data_source_info"')
ingest_job_index = line.find('INSERT INTO "ingest_jobs"') ingest_job_index = line.find('INSERT INTO "ingest_jobs"')
parens = line[line.find('(') + 1 : line.rfind(')')] parens = line[line.find('(') + 1 : line.rfind(')')]
fields_list = parens.replace(" ", "").split(',') fields_list = parens.replace(" ", "").split(',')
# remove object ID # remove object ID
if (files_index != -1): if (files_index != -1):
obj_id = fields_list[0] 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:]) + ');') newLine = ('INSERT INTO "tsk_files" VALUES(' + ', '.join(fields_list[1:]) + ');')
return newLine return newLine
# remove object ID # remove object ID
elif (path_index != -1): elif (path_index != -1):
obj_id = fields_list[0] obj_id = int(fields_list[0])
objValue = table[int(obj_id)] objValue = files_table[obj_id]
par_obj_id = objects_table[int(obj_id)] # remove the obj_id from ModuleOutput/EmbeddedFileExtractor directory
par_obj_value = table[par_obj_id] idx_pre = fields_list[1].find('EmbeddedFileExtractor') + len('EmbeddedFileExtractor')
par_obj_name = par_obj_value[par_obj_value.rfind('/')+1:] if idx_pre > -1:
#check the par_id that we insert to the path name when we create uniqueName idx_pos = fields_list[1].find('\\', idx_pre + 2)
pathValue = re.sub(par_obj_name + '_' + str(par_obj_id), par_obj_name, fields_list[1]) 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:]) + ');') newLine = ('INSERT INTO "tsk_files_path" VALUES(' + objValue + ', ' + pathValue + ', ' + ', '.join(fields_list[2:]) + ');')
return newLine return newLine
# remove object ID # remove object ID
elif (layout_index != -1): elif (layout_index != -1):
obj_id = fields_list[0] 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:]) + ');') newLine = ('INSERT INTO "tsk_file_layout" VALUES(' + path + ', ' + ', '.join(fields_list[1:]) + ');')
return newLine return newLine
# remove object ID # remove object ID
@ -403,29 +410,29 @@ def normalize_db_entry(line, table, vs_parts_table, vs_info_table, fs_info_table
except Exception as e: except Exception as e:
return line return line
if obj_id in table.keys(): if obj_id in files_table.keys():
path = table[obj_id] path = files_table[obj_id]
elif obj_id in vs_parts_table.keys(): elif obj_id in vs_parts_table.keys():
path = vs_parts_table[obj_id] path = vs_parts_table[obj_id]
elif obj_id in vs_info_table.keys(): elif obj_id in vs_info_table.keys():
path = vs_info_table[obj_id] path = vs_info_table[obj_id]
elif obj_id in fs_info_table.keys(): elif obj_id in fs_info_table.keys():
path = fs_info_table[obj_id] path = fs_info_table[obj_id]
if parent_id in table.keys(): if parent_id in files_table.keys():
parent_path = table[parent_id] parent_path = files_table[parent_id]
elif parent_id in vs_parts_table.keys(): elif parent_id in vs_parts_table.keys():
parent_path = vs_parts_table[parent_id] parent_path = vs_parts_table[parent_id]
elif parent_id in vs_info_table.keys(): elif parent_id in vs_info_table.keys():
parent_path = vs_info_table[parent_id] parent_path = vs_info_table[parent_id]
elif parent_id in fs_info_table.keys(): elif parent_id in fs_info_table.keys():
parent_path = fs_info_table[parent_id] parent_path = fs_info_table[parent_id]
if path and parent_path: if path and parent_path:
return newLine + path + ', ' + parent_path + ', ' + ', '.join(fields_list[2:]) + ');' return newLine + path + ', ' + parent_path + ', ' + ', '.join(fields_list[2:]) + ');'
else: else:
return line return line
# remove time-based information, ie Test_6/11/14 -> Test # remove time-based information, ie Test_6/11/14 -> Test
elif (report_index != -1): elif (report_index != -1):
fields_list[1] = "AutopsyTestCase" fields_list[1] = "AutopsyTestCase"
@ -467,60 +474,95 @@ def getAssociatedArtifactType(db_file, artifact_id):
return "File path: " + info[0] + " Artifact Type: " + info[1] 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. """Build the map of object ids to file paths.
Args: 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 # 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 # 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 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. """Build the map of object ids to vs_parts.
Args: 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 # 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 # 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 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. """Build the map of object ids to vs_info.
Args: 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 # 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 # 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 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. """Build the map of object ids to fs_info.
Args: 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 # 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 # 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 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. """Build the map of object ids to par_id.
Args: 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 # 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 # with the object id as the key and par_obj_id, type as the value
mapping = dict([(row[0], row[1]) for row in artifact_cursor.execute("SELECT obj_id, par_obj_id FROM tsk_objects")]) 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 return mapping
def main(): def main():

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