Merge remote-tracking branch 'upstream/custom-release-march-2018' into develop

This commit is contained in:
Richard Cordovano 2018-03-28 13:28:36 -04:00
commit 6a1b21e3bc
6 changed files with 113 additions and 203 deletions

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

@ -546,7 +546,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
@ -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; 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.", "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>() {
@Override
protected Map<String, String> doInBackground() throws NoCurrentCaseException, TskCoreException, IOException, SQLException, ClassNotFoundException {
// Copy the file to temp folder // 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); 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) {
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. // Load the SQLite JDBC driver, if necessary.
Class.forName("org.sqlite.JDBC"); //NON-NLS Class.forName("org.sqlite.JDBC"); //NON-NLS
connection = DriverManager.getConnection("jdbc:sqlite:" + tmpDBPathName); //NON-NLS connection = DriverManager.getConnection("jdbc:sqlite:" + tmpDBPathName); //NON-NLS
// Query the file for the table names and schemas. Map<String, String> dbTablesMap = getTables();
return getTables();
}
@Override
protected void done() {
super.done();
try {
Map<String, String> dbTablesMap = get();
if (dbTablesMap.isEmpty()) { if (dbTablesMap.isEmpty()) {
tablesDropdownList.addItem(Bundle.SQLiteViewer_comboBox_noTableEntry()); tablesDropdownList.addItem(Bundle.SQLiteViewer_comboBox_noTableEntry());
tablesDropdownList.setEnabled(false); tablesDropdownList.setEnabled(false);
@ -351,32 +356,13 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
tablesDropdownList.addItem(tableName); tablesDropdownList.addItem(tableName);
}); });
} }
} catch (InterruptedException ex) { } catch (ClassNotFoundException 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 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(); MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_errorMessage_failedToinitJDBCDriver());
} else { } catch (SQLException ex) {
logger.log(Level.SEVERE, String.format("Unexpected exception while processing DB file '%s' (objId=%d)", sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS 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_unexpectedError(cause.getLocalizedMessage()); 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}" "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);
worker = null;
}
worker = new SwingWorker<Integer, Void>() { try (Statement statement = connection.createStatement();
@Override ResultSet resultSet = statement.executeQuery(
protected Integer doInBackground() throws Exception { "SELECT count (*) as count FROM " + tableName)) { //NON-NLS{
Statement statement = null; numRows = resultSet.getInt("count");
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"); numEntriesField.setText(numRows + " entries");
currPage = 1; currPage = 1;
@ -487,93 +444,34 @@ public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
selectedTableView.setupTable(Collections.emptyList()); selectedTableView.setupTable(Collections.emptyList());
} }
} catch (InterruptedException ex) { } catch (SQLException ex) {
logger.log(Level.SEVERE, "Interrupted while getting row count from table " + tableName, ex); //NON-NLS 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
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_selectTable_errorText(tableName));
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(
}
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 "SELECT * FROM " + tableName
+ " LIMIT " + Integer.toString(numRowsToRead) + " LIMIT " + Integer.toString(numRowsToRead)
+ " OFFSET " + Integer.toString(startRow - 1) + " OFFSET " + Integer.toString(startRow - 1))) {
); //NON-NLS
return resultSetToArrayList(resultSet); ArrayList<Map<String, Object>> rows = 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)) { if (Objects.nonNull(rows)) {
selectedTableView.setupTable(rows); selectedTableView.setupTable(rows);
} else { } else {
selectedTableView.setupTable(Collections.emptyList()); selectedTableView.setupTable(Collections.emptyList());
} }
} catch (InterruptedException ex) { } catch (SQLException ex) {
logger.log(Level.SEVERE, "Interrupted while reading table " + tableName, ex); //NON-NLS 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
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_readTable_errorText(tableName));
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")
private ArrayList<Map<String, Object>> resultSetToArrayList(ResultSet rs) throws SQLException { private ArrayList<Map<String, Object>> resultSetToArrayList(ResultSet rs) throws SQLException {

View File

@ -91,13 +91,25 @@ public interface DataContentViewer {
* 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.
* *
* Level 0: Not supported/should never be the default viewer
*
* Level 1: Always work, not very specific
*
* Level 2: Unused
*
* Level 3: Artifact-based that flag files
*
* Level 4: File-based that are not always enabled, but also not really specific
*
* Level 5: File-based that are specific:
*
* Level 6: Artifact-based that is not really specific
*
* Level 7: Artifact-based and specific
*
* @param node Node to check for preference * @param node Node to check for preference
* *
* @return an int (0-10) higher return means the viewer has higher priority * @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); public int isPreferred(Node node);
} }

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

@ -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;
} }