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/ /RecentActivity/release/
/CentralRepository/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="thirdparty.dir" value="${basedir}/../thirdparty" />
<property name="modules.dir" value="${basedir}/release/modules/" /> <property name="modules.dir" value="${basedir}/release/modules/" />
<property name="ext.dir" value="${modules.dir}/ext" /> <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"> <target name="get-InternalPythonModules" description="get internal python modules">
<copy todir="release/InternalPythonModules" > <copy todir="release/InternalPythonModules" >
@ -83,6 +83,7 @@
</target> </target>
<target name="getImageFile"> <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"/> <get src="https://drive.google.com/uc?id=0BxdBkzm5VKGNT0dGY0dqcHVsU3M" dest="${test-input}/filter_test1.img" skipexisting="true"/>
</target> </target>
<target name="get-deps" depends="init-ivy,getTSKJars,get-thirdparty-dependencies,get-InternalPythonModules, download-binlist, getImageFile"> <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 * @returns New Case class with populated database ID
*/ */
@Override @Override
public CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException { public synchronized CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException {
Connection conn = connect();
// 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; PreparedStatement preparedStatement = null;
String sql = "INSERT INTO cases(case_uid, org_id, case_name, creation_date, case_number, " 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) @ServiceProvider(service = DataContentViewer.class, position = 3)
public class FileViewer extends javax.swing.JPanel implements DataContentViewer { 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 long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(FileViewer.class.getName()); 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(""); rtfbodyTextPane.setText("");
htmlbodyTextPane.setText(""); htmlbodyTextPane.setText("");
textbodyTextArea.setText(""); textbodyTextArea.setText("");
drp.setNode(null);
showImagesToggleButton.setEnabled(false); showImagesToggleButton.setEnabled(false);
msgbodyTabbedPane.setEnabled(false); msgbodyTabbedPane.setEnabled(false);
} }
@ -546,7 +545,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
@Override @Override
public int isPreferred(Node node) { public int isPreferred(Node node) {
if (isSupported(node)) { if (isSupported(node)) {
return 6; return 7;
} }
return 0; return 0;
} }

View File

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

View File

@ -85,19 +85,49 @@ public interface DataContentViewer {
public boolean isSupported(Node node); public boolean isSupported(Node node);
/** /**
* Checks whether the given viewer is preferred for the Node. This is a bit * Checks whether the given viewer is preferred for the Node. This is a bit
* subjective, but the idea is that Autopsy wants to display the most * subjective, but the idea is that Autopsy wants to display the most
* relevant tab. The more generic the viewer, the lower the return value * 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 * should be. This will only be called on viewers that support the given
* node. * node (i.e., isSupported() has already returned true).
* *
* @param node Node to check for preference * 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
* @return an int (0-10) higher return means the viewer has higher priority * associated file.
* 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 * Level 7 - Based on the artifact, if any, in the selected node and specific
* Content viewer developer. Modules that operate on very few file * to an artifact type or types. Current content viewers that can return level 7 are
* types should be towards 10. * 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
*/
public int isPreferred(Node node); public int isPreferred(Node node);
} }

View File

@ -24,7 +24,7 @@ DataContentViewerString.pageLabel2.text=Page
# Product Information panel # 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> 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} 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_IMG=http://www.sleuthkit.org/
URL_ON_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.6.0/ URL_ON_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.6.0/
FILE_FOR_LOCAL_HELP=file:/// 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())) { || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID())) {
return 3; return 3;
} else { } else {
return 5; return 6;
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011 Basis Technology Corp. * Copyright 2011-2018 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");
@ -19,21 +19,31 @@
package org.sleuthkit.autopsy.filesearch; package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.text.ParseException;
import java.util.Locale;
import javax.swing.JComboBox; import javax.swing.JComboBox;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.python.icu.text.NumberFormat;
import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException; import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException;
/** /**
* * Filter search size input.
* @author pmartel
*/ */
class SizeSearchFilter extends AbstractFileSearchFilter<SizeSearchPanel> { class SizeSearchFilter extends AbstractFileSearchFilter<SizeSearchPanel> {
/**
* Instantiate a SizeSearchFilter object for a new SizeSearchPanel.
*/
SizeSearchFilter() { SizeSearchFilter() {
this(new SizeSearchPanel()); this(new SizeSearchPanel());
} }
/**
* Instantiate a SizeSearchFilter object for an existing SizeSearchPanel.
*
* @param component The SizeSearchPanel instance.
*/
SizeSearchFilter(SizeSearchPanel component) { SizeSearchFilter(SizeSearchPanel component) {
super(component); super(component);
} }
@ -53,6 +63,14 @@ class SizeSearchFilter extends AbstractFileSearchFilter<SizeSearchPanel> {
return "size " + operator + " " + size; //NON-NLS 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) { private String compareComboBoxToOperator(JComboBox<String> compare) {
String compareSize = compare.getSelectedItem().toString(); String compareSize = compare.getSelectedItem().toString();
@ -75,20 +93,20 @@ class SizeSearchFilter extends AbstractFileSearchFilter<SizeSearchPanel> {
} }
@Override @Override
@Messages ({ @Messages({
"SizeSearchFilter.errorMessage.nonNegativeNumber=Input size data is a negative number.", "SizeSearchFilter.errorMessage.nonNegativeNumber=Input size data is a negative number.",
"SizeSearchFilter.errorMessage.notANumber=Input size data is not a number." "SizeSearchFilter.errorMessage.notANumber=Input size data is not a number."
}) })
public boolean isValid() { public boolean isValid() {
String input = this.getComponent().getSizeTextField().getText(); String input = this.getComponent().getSizeTextField().getText();
try { try {
int inputInt = Integer.parseInt(input); int inputInt = NumberFormat.getNumberInstance(Locale.US).parse(input).intValue();
if (inputInt < 0) { if (inputInt < 0) {
setLastError(Bundle.SizeSearchFilter_errorMessage_nonNegativeNumber()); setLastError(Bundle.SizeSearchFilter_errorMessage_nonNegativeNumber());
return false; return false;
} }
} catch (NumberFormatException | NullPointerException e) { } catch (ParseException ex) {
setLastError(Bundle.SizeSearchFilter_errorMessage_notANumber()); setLastError(Bundle.SizeSearchFilter_errorMessage_notANumber());
return false; 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 * Ensures that all directories, files which are members of the ingest
* applied to the current run of ingest, checks if unallocated space * file filter, and unallocated blocks (when processUnallocated is
* should be processed inside call to fileIsMemberOf * 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; return false;
} }
@ -462,6 +469,30 @@ final class IngestTasksScheduler {
return true; 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 * Checks whether or not a collection of ingest tasks includes a task for a
* given data source ingest job. * 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.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertFalse;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -32,6 +33,7 @@ import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseDetails; import org.sleuthkit.autopsy.casemodule.CaseDetails;
import junit.framework.Test; import junit.framework.Test;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Exceptions; import org.openide.util.Exceptions;
import org.python.icu.impl.Assert; import org.python.icu.impl.Assert;
import org.sleuthkit.autopsy.casemodule.ImageDSProcessor; 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.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType; import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory; 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;
import org.sleuthkit.autopsy.testutils.DataSourceProcessorRunner.ProcessorCallback; import org.sleuthkit.autopsy.testutils.DataSourceProcessorRunner.ProcessorCallback;
import org.sleuthkit.autopsy.testutils.IngestJobRunner; import org.sleuthkit.autopsy.testutils.IngestJobRunner;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; 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 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 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() { public static Test suite() {
NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestFileFiltersTest.class). NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestFileFiltersTest.class).
@ -60,6 +67,10 @@ public class IngestFileFiltersTest extends TestCase {
return conf.suite(); return conf.suite();
} }
public IngestFileFiltersTest(String name) {
super(name);
}
@Override @Override
public void setUp() { public void setUp() {
// Delete the test directory, if it exists // Delete the test directory, if it exists
@ -82,7 +93,7 @@ public class IngestFileFiltersTest extends TestCase {
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
Exceptions.printStackTrace(ex); Exceptions.printStackTrace(ex);
Assert.fail(ex); Assert.fail(ex);
} }
assertTrue(CASE_DIR.exists()); assertTrue(CASE_DIR.exists());
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor(); ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
try { try {
@ -116,28 +127,48 @@ public class IngestFileFiltersTest extends TestCase {
assertFalse(CASE_DIR.exists()); 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 { try {
Case openCase = Case.getOpenCase(); Case openCase = Case.getOpenCase();
runIngestJob(openCase.getDataSources()); runIngestJob(openCase.getDataSources(), Files_Dirs_Unalloc_Ingest_Filter);
FileManager fileManager = openCase.getServices().getFileManager(); FileManager fileManager = openCase.getServices().getFileManager();
List<AbstractFile> results = fileManager.findFiles("file.jpg", "dir1"); List<AbstractFile> results = fileManager.findFiles("file.jpg", "dir1");
String mimeType = results.get(0).getMIMEType(); String mimeType = results.get(0).getMIMEType();
assertEquals("image/jpeg", mimeType); 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) { } catch (NoCurrentCaseException | TskCoreException ex) {
Exceptions.printStackTrace(ex); Exceptions.printStackTrace(ex);
Assert.fail(ex); Assert.fail(ex);
} }
} }
private void runIngestJob(List<Content> datasources) { private void runIngestJob(List<Content> datasources, FilesSet filter) {
FileTypeIdModuleFactory factory = new FileTypeIdModuleFactory(); FileTypeIdModuleFactory factory = new FileTypeIdModuleFactory();
IngestModuleIngestJobSettings settings = factory.getDefaultIngestJobSettings(); IngestModuleIngestJobSettings settings = factory.getDefaultIngestJobSettings();
IngestModuleTemplate template = new IngestModuleTemplate(factory, settings); IngestModuleTemplate template = new IngestModuleTemplate(factory, settings);
template.setEnabled(true); template.setEnabled(true);
ArrayList<IngestModuleTemplate> templates = new ArrayList<>(); ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(template); 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 { try {
List<IngestModuleError> errs = IngestJobRunner.runIngestJob(datasources, ingestJobSettings); List<IngestModuleError> errs = IngestJobRunner.runIngestJob(datasources, ingestJobSettings);
assertEquals(0, errs.size()); assertEquals(0, errs.size());
@ -146,4 +177,5 @@ public class IngestFileFiltersTest extends TestCase {
Assert.fail(ex); Assert.fail(ex);
} }
} }
}
}

View File

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

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2018 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.
@ -37,11 +37,13 @@ import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PathValidator; import org.sleuthkit.autopsy.coreutils.PathValidator;
final class MemoryDSInputPanel extends JPanel implements DocumentListener { final class MemoryDSInputPanel extends JPanel implements DocumentListener {
private static final long serialVersionUID = 1L; //default private static final long serialVersionUID = 1L; //default
private final String PROP_LASTINPUT_PATH = "LBL_LastInputFile_PATH"; private final String PROP_LASTINPUT_PATH = "LBL_LastInputFile_PATH";
private final JFileChooser fc = new JFileChooser(); private final JFileChooser fc = new JFileChooser();
@ -52,14 +54,14 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
private final List<String> PluginListNames = new ArrayList<>(); private final List<String> PluginListNames = new ArrayList<>();
private final Map<String, Boolean> pluginListStates = new HashMap<>(); // is set by listeners when users select and deselect items private final Map<String, Boolean> pluginListStates = new HashMap<>(); // is set by listeners when users select and deselect items
private final Boolean isEnabled = true; private final Boolean isEnabled = true;
/** /**
* Creates new MemoryDSInputPanel panel for user input * Creates new MemoryDSInputPanel panel for user input
*/ */
private MemoryDSInputPanel(String context) { 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); Arrays.sort(this.pluginList);
initComponents(); initComponents();
errorLabel.setVisible(false); errorLabel.setVisible(false);
@ -91,7 +93,7 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
private void postInit() { private void postInit() {
pathTextField.getDocument().addDocumentListener(this); pathTextField.getDocument().addDocumentListener(this);
} }
private void customizePluginListTable() { private void customizePluginListTable() {
PluginList.setModel(tableModel); PluginList.setModel(tableModel);
PluginList.setTableHeader(null); PluginList.setTableHeader(null);
@ -135,14 +137,14 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
// set the selected timezone // set the selected timezone
timeZoneComboBox.setSelectedItem(formatted); timeZoneComboBox.setSelectedItem(formatted);
} }
private void createVolatilityVersionList() { private void createVolatilityVersionList() {
volExecutableComboBox.addItem("2.6"); volExecutableComboBox.addItem("2.6");
volExecutableComboBox.addItem("2.5"); volExecutableComboBox.addItem("2.5");
} }
private void createPluginList() { private void createPluginList() {
PluginListNames.clear(); PluginListNames.clear();
pluginListStates.clear(); pluginListStates.clear();
@ -150,19 +152,19 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
// if the config file doesn't exist, then set them all to enabled // if the config file doesn't exist, then set them all to enabled
boolean allEnabled = !ModuleSettings.configExists(this.contextName); boolean allEnabled = !ModuleSettings.configExists(this.contextName);
Map<String, String> pluginMap = ModuleSettings.getConfigSettings(this.contextName); Map<String, String> pluginMap = ModuleSettings.getConfigSettings(this.contextName);
for (String plugin : pluginList) { for (String plugin : pluginList) {
PluginListNames.add(plugin); PluginListNames.add(plugin);
if (allEnabled) if (allEnabled) {
pluginListStates.put(plugin, true); pluginListStates.put(plugin, true);
else } else {
pluginListStates.put(plugin, pluginMap.containsKey(plugin)); pluginListStates.put(plugin, pluginMap.containsKey(plugin));
}
} }
tableModel.fireTableDataChanged(); tableModel.fireTableDataChanged();
//this.tableModel = pluginsToRun.getModel(); //this.tableModel = pluginsToRun.getModel();
} }
/** /**
* This method is called from within the constructor to initialize the form. * 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 * WARNING: Do NOT modify this code. The content of this method is always
@ -282,18 +284,18 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
String oldText = pathTextField.getText(); String oldText = pathTextField.getText();
// set the current directory of the FileChooser if the ImagePath Field is valid // set the current directory of the FileChooser if the ImagePath Field is valid
File currentDir = new File(oldText); File currentDir = new File(oldText);
if (currentDir.exists()) { if (currentDir.exists()) {
fc.setCurrentDirectory(currentDir); fc.setCurrentDirectory(currentDir);
} }
int retval = fc.showOpenDialog(this); int retval = fc.showOpenDialog(this);
if (retval == JFileChooser.APPROVE_OPTION) { if (retval == JFileChooser.APPROVE_OPTION) {
String path = fc.getSelectedFile().getPath(); String path = fc.getSelectedFile().getPath();
pathTextField.setText(path); pathTextField.setText(path);
} }
}//GEN-LAST:event_browseButtonActionPerformed }//GEN-LAST:event_browseButtonActionPerformed
private void volExecutableComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_volExecutableComboBoxActionPerformed private void volExecutableComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_volExecutableComboBoxActionPerformed
@ -322,7 +324,7 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
String getImageFilePath() { String getImageFilePath() {
return pathTextField.getText(); return pathTextField.getText();
} }
List<String> getPluginsToRun() { List<String> getPluginsToRun() {
List<String> enabledPlugins = new ArrayList<>(); List<String> enabledPlugins = new ArrayList<>();
Map<String, String> pluginMap = new HashMap<>(); Map<String, String> pluginMap = new HashMap<>();
@ -332,7 +334,7 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
pluginMap.put(plugin, ""); pluginMap.put(plugin, "");
} }
} }
ModuleSettings.setConfigSettings(this.contextName, pluginMap); ModuleSettings.setConfigSettings(this.contextName, pluginMap);
// @@ Could return keys of set // @@ Could return keys of set
return enabledPlugins; return enabledPlugins;
@ -374,11 +376,19 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
* *
* @param path Absolute path to the selected data source * @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) { 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_errorMsg_dataSourcePathOnCdrive());
}
} catch (NoCurrentCaseException unused) {
errorLabel.setVisible(true); errorLabel.setVisible(true);
errorLabel.setText(Bundle.MemoryDSInputPanel_error_text()); 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 * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2018 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");
@ -28,21 +28,21 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
/** /**
* A MEmory data source processor that implements the DataSourceProcessor service * A memory image data source processor that implements the DataSourceProcessor
* provider interface to allow integration with the add data source wizard. It * service provider interface to allow integration with the Add Data Source
* also provides a run method overload to allow it to be used independently of * wizard. It also provides a run method overload to allow it to be used
* the wizard. * independently of the wizard.
*/ */
@ServiceProvider(service = DataSourceProcessor.class) @ServiceProvider(service = DataSourceProcessor.class)
public class MemoryDSProcessor implements DataSourceProcessor { public class MemoryDSProcessor implements DataSourceProcessor {
private final MemoryDSInputPanel configPanel; 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 * 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. * allow it to be used independently of the wizard.
*/ */
public MemoryDSProcessor() { public MemoryDSProcessor() {
@ -117,37 +117,40 @@ public class MemoryDSProcessor implements DataSourceProcessor {
@Override @Override
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
configPanel.storeSettings(); 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 * Adds a memory image data source to the case database using a background
* a separate thread and the given settings instead of those provided by the * task in a separate thread and the given settings instead of those
* selection and configuration panel. Returns as soon as the background task * provided by the selection and configuration panel. Returns as soon as the
* is started and uses the callback object to signal task completion and * background task is started and uses the callback object to signal task
* return results. * completion and return results.
* *
* @param deviceId An ASCII-printable identifier for the device * @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is * associated with the data source that is intended
* intended to be unique across multiple cases * to be unique across multiple cases (e.g., a UUID).
* (e.g., a UUID). * @param memoryImagePath Path to the memory image file.
* @param imageFilePath Path to the image file. * @param pluginsToRun The Volatility plugins to run.
* @param timeZone The time zone to use when processing dates * @param timeZone The time zone to use when processing dates and
* and times for the image, obtained from * times for the image, obtained from
* java.util.TimeZone.getID. * java.util.TimeZone.getID.
* @param chunkSize The maximum size of each chunk of the raw * @param progressMonitor Progress monitor for reporting progress during
* data source as it is divided up into virtual * processing.
* unallocated space files. * @param callback Callback to call when processing is done.
* @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) { private void run(String deviceId, String memoryImagePath, List<String> pluginsToRun, String timeZone, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addImageTask = new AddMemoryImageTask(deviceId, imageFilePath, pluginsToRun, timeZone, 0, progressMonitor, callback); addImageTask = new AddMemoryImageTask(deviceId, memoryImagePath, pluginsToRun, timeZone, progressMonitor, callback);
new Thread(addImageTask).start(); 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 @Override
public void cancel() { public void cancel() {
if (addImageTask != null) { 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) { if (artifact == null) {
return 4; return 4;
} else if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { } 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()) { } else if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
try { try {
BlackboardAttribute attribute = artifact.getAttribute(TSK_ACCOUNT_TYPE); BlackboardAttribute attribute = artifact.getAttribute(TSK_ACCOUNT_TYPE);
if (attribute != null && Account.Type.CREDIT_CARD.getTypeName().equals(attribute.getValueString())) { if (attribute != null && Account.Type.CREDIT_CARD.getTypeName().equals(attribute.getValueString())) {
return 6; return 7;
} else { } else {
return 4; 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) { static private void addAttributeIfNotAlreadyCaptured(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMap, ATTRIBUTE_TYPE attrType, String groupName, Matcher matcher) {
BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType); BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType);
attributeMap.computeIfAbsent(type, t -> {
if( ! attributeMap.containsKey(type)) {
String value = matcher.group(groupName); String value = matcher.group(groupName);
if (attrType.equals(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)) { if (attrType.equals(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)) {
attributeMap.put(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD), attributeMap.put(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD),
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, value)); new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, value));
value = CharMatcher.anyOf(" -").removeFrom(value); value = CharMatcher.anyOf(" -").removeFrom(value);
} }
if (StringUtils.isNotBlank(value)) { if (StringUtils.isNotBlank(value)) {
return new BlackboardAttribute(attrType, MODULE_NAME, value); attributeMap.put(type, new BlackboardAttribute(attrType, MODULE_NAME, value));
} else {
return null;
} }
}); }
} }
} }

View File

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