Merge remote-tracking branch 'upstream/release-4.7.0' into 967-don't-show-secondary-relationships-by-default

This commit is contained in:
millmanorama 2018-04-04 14:14:06 +02:00
commit 6c4573f15b
21 changed files with 1001 additions and 855 deletions

3
.gitignore vendored
View File

@ -78,3 +78,6 @@ hs_err_pid*.log
/RecentActivity/release/
/CentralRepository/release/
*.img
*.vhd
*.E01

22
.travis.yml Normal file
View File

@ -0,0 +1,22 @@
language: java
sudo: required
dist: trusty
os:
- linux
env:
global:
- TSK_HOME=$TRAVIS_BUILD_DIR/sleuthkit/sleuthkit
jdk:
- oraclejdk8
before_install:
- git clone https://github.com/sleuthkit/sleuthkit.git sleuthkit/sleuthkit
install:
- sudo apt-get install testdisk
- cd sleuthkit/sleuthkit
- sh install-sleuthkit.sh
script:
- cd $TRAVIS_BUILD_DIR/
- ant build
- cd Core/
- xvfb-run ant test

View File

@ -12,7 +12,7 @@
<property name="thirdparty.dir" value="${basedir}/../thirdparty" />
<property name="modules.dir" value="${basedir}/release/modules/" />
<property name="ext.dir" value="${modules.dir}/ext" />
<property name="test-input" location="test"/>
<property name="test-input" location="test/qa-functional/data"/>
<target name="get-InternalPythonModules" description="get internal python modules">
<copy todir="release/InternalPythonModules" >
@ -83,6 +83,7 @@
</target>
<target name="getImageFile">
<mkdir dir="${basedir}/test/qa-functional/data"/>
<get src="https://drive.google.com/uc?id=0BxdBkzm5VKGNT0dGY0dqcHVsU3M" dest="${test-input}/filter_test1.img" skipexisting="true"/>
</target>
<target name="get-deps" depends="init-ivy,getTSKJars,get-thirdparty-dependencies,get-InternalPythonModules, download-binlist, getImageFile">

View File

@ -176,9 +176,15 @@ public abstract class AbstractSqlEamDb implements EamDb {
* @returns New Case class with populated database ID
*/
@Override
public CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException {
Connection conn = connect();
public synchronized CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException {
// check if there is already an existing CorrelationCase for this Case
CorrelationCase cRCase = getCaseByUUID(eamCase.getCaseUUID());
if (cRCase != null) {
return cRCase;
}
Connection conn = connect();
PreparedStatement preparedStatement = null;
String sql = "INSERT INTO cases(case_uid, org_id, case_name, creation_date, case_number, "

View File

@ -39,7 +39,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.FileTypeViewer;
@ServiceProvider(service = DataContentViewer.class, position = 3)
public class FileViewer extends javax.swing.JPanel implements DataContentViewer {
private static final int CONFIDENCE_LEVEL = 7;
private static final int CONFIDENCE_LEVEL = 5;
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(FileViewer.class.getName());

View File

@ -503,7 +503,6 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
rtfbodyTextPane.setText("");
htmlbodyTextPane.setText("");
textbodyTextArea.setText("");
drp.setNode(null);
showImagesToggleButton.setEnabled(false);
msgbodyTabbedPane.setEnabled(false);
}
@ -546,7 +545,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
@Override
public int isPreferred(Node node) {
if (isSupported(node)) {
return 6;
return 7;
}
return 0;
}

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.contentviewers;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Cursor;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
@ -36,12 +37,8 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
@ -71,7 +68,6 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
private Connection connection;
private int numRows; // num of rows in the selected table
private int currPage = 0; // curr page of rows being displayed
private SwingWorker<? extends Object, ? extends Object> worker;
/**
* Constructs a file content viewer for SQLite database files.
@ -213,6 +209,7 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
}// </editor-fold>//GEN-END:initComponents
private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
currPage++;
if (currPage * ROWS_PER_PAGE > numRows) {
nextPageButton.setEnabled(false);
@ -223,9 +220,12 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
// read and display a page of rows
String tableName = (String) this.tablesDropdownList.getSelectedItem();
readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE);
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}//GEN-LAST:event_nextPageButtonActionPerformed
private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
currPage--;
if (currPage == 1) {
prevPageButton.setEnabled(false);
@ -236,6 +236,7 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
// read and display a page of rows
String tableName = (String) this.tablesDropdownList.getSelectedItem();
readTable(tableName, (currPage - 1) * ROWS_PER_PAGE + 1, ROWS_PER_PAGE);
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}//GEN-LAST:event_prevPageButtonActionPerformed
private void tablesDropdownListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tablesDropdownListActionPerformed
@ -244,7 +245,9 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
if (null == tableName) {
return;
}
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
selectTable(tableName);
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}//GEN-LAST:event_tablesDropdownListActionPerformed
@ -269,8 +272,10 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
@Override
public void setFile(AbstractFile file) {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
sqliteDbFile = file;
processSQLiteFile();
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
@Override
@ -294,12 +299,6 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
}
}
// delete last temp file
if (null != tmpDbFile) {
tmpDbFile.delete();
tmpDbFile = null;
}
sqliteDbFile = null;
}
@ -315,34 +314,40 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
"SQLiteViewer.errorMessage.failedToinitJDBCDriver=The JDBC driver for SQLite could not be loaded.",
"# {0} - exception message", "SQLiteViewer.errorMessage.unexpectedError=An unexpected error occurred:\n{0).",})
private void processSQLiteFile() {
SwingUtilities.invokeLater(() -> {
tablesDropdownList.removeAllItems();
});
new SwingWorker<Map<String, String>, Void>() {
@Override
protected Map<String, String> doInBackground() throws NoCurrentCaseException, TskCoreException, IOException, SQLException, ClassNotFoundException {
// Copy the file to temp folder
String tmpDBPathName = Case.getOpenCase().getTempDirectory() + File.separator + sqliteDbFile.getName();
String tmpDBPathName;
try {
tmpDBPathName = Case.getOpenCase().getTempDirectory() + File.separator + sqliteDbFile.getName();
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Current case has been closed", ex); //NON-NLS
MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_errorMessage_noCurrentCase());
return;
}
tmpDbFile = new File(tmpDBPathName);
if (! tmpDbFile.exists()) {
try {
ContentUtils.writeToFile(sqliteDbFile, tmpDbFile);
// Look for any meta files associated with this DB - WAL, SHM, etc.
findAndCopySQLiteMetaFile(sqliteDbFile, sqliteDbFile.getName() + "-wal");
findAndCopySQLiteMetaFile(sqliteDbFile, sqliteDbFile.getName() + "-shm");
} catch (IOException | NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Failed to create temp copy of DB file '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_errorMessage_failedToExtractFile());
return;
}
}
try {
// Load the SQLite JDBC driver, if necessary.
Class.forName("org.sqlite.JDBC"); //NON-NLS
connection = DriverManager.getConnection("jdbc:sqlite:" + tmpDBPathName); //NON-NLS
// Query the file for the table names and schemas.
return getTables();
}
@Override
protected void done() {
super.done();
try {
Map<String, String> dbTablesMap = get();
Map<String, String> dbTablesMap = getTables();
if (dbTablesMap.isEmpty()) {
tablesDropdownList.addItem(Bundle.SQLiteViewer_comboBox_noTableEntry());
tablesDropdownList.setEnabled(false);
@ -351,32 +356,13 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
tablesDropdownList.addItem(tableName);
});
}
} catch (InterruptedException ex) {
logger.log(Level.SEVERE, String.format("Interrupted while opening SQLite database file '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_errorMessage_interrupted());
} catch (ExecutionException ex) {
String errorMessage;
Throwable cause = ex.getCause();
if (cause instanceof NoCurrentCaseException) {
logger.log(Level.SEVERE, "Current case has been closed", ex); //NON-NLS
errorMessage = Bundle.SQLiteViewer_errorMessage_noCurrentCase();
} else if (cause instanceof TskCoreException || cause instanceof IOException) {
logger.log(Level.SEVERE, String.format("Failed to create temp copy of DB file '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
errorMessage = Bundle.SQLiteViewer_errorMessage_failedToExtractFile();
} else if (cause instanceof SQLException) {
logger.log(Level.SEVERE, String.format("Failed to get tables from DB file '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
errorMessage = Bundle.SQLiteViewer_errorMessage_failedToQueryDatabase();
} else if (cause instanceof ClassNotFoundException) {
} catch (ClassNotFoundException ex) {
logger.log(Level.SEVERE, String.format("Failed to initialize JDBC SQLite '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
errorMessage = Bundle.SQLiteViewer_errorMessage_failedToinitJDBCDriver();
} else {
logger.log(Level.SEVERE, String.format("Unexpected exception while processing DB file '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
errorMessage = Bundle.SQLiteViewer_errorMessage_unexpectedError(cause.getLocalizedMessage());
MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_errorMessage_failedToinitJDBCDriver());
} catch (SQLException ex) {
logger.log(Level.SEVERE, String.format("Failed to get tables from DB file '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_errorMessage_failedToQueryDatabase());
}
MessageNotifyUtil.Message.error(errorMessage);
}
}
}.execute();
}
/**
@ -436,41 +422,12 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
"SQLiteViewer.selectTable.errorText=Error getting row count for table: {0}"
})
private void selectTable(String tableName) {
if (worker != null && !worker.isDone()) {
worker.cancel(false);
worker = null;
}
worker = new SwingWorker<Integer, Void>() {
@Override
protected Integer doInBackground() throws Exception {
try (Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(
"SELECT count (*) as count FROM " + tableName)) { //NON-NLS{
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connection.createStatement();
resultSet = statement.executeQuery(
"SELECT count (*) as count FROM " + tableName); //NON-NLS
return resultSet.getInt("count");
} catch (SQLException ex) {
throw ex;
} finally {
if (null != resultSet) {
resultSet.close();
}
if (null != statement) {
statement.close();
}
}
}
@Override
protected void done() {
super.done();
try {
numRows = get();
numRows = resultSet.getInt("count");
numEntriesField.setText(numRows + " entries");
currPage = 1;
@ -487,93 +444,34 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
selectedTableView.setupTable(Collections.emptyList());
}
} catch (InterruptedException ex) {
logger.log(Level.SEVERE, "Interrupted while getting row count from table " + tableName, ex); //NON-NLS
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
ex.getMessage(),
Bundle.SQLiteViewer_selectTable_errorText(tableName),
JOptionPane.ERROR_MESSAGE);
} catch (ExecutionException ex) {
logger.log(Level.SEVERE, "Unexpected exception while getting row count from table " + tableName, ex); //NON-NLS
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
ex.getCause().getMessage(),
Bundle.SQLiteViewer_selectTable_errorText(tableName),
JOptionPane.ERROR_MESSAGE);
} catch (SQLException ex) {
logger.log(Level.SEVERE, String.format("Failed to load table %s from DB file '%s' (objId=%d)", tableName, sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_selectTable_errorText(tableName));
}
}
};
worker.execute();
}
@NbBundle.Messages({"# {0} - tableName",
"SQLiteViewer.readTable.errorText=Error getting rows for table: {0}"})
private void readTable(String tableName, int startRow, int numRowsToRead) {
if (worker != null && !worker.isDone()) {
worker.cancel(false);
worker = null;
}
worker = new SwingWorker<ArrayList<Map<String, Object>>, Void>() {
@Override
protected ArrayList<Map<String, Object>> doInBackground() throws Exception {
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connection.createStatement();
resultSet = statement.executeQuery(
try (
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(
"SELECT * FROM " + tableName
+ " LIMIT " + Integer.toString(numRowsToRead)
+ " OFFSET " + Integer.toString(startRow - 1)
); //NON-NLS
+ " OFFSET " + Integer.toString(startRow - 1))) {
return resultSetToArrayList(resultSet);
} catch (SQLException ex) {
throw ex;
} finally {
if (null != resultSet) {
resultSet.close();
}
if (null != statement) {
statement.close();
}
}
}
@Override
protected void done() {
if (isCancelled()) {
return;
}
super.done();
try {
ArrayList<Map<String, Object>> rows = get();
ArrayList<Map<String, Object>> rows = resultSetToArrayList(resultSet);
if (Objects.nonNull(rows)) {
selectedTableView.setupTable(rows);
} else {
selectedTableView.setupTable(Collections.emptyList());
}
} catch (InterruptedException ex) {
logger.log(Level.SEVERE, "Interrupted while reading table " + tableName, ex); //NON-NLS
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
ex.getMessage(),
Bundle.SQLiteViewer_readTable_errorText(tableName),
JOptionPane.ERROR_MESSAGE);
} catch (ExecutionException ex) {
logger.log(Level.SEVERE, "Unexpected exception while reading table " + tableName, ex); //NON-NLS
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
ex.getCause().getMessage(),
Bundle.SQLiteViewer_readTable_errorText(tableName),
JOptionPane.ERROR_MESSAGE);
} catch (SQLException ex) {
logger.log(Level.SEVERE, String.format("Failed to read table %s from DB file '%s' (objId=%d)", tableName, sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_readTable_errorText(tableName));
}
}
};
worker.execute();
}
@NbBundle.Messages("SQLiteViewer.BlobNotShown.message=BLOB Data not shown")
private ArrayList<Map<String, Object>> resultSetToArrayList(ResultSet rs) throws SQLException {

View File

@ -89,15 +89,45 @@ public interface DataContentViewer {
* subjective, but the idea is that Autopsy wants to display the most
* relevant tab. The more generic the viewer, the lower the return value
* should be. This will only be called on viewers that support the given
* node.
* node (i.e., isSupported() has already returned true).
*
* The following are some examples of the current levels in use. If the selected
* node is an artifact, the level may be determined by both the artifact and its
* associated file.
*
* Level 7 - Based on the artifact, if any, in the selected node and specific
* to an artifact type or types. Current content viewers that can return level 7 are
* the Messages tab (only supported for email and SMS) and the Indexed Text tab
* when the selected node is a Keyword Search hit.
*
* Level 6 - Based on the artifact, if any, in the selected node but not
* restricted to particular types. The current content viewer that can return level 6
* is the Results tab. It returns this level for most artifact types,
* unless the associated file is assumed to be of greater interest (for example,
* a Hash Set Hit will not be level 6 because the file itself is of greater interest).
*
* Level 5 - Based on the file in the selected node and very specific to the file type. The current
* content viewer that will return level 5 is
* the Application tab, which supports media files (such as images) and
* certain types of databases.
*
* Level 4 - Based on the file in the selected node but fairly general.
* Currently this is the level returned by the Indexed Text tab if Keyword Search
* has been run (unless the node is a Keyword Search hit or a Credit Card account).
* This is the default tab for most files.
*
* Level 3 - Based on the artifact, if any, in the selected node where the
* artifact is thought to be of less interest than the associated file. This
* level is returned by the Results tab for artifacts like Hash Set Hits.
*
* Level 1 - Very general and should always be available. The Hex, Strings, and Metadata tabs
* are all this level
*
* Level 0 - For cases where the content viewer should never be displayed by default.
*
* @param node Node to check for preference
*
* @return an int (0-10) higher return means the viewer has higher priority
* 0 means not supported 1 to 2 means the module will display all
* file types (such as the hex viewer) 3-10 are prioritized by
* Content viewer developer. Modules that operate on very few file
* types should be towards 10.
*/
public int isPreferred(Node node);
}

View File

@ -24,7 +24,7 @@ DataContentViewerString.pageLabel2.text=Page
# Product Information panel
LBL_Description=<div style=\"font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif;\">\n <b>Product Version:</b> {0} ({9}) <br><b>Sleuth Kit Version:</b> {7} <br><b>Netbeans RCP Build:</b> {8} <br> <b>Java:</b> {1}; {2}<br> <b>System:</b> {3}; {4}; {5}<br><b>Userdir:</b> {6}</div>
Format_OperatingSystem_Value={0} version {1} running on {2}
LBL_Copyright=<div style\="font-size\: 12pt; font-family\: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style\="color\: \#1E2A60;" href\="http\://www.sleuthkit.org">http\://www.sleuthkit.org</a>.</li><li>Training: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/autopsy-training">http://www.basistech.com/autopsy-training</a></li><li>Commercial Support: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/digital-forensics/autopsy/support/">http://www.basistech.com/digital-forensics/autopsy/support/</a></li></ul>Copyright &copy; 2003-2017. </div>
LBL_Copyright=<div style\="font-size\: 12pt; font-family\: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style\="color\: \#1E2A60;" href\="http\://www.sleuthkit.org">http\://www.sleuthkit.org</a>.</li><li>Training: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/autopsy-training">http://www.basistech.com/autopsy-training</a></li><li>Commercial Support: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/digital-forensics/autopsy/support/">http://www.basistech.com/digital-forensics/autopsy/support/</a></li></ul>Copyright &copy; 2003-2018. </div>
URL_ON_IMG=http://www.sleuthkit.org/
URL_ON_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.6.0/
FILE_FOR_LOCAL_HELP=file:///

View File

@ -477,7 +477,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID())) {
return 3;
} else {
return 5;
return 6;
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,21 +19,31 @@
package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.util.Locale;
import javax.swing.JComboBox;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.python.icu.text.NumberFormat;
import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException;
/**
*
* @author pmartel
* Filter search size input.
*/
class SizeSearchFilter extends AbstractFileSearchFilter<SizeSearchPanel> {
/**
* Instantiate a SizeSearchFilter object for a new SizeSearchPanel.
*/
SizeSearchFilter() {
this(new SizeSearchPanel());
}
/**
* Instantiate a SizeSearchFilter object for an existing SizeSearchPanel.
*
* @param component The SizeSearchPanel instance.
*/
SizeSearchFilter(SizeSearchPanel component) {
super(component);
}
@ -53,6 +63,14 @@ class SizeSearchFilter extends AbstractFileSearchFilter<SizeSearchPanel> {
return "size " + operator + " " + size; //NON-NLS
}
/**
* Get the comparison operator associated with the size comparison
* drop-down selection.
*
* @param compare The drop-down component.
*
* @return The operator.
*/
private String compareComboBoxToOperator(JComboBox<String> compare) {
String compareSize = compare.getSelectedItem().toString();
@ -75,7 +93,7 @@ class SizeSearchFilter extends AbstractFileSearchFilter<SizeSearchPanel> {
}
@Override
@Messages ({
@Messages({
"SizeSearchFilter.errorMessage.nonNegativeNumber=Input size data is a negative number.",
"SizeSearchFilter.errorMessage.notANumber=Input size data is not a number."
})
@ -83,12 +101,12 @@ class SizeSearchFilter extends AbstractFileSearchFilter<SizeSearchPanel> {
String input = this.getComponent().getSizeTextField().getText();
try {
int inputInt = Integer.parseInt(input);
int inputInt = NumberFormat.getNumberInstance(Locale.US).parse(input).intValue();
if (inputInt < 0) {
setLastError(Bundle.SizeSearchFilter_errorMessage_nonNegativeNumber());
return false;
}
} catch (NumberFormatException | NullPointerException e) {
} catch (ParseException ex) {
setLastError(Bundle.SizeSearchFilter_errorMessage_notANumber());
return false;
}

View File

@ -410,11 +410,18 @@ final class IngestTasksScheduler {
}
/*
* Check if the file is a member of the file ingest filter that is being
* applied to the current run of ingest, checks if unallocated space
* should be processed inside call to fileIsMemberOf
* Ensures that all directories, files which are members of the ingest
* file filter, and unallocated blocks (when processUnallocated is
* enabled) all continue to be processed. AbstractFiles which do not
* meet one of these criteria will be skipped.
*
* An additional check to see if unallocated space should be processed
* is part of the FilesSet.fileIsMemberOf() method.
*
* This code may need to be updated when
* TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS comes into use by Autopsy.
*/
if (!file.isDir() && task.getIngestJob().getFileIngestFilter().fileIsMemberOf(file) == null) {
if (!file.isDir() && !shouldBeCarved(task) && !fileAcceptedByFilter(task)) {
return false;
}
@ -462,6 +469,30 @@ final class IngestTasksScheduler {
return true;
}
/**
* Check whether or not a file should be carved for a data source ingest
* ingest job.
*
* @param task The file ingest task for the file.
*
* @return True or false.
*/
private static boolean shouldBeCarved(final FileIngestTask task) {
return task.getIngestJob().shouldProcessUnallocatedSpace() && task.getFile().getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS);
}
/**
* Checks whether or not a file is accepted (passes) the file filter for a data
* source ingest job.
*
* @param task The file ingest task for the file.
*
* @return True or false.
*/
private static boolean fileAcceptedByFilter(final FileIngestTask task) {
return !(task.getIngestJob().getFileIngestFilter().fileIsMemberOf(task.getFile()) == null);
}
/**
* Checks whether or not a collection of ingest tasks includes a task for a
* given data source ingest job.

Binary file not shown.

View File

@ -23,6 +23,7 @@ import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static junit.framework.Assert.assertFalse;
import junit.framework.TestCase;
@ -32,6 +33,7 @@ import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseDetails;
import junit.framework.Test;
import org.apache.commons.io.FileUtils;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Exceptions;
import org.python.icu.impl.Assert;
import org.sleuthkit.autopsy.casemodule.ImageDSProcessor;
@ -40,18 +42,23 @@ import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.MetaTypeCondition;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.ParentPathCondition;
import org.sleuthkit.autopsy.testutils.DataSourceProcessorRunner;
import org.sleuthkit.autopsy.testutils.DataSourceProcessorRunner.ProcessorCallback;
import org.sleuthkit.autopsy.testutils.IngestJobRunner;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
public class IngestFileFiltersTest extends TestCase {
public class IngestFileFiltersTest extends NbTestCase {
private static final Path CASE_DIRECTORY_PATH = Paths.get(System.getProperty("java.io.tmpdir"), "IngestFileFiltersTest");
private static final File CASE_DIR = new File(CASE_DIRECTORY_PATH.toString());
private static final Path IMAGE_PATH = Paths.get("test/filter_test1.img");
private final Path IMAGE_PATH = Paths.get(this.getDataDir().toString(),"filter_test1.img");
public static Test suite() {
NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestFileFiltersTest.class).
@ -60,6 +67,10 @@ public class IngestFileFiltersTest extends TestCase {
return conf.suite();
}
public IngestFileFiltersTest(String name) {
super(name);
}
@Override
public void setUp() {
// Delete the test directory, if it exists
@ -116,28 +127,48 @@ public class IngestFileFiltersTest extends TestCase {
assertFalse(CASE_DIR.exists());
}
public void testFileType() {
public void testBasicDir() {
HashMap<String, Rule> rule = new HashMap<>();
rule.put("Rule", new Rule("testFileType", null, new MetaTypeCondition(MetaTypeCondition.Type.FILES), new ParentPathCondition("dir1"), null, null, null));
//Filter for dir1 and no unallocated space
FilesSet Files_Dirs_Unalloc_Ingest_Filter = new FilesSet("Filter", "Filter to find all files in dir1.", false, true, rule);
try {
Case openCase = Case.getOpenCase();
runIngestJob(openCase.getDataSources());
runIngestJob(openCase.getDataSources(), Files_Dirs_Unalloc_Ingest_Filter);
FileManager fileManager = openCase.getServices().getFileManager();
List<AbstractFile> results = fileManager.findFiles("file.jpg", "dir1");
String mimeType = results.get(0).getMIMEType();
assertEquals("image/jpeg", mimeType);
results = fileManager.findFiles("%%");
for (AbstractFile file : results) {
//All files in dir1 should have MIME type, except '.' '..' and slack files
if (file.getParentPath().equalsIgnoreCase("/dir1/")) {
if (!(file.getName().equals(".") || file.getName().equals("..") || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
String errMsg = String.format("File %s (objId=%d) unexpectedly blocked by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, !(file.getMIMEType() == null || file.getMIMEType().isEmpty()));
}
} else { //All files not in dir1 shouldn't have MIME type
String errMsg = String.format("File %s (objId=%d) unexpectedly passed by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, file.getMIMEType() == null);
}
}
} catch (NoCurrentCaseException | TskCoreException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
private void runIngestJob(List<Content> datasources) {
private void runIngestJob(List<Content> datasources, FilesSet filter) {
FileTypeIdModuleFactory factory = new FileTypeIdModuleFactory();
IngestModuleIngestJobSettings settings = factory.getDefaultIngestJobSettings();
IngestModuleTemplate template = new IngestModuleTemplate(factory, settings);
template.setEnabled(true);
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(template);
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestType.FILES_ONLY, templates);
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestType.FILES_ONLY, templates, filter);
try {
List<IngestModuleError> errs = IngestJobRunner.runIngestJob(datasources, ingestJobSettings);
assertEquals(0, errs.size());
@ -146,4 +177,5 @@ public class IngestFileFiltersTest extends TestCase {
Assert.fail(ex);
}
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,80 +23,89 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content;
/*
* A runnable that adds a raw data source to a case database.
* A runnable that adds a memory image data source to a case database.
*/
final class AddMemoryImageTask implements Runnable {
private static final Logger logger = Logger.getLogger(AddMemoryImageTask.class.getName());
private final static Logger logger = Logger.getLogger(AddMemoryImageTask.class.getName());
private final String deviceId;
private final String imageFilePath;
private final String memoryImagePath;
private final String timeZone;
private final List<String> pluginsToRun;
private final DataSourceProcessorProgressMonitor progressMonitor;
private final DataSourceProcessorCallback callback;
private VolatilityProcessor volatilityProcessor = null;
private boolean isCancelled = false;
private volatile VolatilityProcessor volatilityProcessor;
private volatile boolean isCancelled;
/**
* Constructs a runnable that adds a raw data source to a case database.
* Constructs a runnable that adds a memory image to a case database.
*
* @param deviceId An ASCII-printable identifier for the
* device associated with the data source
* that is intended to be unique across
* multiple cases (e.g., a UUID).
* @param imageFilePath Path to a Raw data source file.
* @param timeZone The time zone to use when processing dates
* and times for the image, obtained from
* @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is intended
* to be unique across multiple cases (e.g., a UUID).
* @param memoryImagePath Path to the memory image file.
* @param pluginsToRun The Volatility plugins to run.
* @param timeZone The time zone to use when processing dates and
* times for the image, obtained from
* java.util.TimeZone.getID.
* @param breakupChunks 2GB or not breakup.
* @param progressMonitor Progress monitor for reporting
* progressMonitor during processing.
* @param progressMonitor Progress monitor for reporting progressMonitor
* during processing.
* @param callback Callback to call when processing is done.
*/
AddMemoryImageTask(String deviceId, String imageFilePath, List<String> PluginsToRun, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
AddMemoryImageTask(String deviceId, String memoryImagePath, List<String> pluginsToRun, String timeZone, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
this.deviceId = deviceId;
this.imageFilePath = imageFilePath;
this.pluginsToRun = PluginsToRun;
this.memoryImagePath = memoryImagePath;
this.pluginsToRun = pluginsToRun;
this.timeZone = timeZone;
this.callback = callback;
this.progressMonitor = progressMonitor;
}
/**
* Adds a raw data source to a case database.
* Adds a memory image data source to a case database.
*/
@Messages({
"# {0} - exception message",
"AddMemoryImageTask_errorMessage_criticalException= Critical error: {0}",
})
@Override
public void run() {
if (isCancelled) {
return;
}
progressMonitor.setIndeterminate(true);
progressMonitor.setProgress(0);
List<Content> dataSources = new ArrayList<>();
List<String> errorMessages = new ArrayList<>();
boolean criticalErrorOccurred = false;
Image dataSource = addImageToCase(errorMessages);
if (dataSource == null) {
criticalErrorOccurred = true;
}
/* call Volatility to process the image */
else {
if (isCancelled)
return;
volatilityProcessor = new VolatilityProcessor(imageFilePath, dataSource, pluginsToRun, progressMonitor);
if (volatilityProcessor.run()) {
try {
Image dataSource = addImageToCase();
dataSources.add(dataSource);
volatilityProcessor = new VolatilityProcessor(memoryImagePath, dataSource, pluginsToRun, progressMonitor);
volatilityProcessor.run();
} catch (NoCurrentCaseException | TskCoreException | VolatilityProcessor.VolatilityProcessorException ex) {
criticalErrorOccurred = true;
errorMessages.add(Bundle.AddMemoryImageTask_errorMessage_criticalException(ex.getLocalizedMessage()));
/*
* Log the exception as well as add it to the error messages, to
* ensure that the stack trace is not lost.
*/
logger.log(Level.SEVERE, String.format("Critical error processing memory image data source at %s for device %s", memoryImagePath, deviceId), ex);
}
errorMessages.addAll(volatilityProcessor.getErrorMessages());
}
progressMonitor.setProgress(100);
/**
@ -110,55 +119,64 @@ final class AddMemoryImageTask implements Runnable {
} else {
result = DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS;
}
callback.done(result, errorMessages, new ArrayList<>(Arrays.asList(dataSource)));
callback.done(result, errorMessages, dataSources);
}
/**
* Attempts to add the input image to the case.
* Attempts to add the input memory image to the case as a data source.
*
* @param errorMessages If there are any error messages, the error messages
* are added to this list for eventual return to the
* caller via the callback.
* @returns Image that was added to DB or null on error
* @return The Image object representation of the memeory image file data
* source.
*
* @throws NoCurrentCaseException If there is no current case.
* @throws TskCoreException If there is an error adding the data
* source to the case database.
*/
@Messages({"AddMemoryImageTask.progress.add.text=Adding memory image: ",
"AddMemoryImageTask.image.critical.error.adding=Critical error adding ",
"AddMemoryImageTask.for.device=for device ",
"AddMemoryImageTask.image.notExisting=is not existing.",
"AddMemoryImageTask.image.noncritical.error.adding=Non-critical error adding "})
private Image addImageToCase(List<String> errorMessages) {
progressMonitor.setProgressText(Bundle.AddMemoryImageTask_progress_add_text() + imageFilePath);
SleuthkitCase caseDatabase = Case.getCurrentCase().getSleuthkitCase();
caseDatabase.acquireExclusiveLock();
// verify it exists
File imageFile = Paths.get(imageFilePath).toFile();
if (!imageFile.exists()) {
errorMessages.add(Bundle.AddMemoryImageTask_image_critical_error_adding() + imageFilePath + Bundle.AddMemoryImageTask_for_device()
+ deviceId + Bundle.AddMemoryImageTask_image_notExisting());
return null;
}
@Messages({
"# {0} - image file path",
"AddMemoryImageTask_progressMessage_addingImageFile= Adding memory image {0}",
"# {0} - image file path",
"# {1} - device id",
"AddMemoryImageTask_exceptionMessage_noImageFile= Memory image file {0} for device {1} does not exist"
})
private Image addImageToCase() throws NoCurrentCaseException, TskCoreException {
progressMonitor.setProgressText(Bundle.AddMemoryImageTask_progressMessage_addingImageFile( memoryImagePath));
SleuthkitCase caseDatabase = Case.getOpenCase().getSleuthkitCase();
caseDatabase.acquireSingleUserCaseWriteLock();
try {
// add it to the DB
List<String> imageFilePaths = new ArrayList<>();
imageFilePaths.add(imageFilePath);
Image dataSource = caseDatabase.addImageInfo(0, imageFilePaths, timeZone); //TODO: change hard coded deviceId.
/*
* Verify the memory image file exists.
*/
File imageFile = Paths.get(memoryImagePath).toFile();
if (!imageFile.exists()) {
throw new TskCoreException(Bundle.AddMemoryImageTask_exceptionMessage_noImageFile(memoryImagePath, deviceId));
}
/*
* Add the data source.
*
* NOTE: The object id for device passed to
* SleuthkitCase.addImageInfo is hard-coded to zero for now. This
* will need to be changed when a Device abstraction is added to the
* SleuthKit data model.
*/
Image dataSource = caseDatabase.addImageInfo(0, new ArrayList<>(Arrays.asList(memoryImagePath)), timeZone);
return dataSource;
} catch (TskCoreException ex) {
errorMessages.add(Bundle.AddMemoryImageTask_image_critical_error_adding() + imageFilePath + Bundle.AddMemoryImageTask_for_device() + deviceId + ":" + ex.getLocalizedMessage());
return null;
} finally {
caseDatabase.releaseExclusiveLock();
caseDatabase.releaseSingleUserCaseWriteLock();
}
}
/**
* Requests cancellation of this task by setting a cancelled flag.
*/
void cancelTask() {
isCancelled = true;
if (volatilityProcessor != null) {
volatilityProcessor.cancel();
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -37,11 +37,13 @@ import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PathValidator;
final class MemoryDSInputPanel extends JPanel implements DocumentListener {
private static final long serialVersionUID = 1L; //default
private final String PROP_LASTINPUT_PATH = "LBL_LastInputFile_PATH";
private final JFileChooser fc = new JFileChooser();
@ -57,7 +59,7 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
* Creates new MemoryDSInputPanel panel for user input
*/
private MemoryDSInputPanel(String context) {
this.pluginList = new String[]{"amcache","cmdline","cmdscan","consoles","malfind","netscan","notepad","pslist","psxview","shellbags","shimcache","shutdown","userassist", "apihooks","connscan","devicetree","dlllist","envars","filescan","gahti","getservicesids","getsids","handles","hashdump","hivelist","hivescan","impscan","ldrmodules","lsadump","modules","mutantscan","privs","psscan","pstree","sockets","svcscan","shimcache","timeliner","unloadedmodules","userhandles","vadinfo","verinfo"};
this.pluginList = new String[]{"amcache", "cmdline", "cmdscan", "consoles", "malfind", "netscan", "notepad", "pslist", "psxview", "shellbags", "shimcache", "shutdown", "userassist", "apihooks", "connscan", "devicetree", "dlllist", "envars", "filescan", "gahti", "getservicesids", "getsids", "handles", "hashdump", "hivelist", "hivescan", "impscan", "ldrmodules", "lsadump", "modules", "mutantscan", "privs", "psscan", "pstree", "sockets", "svcscan", "shimcache", "timeliner", "unloadedmodules", "userhandles", "vadinfo", "verinfo"};
Arrays.sort(this.pluginList);
initComponents();
@ -153,16 +155,16 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
for (String plugin : pluginList) {
PluginListNames.add(plugin);
if (allEnabled)
if (allEnabled) {
pluginListStates.put(plugin, true);
else
} else {
pluginListStates.put(plugin, pluginMap.containsKey(plugin));
}
}
tableModel.fireTableDataChanged();
//this.tableModel = pluginsToRun.getModel();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
@ -374,11 +376,19 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
*
* @param path Absolute path to the selected data source
*/
@Messages({"MemoryDSInputPanel.error.text=Path to multi-user data source is on \"C:\" drive"})
@Messages({
"MemoryDSInputPanel_errorMsg_noOpenCase=No open case",
"MemoryDSInputPanel_errorMsg_dataSourcePathOnCdrive=Path to multi-user data source is on \"C:\" drive"
})
private void warnIfPathIsInvalid(String path) {
if (!PathValidator.isValid(path, Case.getCurrentCase().getCaseType())) {
try {
if (!PathValidator.isValid(path, Case.getOpenCase().getCaseType())) {
errorLabel.setVisible(true);
errorLabel.setText(Bundle.MemoryDSInputPanel_error_text());
errorLabel.setText(Bundle.MemoryDSInputPanel_errorMsg_dataSourcePathOnCdrive());
}
} catch (NoCurrentCaseException unused) {
errorLabel.setVisible(true);
errorLabel.setText(Bundle.MemoryDSInputPanel_errorMsg_dataSourcePathOnCdrive());
}
}
@ -470,5 +480,4 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -28,21 +28,21 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
/**
* A MEmory data source processor that implements the DataSourceProcessor service
* provider interface to allow integration with the add data source wizard. It
* also provides a run method overload to allow it to be used independently of
* the wizard.
* A memory image data source processor that implements the DataSourceProcessor
* service provider interface to allow integration with the Add Data Source
* wizard. It also provides a run method overload to allow it to be used
* independently of the wizard.
*/
@ServiceProvider(service = DataSourceProcessor.class)
public class MemoryDSProcessor implements DataSourceProcessor {
private final MemoryDSInputPanel configPanel;
private AddMemoryImageTask addImageTask = null;
private AddMemoryImageTask addImageTask;
/*
* Constructs a Memory data source processor that implements the
* Constructs a memory data source processor that implements the
* DataSourceProcessor service provider interface to allow integration with
* the add data source wizard. It also provides a run method overload to
* the Add Data source wizard. It also provides a run method overload to
* allow it to be used independently of the wizard.
*/
public MemoryDSProcessor() {
@ -117,37 +117,40 @@ public class MemoryDSProcessor implements DataSourceProcessor {
@Override
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
configPanel.storeSettings();
run(UUID.randomUUID().toString(), configPanel.getImageFilePath(), configPanel.getPluginsToRun(), configPanel.getTimeZone(), 0, progressMonitor, callback);
run(UUID.randomUUID().toString(), configPanel.getImageFilePath(), configPanel.getPluginsToRun(), configPanel.getTimeZone(), progressMonitor, callback);
}
/**
* Adds a "memory" data source to the case database using a background task in
* a separate thread and the given settings instead of those provided by the
* selection and configuration panel. Returns as soon as the background task
* is started and uses the callback object to signal task completion and
* return results.
* Adds a memory image data source to the case database using a background
* task in a separate thread and the given settings instead of those
* provided by the selection and configuration panel. Returns as soon as the
* background task is started and uses the callback object to signal task
* completion and return results.
*
* @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is
* intended to be unique across multiple cases
* (e.g., a UUID).
* @param imageFilePath Path to the image file.
* @param timeZone The time zone to use when processing dates
* and times for the image, obtained from
* associated with the data source that is intended
* to be unique across multiple cases (e.g., a UUID).
* @param memoryImagePath Path to the memory image file.
* @param pluginsToRun The Volatility plugins to run.
* @param timeZone The time zone to use when processing dates and
* times for the image, obtained from
* java.util.TimeZone.getID.
* @param chunkSize The maximum size of each chunk of the raw
* data source as it is divided up into virtual
* unallocated space files.
* @param progressMonitor Progress monitor for reporting progress
* during processing.
* @param progressMonitor Progress monitor for reporting progress during
* processing.
* @param callback Callback to call when processing is done.
*/
private void run(String deviceId, String imageFilePath, List<String> pluginsToRun, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addImageTask = new AddMemoryImageTask(deviceId, imageFilePath, pluginsToRun, timeZone, 0, progressMonitor, callback);
private void run(String deviceId, String memoryImagePath, List<String> pluginsToRun, String timeZone, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addImageTask = new AddMemoryImageTask(deviceId, memoryImagePath, pluginsToRun, timeZone, progressMonitor, callback);
new Thread(addImageTask).start();
//new Thread(new AddLocalFilesTask(deviceId, rootVirtualDirectoryName, localFilePaths, progressMonitor, callback)).start();
}
/**
* Requests cancellation of the background task that adds a data source to
* the case database, after the task is started using the run method. This
* is a "best effort" cancellation, with no guarantees that the case
* database will be unchanged. If cancellation succeeded, the list of new
* data sources returned by the background task will be empty.
*/
@Override
public void cancel() {
if (addImageTask != null) {
@ -165,4 +168,3 @@ public class MemoryDSProcessor implements DataSourceProcessor {
}
}

View File

@ -376,12 +376,12 @@ public class ExtractedContentViewer implements DataContentViewer {
if (artifact == null) {
return 4;
} else if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
return 6;
return 7;
} else if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
try {
BlackboardAttribute attribute = artifact.getAttribute(TSK_ACCOUNT_TYPE);
if (attribute != null && Account.Type.CREDIT_CARD.getTypeName().equals(attribute.getValueString())) {
return 6;
return 7;
} else {
return 4;
}

View File

@ -645,18 +645,18 @@ final class RegexQuery implements KeywordSearchQuery {
*/
static private void addAttributeIfNotAlreadyCaptured(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMap, ATTRIBUTE_TYPE attrType, String groupName, Matcher matcher) {
BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType);
attributeMap.computeIfAbsent(type, t -> {
if( ! attributeMap.containsKey(type)) {
String value = matcher.group(groupName);
if (attrType.equals(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)) {
attributeMap.put(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD),
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, value));
value = CharMatcher.anyOf(" -").removeFrom(value);
}
if (StringUtils.isNotBlank(value)) {
return new BlackboardAttribute(attrType, MODULE_NAME, value);
} else {
return null;
attributeMap.put(type, new BlackboardAttribute(attrType, MODULE_NAME, value));
}
}
});
}
}

View File

@ -175,24 +175,24 @@ class ExtractRegistry extends Extract {
logger.log(Level.SEVERE, null, ex);
}
int j = 0;
for (AbstractFile regFile : allRegistryFiles) {
String regFileName = regFile.getName();
long regFileId = regFile.getId();
String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, "reg") + File.separator + regFileName;
String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + regFileName + "-regripper-" + Integer.toString(j++); //NON-NLS
String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + regFileName + "-regripper-" + Long.toString(regFileId); //NON-NLS
File regFileNameLocalFile = new File(regFileNameLocal);
try {
ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, String.format("Error reading registry file '%s' (id=%d).",
regFile.getName(), regFile.getId()), ex); //NON-NLS
regFile.getName(), regFileId), ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
this.getName(), regFileName));
continue;
} catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp registry file '%s' for registry file '%s' (id=%d).",
regFileNameLocal, regFile.getName(), regFile.getId()), ex); //NON-NLS
regFileNameLocal, regFile.getName(), regFileId), ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
this.getName(), regFileName));
@ -205,7 +205,7 @@ class ExtractRegistry extends Extract {
try {
if (logFile != null) {
logFile.write(Integer.toString(j - 1) + "\t" + regFile.getUniquePath() + "\n");
logFile.write(Long.toString(regFileId) + "\t" + regFile.getUniquePath() + "\n");
}
} catch (TskCoreException | IOException ex) {
logger.log(Level.SEVERE, null, ex);