mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
3086-Fix merge conflict with OtherCasesTableModel
This commit is contained in:
commit
3da10bca78
@ -36,7 +36,7 @@ import javax.swing.event.DocumentListener;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||
@ -48,7 +48,7 @@ import org.sleuthkit.autopsy.centralrepository.optionspanel.AddNewOrganizationDi
|
||||
public class EamCaseEditDetailsDialog extends JDialog {
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(EamCaseEditDetailsDialog.class.getName());
|
||||
private EamCase eamCase;
|
||||
private CorrelationCase eamCase;
|
||||
private EamDb dbManager;
|
||||
private Boolean contentChanged = false;
|
||||
private final Collection<JTextField> textBoxes = new ArrayList<>();
|
||||
@ -69,7 +69,7 @@ public class EamCaseEditDetailsDialog extends JDialog {
|
||||
|
||||
try {
|
||||
this.dbManager = EamDb.getInstance();
|
||||
this.eamCase = this.dbManager.getCaseDetails(Case.getCurrentCase().getName());
|
||||
this.eamCase = this.dbManager.getCaseByUUID(Case.getCurrentCase().getName());
|
||||
if(this.eamCase == null){
|
||||
this.eamCase = dbManager.newCase(Case.getCurrentCase());
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalFileInstance;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@ -167,7 +167,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx);
|
||||
CorrelationAttribute eamArtifact = (CorrelationAttribute) tableModel.getRow(selectedRowModelIdx);
|
||||
EamCase eamCasePartial = eamArtifact.getInstances().get(0).getEamCase();
|
||||
CorrelationCase eamCasePartial = eamArtifact.getInstances().get(0).getCorrelationCase();
|
||||
if (eamCasePartial == null) {
|
||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
|
||||
@ -177,7 +177,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
}
|
||||
caseDisplayName = eamCasePartial.getDisplayName();
|
||||
// query case details
|
||||
EamCase eamCase = dbManager.getCaseDetails(eamCasePartial.getCaseUUID());
|
||||
CorrelationCase eamCase = dbManager.getCaseByUUID(eamCasePartial.getCaseUUID());
|
||||
if (eamCase == null) {
|
||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
|
||||
@ -421,9 +421,9 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
try {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
Collection<CorrelationAttributeInstance> artifactInstances = dbManager.getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue()).stream()
|
||||
.filter(artifactInstance -> !artifactInstance.getEamCase().getCaseUUID().equals(caseUUID)
|
||||
|| !artifactInstance.getEamDataSource().getName().equals(dataSourceName)
|
||||
|| !artifactInstance.getEamDataSource().getDeviceID().equals(deviceId))
|
||||
.filter(artifactInstance -> !artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
|
||||
|| !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
|
||||
|| !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId))
|
||||
.collect(Collectors.toList());
|
||||
return artifactInstances;
|
||||
} catch (EamDbException ex) {
|
||||
|
@ -49,7 +49,8 @@ public class DataContentViewerOtherCasesTableCellRenderer implements TableCellRe
|
||||
foreground = Color.WHITE;
|
||||
background = Color.BLUE;
|
||||
} else {
|
||||
String known_status = (String) table.getModel().getValueAt(row, 5);
|
||||
String known_status = (String) table.getModel().getValueAt(row,
|
||||
table.getColumn(DataContentViewerOtherCasesTableModel.TableColumns.KNOWN.columnName()).getModelIndex());
|
||||
if (known_status.equals(TskData.FileKnown.BAD.getName())) {
|
||||
foreground = Color.WHITE;
|
||||
background = Color.RED;
|
||||
|
@ -40,7 +40,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
"DataContentViewerOtherCasesTableModel.known=Known",
|
||||
"DataContentViewerOtherCasesTableModel.comment=Comment",
|
||||
"DataContentViewerOtherCasesTableModel.noData=No Data.",})
|
||||
private enum TableColumns {
|
||||
enum TableColumns {
|
||||
// Ordering here determines displayed column order in Content Viewer.
|
||||
// If order is changed, update the CellRenderer to ensure correct row coloring.
|
||||
CASE_NAME(Bundle.DataContentViewerOtherCasesTableModel_case(), 100),
|
||||
@ -133,18 +133,18 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
|
||||
switch (colId) {
|
||||
case CASE_NAME:
|
||||
if (null != eamArtifactInstance.getEamCase()) {
|
||||
value = eamArtifactInstance.getEamCase().getDisplayName();
|
||||
if (null != eamArtifactInstance.getCorrelationCase()) {
|
||||
value = eamArtifactInstance.getCorrelationCase().getDisplayName();
|
||||
}
|
||||
break;
|
||||
case DEVICE:
|
||||
if (null != eamArtifactInstance.getEamDataSource()) {
|
||||
value = eamArtifactInstance.getEamDataSource().getDeviceID();
|
||||
if (null != eamArtifactInstance.getCorrelationDataSource()) {
|
||||
value = eamArtifactInstance.getCorrelationDataSource().getDeviceID();
|
||||
}
|
||||
break;
|
||||
case DATA_SOURCE:
|
||||
if (null != eamArtifactInstance.getEamDataSource()) {
|
||||
value = eamArtifactInstance.getEamDataSource().getName();
|
||||
if (null != eamArtifactInstance.getCorrelationDataSource()) {
|
||||
value = eamArtifactInstance.getCorrelationDataSource().getName();
|
||||
}
|
||||
break;
|
||||
case FILE_PATH:
|
||||
|
@ -198,7 +198,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* @param eamCase The case to add
|
||||
*/
|
||||
@Override
|
||||
public void newCase(EamCase eamCase) throws EamDbException {
|
||||
public void newCase(CorrelationCase eamCase) throws EamDbException {
|
||||
Connection conn = connect();
|
||||
|
||||
PreparedStatement preparedStatement = null;
|
||||
@ -259,12 +259,12 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* @param case The case to add
|
||||
*/
|
||||
@Override
|
||||
public EamCase newCase(Case autopsyCase) throws EamDbException{
|
||||
public CorrelationCase newCase(Case autopsyCase) throws EamDbException{
|
||||
if(autopsyCase == null){
|
||||
throw new EamDbException("Case is null");
|
||||
}
|
||||
|
||||
EamCase curCeCase = new EamCase(
|
||||
CorrelationCase curCeCase = new CorrelationCase(
|
||||
-1,
|
||||
autopsyCase.getName(), // unique case ID
|
||||
EamOrganization.getDefault(),
|
||||
@ -285,7 +285,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* @param eamCase The case to update
|
||||
*/
|
||||
@Override
|
||||
public void updateCase(EamCase eamCase) throws EamDbException {
|
||||
public void updateCase(CorrelationCase eamCase) throws EamDbException {
|
||||
Connection conn = connect();
|
||||
|
||||
PreparedStatement preparedStatement = null;
|
||||
@ -349,10 +349,12 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* @return The retrieved case
|
||||
*/
|
||||
@Override
|
||||
public EamCase getCaseDetails(String caseUUID) throws EamDbException {
|
||||
public CorrelationCase getCaseByUUID(String caseUUID) throws EamDbException {
|
||||
// @@@ We should have a cache here...
|
||||
|
||||
Connection conn = connect();
|
||||
|
||||
EamCase eamCaseResult = null;
|
||||
CorrelationCase eamCaseResult = null;
|
||||
PreparedStatement preparedStatement = null;
|
||||
ResultSet resultSet = null;
|
||||
|
||||
@ -386,11 +388,11 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* @return List of cases
|
||||
*/
|
||||
@Override
|
||||
public List<EamCase> getCases() throws EamDbException {
|
||||
public List<CorrelationCase> getCases() throws EamDbException {
|
||||
Connection conn = connect();
|
||||
|
||||
List<EamCase> cases = new ArrayList<>();
|
||||
EamCase eamCaseResult;
|
||||
List<CorrelationCase> cases = new ArrayList<>();
|
||||
CorrelationCase eamCaseResult;
|
||||
PreparedStatement preparedStatement = null;
|
||||
ResultSet resultSet = null;
|
||||
|
||||
@ -450,27 +452,27 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
*
|
||||
* @param eamDataSource the data source to update
|
||||
*/
|
||||
@Override
|
||||
public void updateDataSource(CorrelationDataSource eamDataSource) throws EamDbException {
|
||||
Connection conn = connect();
|
||||
|
||||
PreparedStatement preparedStatement = null;
|
||||
String sql = "UPDATE data_sources SET name=? WHERE device_id=?";
|
||||
|
||||
try {
|
||||
preparedStatement = conn.prepareStatement(sql);
|
||||
|
||||
preparedStatement.setString(1, eamDataSource.getName());
|
||||
preparedStatement.setString(2, eamDataSource.getDeviceID());
|
||||
|
||||
preparedStatement.executeUpdate();
|
||||
} catch (SQLException ex) {
|
||||
throw new EamDbException("Error updating case.", ex); // NON-NLS
|
||||
} finally {
|
||||
EamDbUtil.closePreparedStatement(preparedStatement);
|
||||
EamDbUtil.closeConnection(conn);
|
||||
}
|
||||
}
|
||||
// @Override
|
||||
// public void updateDataSource(CorrelationDataSource eamDataSource) throws EamDbException {
|
||||
// Connection conn = connect();
|
||||
// BC: This needs to be updated because device_id is not unique. Query needs to also use case_id
|
||||
// PreparedStatement preparedStatement = null;
|
||||
// String sql = "UPDATE data_sources SET name=? WHERE device_id=?";
|
||||
//
|
||||
// try {
|
||||
// preparedStatement = conn.prepareStatement(sql);
|
||||
//
|
||||
// preparedStatement.setString(1, eamDataSource.getName());
|
||||
// preparedStatement.setString(2, eamDataSource.getDeviceID());
|
||||
//
|
||||
// preparedStatement.executeUpdate();
|
||||
// } catch (SQLException ex) {
|
||||
// throw new EamDbException("Error updating case.", ex); // NON-NLS
|
||||
// } finally {
|
||||
// EamDbUtil.closePreparedStatement(preparedStatement);
|
||||
// EamDbUtil.closeConnection(conn);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Retrieves Data Source details based on data source device ID
|
||||
@ -568,8 +570,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
preparedStatement = conn.prepareStatement(sql.toString());
|
||||
for (CorrelationAttributeInstance eamInstance : eamInstances) {
|
||||
if(! eamArtifact.getCorrelationValue().isEmpty()){
|
||||
preparedStatement.setString(1, eamInstance.getEamCase().getCaseUUID());
|
||||
preparedStatement.setString(2, eamInstance.getEamDataSource().getDeviceID());
|
||||
preparedStatement.setString(1, eamInstance.getCorrelationCase().getCaseUUID());
|
||||
preparedStatement.setString(2, eamInstance.getCorrelationDataSource().getDeviceID());
|
||||
preparedStatement.setString(3, eamArtifact.getCorrelationValue());
|
||||
preparedStatement.setString(4, eamInstance.getFilePath());
|
||||
preparedStatement.setByte(5, eamInstance.getKnownStatus().getFileKnownValue());
|
||||
@ -928,8 +930,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
|
||||
for (CorrelationAttributeInstance eamInstance : eamInstances) {
|
||||
if(! eamArtifact.getCorrelationValue().isEmpty()){
|
||||
bulkPs.setString(1, eamInstance.getEamCase().getCaseUUID());
|
||||
bulkPs.setString(2, eamInstance.getEamDataSource().getDeviceID());
|
||||
bulkPs.setString(1, eamInstance.getCorrelationCase().getCaseUUID());
|
||||
bulkPs.setString(2, eamInstance.getCorrelationDataSource().getDeviceID());
|
||||
bulkPs.setString(3, eamArtifact.getCorrelationValue());
|
||||
bulkPs.setString(4, eamInstance.getFilePath());
|
||||
bulkPs.setByte(5, eamInstance.getKnownStatus().getFileKnownValue());
|
||||
@ -962,7 +964,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* Executes a bulk insert of the cases
|
||||
*/
|
||||
@Override
|
||||
public void bulkInsertCases(List<EamCase> cases) throws EamDbException {
|
||||
public void bulkInsertCases(List<CorrelationCase> cases) throws EamDbException {
|
||||
Connection conn = connect();
|
||||
|
||||
if (cases.isEmpty()) {
|
||||
@ -978,7 +980,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
+ getConflictClause();
|
||||
bulkPs = conn.prepareStatement(sql);
|
||||
|
||||
for (EamCase eamCase : cases) {
|
||||
for (CorrelationCase eamCase : cases) {
|
||||
bulkPs.setString(1, eamCase.getCaseUUID());
|
||||
if (null == eamCase.getOrg()) {
|
||||
bulkPs.setNull(2, Types.INTEGER);
|
||||
@ -1075,8 +1077,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
|
||||
try {
|
||||
preparedQuery = conn.prepareStatement(sqlQuery.toString());
|
||||
preparedQuery.setString(1, eamInstance.getEamCase().getCaseUUID());
|
||||
preparedQuery.setString(2, eamInstance.getEamDataSource().getDeviceID());
|
||||
preparedQuery.setString(1, eamInstance.getCorrelationCase().getCaseUUID());
|
||||
preparedQuery.setString(2, eamInstance.getCorrelationDataSource().getDeviceID());
|
||||
preparedQuery.setString(3, eamArtifact.getCorrelationValue());
|
||||
preparedQuery.setString(4, eamInstance.getFilePath());
|
||||
resultSet = preparedQuery.executeQuery();
|
||||
@ -1103,12 +1105,12 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
// in the database, but we don't expect the user to be tagging large numbers
|
||||
// of items (that didn't have the CE ingest module run on them) at once.
|
||||
|
||||
if(null == getCaseDetails(eamInstance.getEamCase().getCaseUUID())){
|
||||
newCase(eamInstance.getEamCase());
|
||||
if(null == getCaseByUUID(eamInstance.getCorrelationCase().getCaseUUID())){
|
||||
newCase(eamInstance.getCorrelationCase());
|
||||
}
|
||||
|
||||
if (null == getDataSourceDetails(eamInstance.getEamDataSource().getDeviceID())) {
|
||||
newDataSource(eamInstance.getEamDataSource());
|
||||
if (null == getDataSourceDetails(eamInstance.getCorrelationDataSource().getDeviceID())) {
|
||||
newDataSource(eamInstance.getCorrelationDataSource());
|
||||
}
|
||||
|
||||
eamArtifact.getInstances().get(0).setKnownStatus(knownStatus);
|
||||
@ -1836,7 +1838,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
*
|
||||
* @throws SQLException when an expected column name is not in the resultSet
|
||||
*/
|
||||
private EamCase getEamCaseFromResultSet(ResultSet resultSet) throws SQLException {
|
||||
private CorrelationCase getEamCaseFromResultSet(ResultSet resultSet) throws SQLException {
|
||||
if (null == resultSet) {
|
||||
return null;
|
||||
}
|
||||
@ -1853,8 +1855,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
resultSet.getString("poc_phone"));
|
||||
}
|
||||
|
||||
EamCase eamCase = new EamCase(resultSet.getString("case_uid"), resultSet.getString("case_name"));
|
||||
eamCase.setID(resultSet.getInt("case_id"));
|
||||
CorrelationCase eamCase = new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), resultSet.getString("case_name"));
|
||||
eamCase.setOrg(eamOrg);
|
||||
eamCase.setCreationDate(resultSet.getString("creation_date"));
|
||||
eamCase.setCaseNumber(resultSet.getString("case_number"));
|
||||
@ -1911,7 +1912,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
return null;
|
||||
}
|
||||
CorrelationAttributeInstance eamArtifactInstance = new CorrelationAttributeInstance(
|
||||
new EamCase(resultSet.getString("case_uid"), resultSet.getString("case_name")),
|
||||
new CorrelationCase(resultSet.getString("case_uid"), resultSet.getString("case_name")),
|
||||
new CorrelationDataSource(-1, resultSet.getString("device_id"), resultSet.getString("name")),
|
||||
resultSet.getString("file_path"),
|
||||
resultSet.getString("comment"),
|
||||
|
@ -53,52 +53,52 @@ public class CorrelationAttributeInstance implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String ID;
|
||||
private EamCase eamCase;
|
||||
private CorrelationDataSource eamDataSource;
|
||||
private int ID;
|
||||
private CorrelationCase correlationCase;
|
||||
private CorrelationDataSource correlationDataSource;
|
||||
private String filePath;
|
||||
private String comment;
|
||||
private TskData.FileKnown knownStatus;
|
||||
private GlobalStatus globalStatus;
|
||||
|
||||
public CorrelationAttributeInstance(
|
||||
EamCase eamCase,
|
||||
CorrelationCase eamCase,
|
||||
CorrelationDataSource eamDataSource
|
||||
) {
|
||||
this("", eamCase, eamDataSource, "", null, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
this(-1, eamCase, eamDataSource, "", null, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
}
|
||||
|
||||
public CorrelationAttributeInstance(
|
||||
EamCase eamCase,
|
||||
CorrelationCase eamCase,
|
||||
CorrelationDataSource eamDataSource,
|
||||
String filePath
|
||||
) {
|
||||
this("", eamCase, eamDataSource, filePath, null, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
this(-1, eamCase, eamDataSource, filePath, null, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
}
|
||||
|
||||
public CorrelationAttributeInstance(
|
||||
EamCase eamCase,
|
||||
CorrelationCase eamCase,
|
||||
CorrelationDataSource eamDataSource,
|
||||
String filePath,
|
||||
String comment
|
||||
) {
|
||||
this("", eamCase, eamDataSource, filePath, comment, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
this(-1, eamCase, eamDataSource, filePath, comment, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
}
|
||||
|
||||
public CorrelationAttributeInstance(
|
||||
EamCase eamCase,
|
||||
CorrelationCase eamCase,
|
||||
CorrelationDataSource eamDataSource,
|
||||
String filePath,
|
||||
String comment,
|
||||
TskData.FileKnown knownStatus,
|
||||
GlobalStatus globalStatus
|
||||
) {
|
||||
this("", eamCase, eamDataSource, filePath, comment, knownStatus, globalStatus);
|
||||
this(-1, eamCase, eamDataSource, filePath, comment, knownStatus, globalStatus);
|
||||
}
|
||||
|
||||
public CorrelationAttributeInstance(
|
||||
String ID,
|
||||
EamCase eamCase,
|
||||
int ID,
|
||||
CorrelationCase eamCase,
|
||||
CorrelationDataSource eamDataSource,
|
||||
String filePath,
|
||||
String comment,
|
||||
@ -106,8 +106,8 @@ public class CorrelationAttributeInstance implements Serializable {
|
||||
GlobalStatus globalStatus
|
||||
) {
|
||||
this.ID = ID;
|
||||
this.eamCase = eamCase;
|
||||
this.eamDataSource = eamDataSource;
|
||||
this.correlationCase = eamCase;
|
||||
this.correlationDataSource = eamDataSource;
|
||||
// Lower case paths to normalize paths and improve correlation results, if this causes significant issues on case-sensitive file systems, remove
|
||||
this.filePath = filePath.toLowerCase();
|
||||
this.comment = comment;
|
||||
@ -116,9 +116,9 @@ public class CorrelationAttributeInstance implements Serializable {
|
||||
}
|
||||
|
||||
public Boolean equals(CorrelationAttributeInstance otherInstance) {
|
||||
return ((this.getID().equals(otherInstance.getID()))
|
||||
&& (this.getEamCase().equals(otherInstance.getEamCase()))
|
||||
&& (this.getEamDataSource().equals(otherInstance.getEamDataSource()))
|
||||
return ((this.getID() == otherInstance.getID())
|
||||
&& (this.getCorrelationCase().equals(otherInstance.getCorrelationCase()))
|
||||
&& (this.getCorrelationDataSource().equals(otherInstance.getCorrelationDataSource()))
|
||||
&& (this.getFilePath().equals(otherInstance.getFilePath()))
|
||||
&& (this.getGlobalStatus().equals(otherInstance.getGlobalStatus()))
|
||||
&& (this.getKnownStatus().equals(otherInstance.getKnownStatus()))
|
||||
@ -128,8 +128,8 @@ public class CorrelationAttributeInstance implements Serializable {
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getID()
|
||||
+ this.getEamCase().getCaseUUID()
|
||||
+ this.getEamDataSource().getName()
|
||||
+ this.getCorrelationCase().getCaseUUID()
|
||||
+ this.getCorrelationDataSource().getName()
|
||||
+ this.getFilePath()
|
||||
+ this.getGlobalStatus()
|
||||
+ this.getKnownStatus()
|
||||
@ -137,45 +137,24 @@ public class CorrelationAttributeInstance implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ID
|
||||
* @return the database ID
|
||||
*/
|
||||
public String getID() {
|
||||
int getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ID the ID to set
|
||||
*/
|
||||
public void setID(String ID) {
|
||||
this.ID = ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the eamCase
|
||||
*/
|
||||
public EamCase getEamCase() {
|
||||
return eamCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param eamCase the eamCase to set
|
||||
*/
|
||||
public void setEamCase(EamCase eamCase) {
|
||||
this.eamCase = eamCase;
|
||||
public CorrelationCase getCorrelationCase() {
|
||||
return correlationCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the eamDataSource
|
||||
*/
|
||||
public CorrelationDataSource getEamDataSource() {
|
||||
return eamDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param eamDataSource the eamDataSource to set
|
||||
*/
|
||||
public void setEamDataSource(CorrelationDataSource eamDataSource) {
|
||||
this.eamDataSource = eamDataSource;
|
||||
public CorrelationDataSource getCorrelationDataSource() {
|
||||
return correlationDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -185,14 +164,6 @@ public class CorrelationAttributeInstance implements Serializable {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param filePath the filePath to set
|
||||
*/
|
||||
public void setFilePath(String filePath) {
|
||||
// Lower case paths to normalize paths and improve correlation results, if this causes significant issues on case-sensitive file systems, remove
|
||||
this.filePath = filePath.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the comment
|
||||
*/
|
||||
|
@ -29,13 +29,13 @@ import org.openide.util.NbBundle.Messages;
|
||||
* Used to store info about a case.
|
||||
*
|
||||
*/
|
||||
public class EamCase implements Serializable {
|
||||
public class CorrelationCase implements Serializable {
|
||||
|
||||
private static long serialVersionUID = 1L;
|
||||
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
|
||||
|
||||
private int ID;
|
||||
private String caseUUID;
|
||||
private int databaseId;
|
||||
private String caseUUID; // globally unique
|
||||
private EamOrganization org;
|
||||
private String displayName;
|
||||
private String creationDate;
|
||||
@ -45,11 +45,20 @@ public class EamCase implements Serializable {
|
||||
private String examinerPhone;
|
||||
private String notes;
|
||||
|
||||
public EamCase(String caseUUID, String displayName) {
|
||||
/**
|
||||
*
|
||||
* @param caseUUID Globally unique identifier
|
||||
* @param displayName
|
||||
*/
|
||||
public CorrelationCase(String caseUUID, String displayName) {
|
||||
this(-1, caseUUID, null, displayName, DATE_FORMAT.format(new Date()), null, null, null, null, null);
|
||||
}
|
||||
|
||||
public EamCase(int ID,
|
||||
CorrelationCase(int ID, String caseUUID, String displayName) {
|
||||
this(ID, caseUUID, null, displayName, DATE_FORMAT.format(new Date()), null, null, null, null, null);
|
||||
}
|
||||
|
||||
public CorrelationCase(int ID,
|
||||
String caseUUID,
|
||||
EamOrganization org,
|
||||
String displayName,
|
||||
@ -59,7 +68,7 @@ public class EamCase implements Serializable {
|
||||
String examinerEmail,
|
||||
String examinerPhone,
|
||||
String notes) {
|
||||
this.ID = ID;
|
||||
this.databaseId = ID;
|
||||
this.caseUUID = caseUUID;
|
||||
this.org = org;
|
||||
this.displayName = displayName;
|
||||
@ -149,18 +158,13 @@ public class EamCase implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ID
|
||||
* @return the database ID for the case or -1 if it is unknown (or not in the DB)
|
||||
*/
|
||||
public int getID() {
|
||||
return ID;
|
||||
int getID() {
|
||||
// @@@ Should probably have some lazy logic here to lead the ID from the DB if it is -1
|
||||
return databaseId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ID the ID to set
|
||||
*/
|
||||
public void setID(int ID) {
|
||||
this.ID = ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the caseUUID
|
||||
@ -169,12 +173,6 @@ public class EamCase implements Serializable {
|
||||
return caseUUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param caseUUID the caseUUID to set
|
||||
*/
|
||||
public void setCaseUUID(String caseUUID) {
|
||||
this.caseUUID = caseUUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the org
|
||||
@ -287,5 +285,4 @@ public class EamCase implements Serializable {
|
||||
public void setNotes(String notes) {
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
}
|
@ -34,7 +34,7 @@ public class CorrelationDataSource implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final int dataSourceId; //< Id in the central repo
|
||||
private final String deviceID;
|
||||
private final String deviceID; //< Unique to its associated case (not necessarily globally unique)
|
||||
private final String name;
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@ public class CorrelationDataSource implements Serializable {
|
||||
public String toString() {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append("(");
|
||||
str.append("ID=").append(Integer.toString(getDataSourceID()));
|
||||
str.append("ID=").append(Integer.toString(getID()));
|
||||
str.append(",deviceID=").append(getDeviceID());
|
||||
str.append(",name=").append(getName());
|
||||
str.append(")");
|
||||
@ -81,13 +81,16 @@ public class CorrelationDataSource implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database row ID
|
||||
*
|
||||
* @return the ID
|
||||
*/
|
||||
public int getDataSourceID() {
|
||||
int getID() {
|
||||
return dataSourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the device ID that is unique to the case
|
||||
* @return the deviceID
|
||||
*/
|
||||
public String getDeviceID() {
|
||||
|
@ -97,7 +97,7 @@ public class EamArtifactUtil {
|
||||
|
||||
// make an instance for the BB source file
|
||||
CorrelationAttributeInstance eamInstance = new CorrelationAttributeInstance(
|
||||
new EamCase(currentCase.getName(), currentCase.getDisplayName()),
|
||||
new CorrelationCase(currentCase.getName(), currentCase.getDisplayName()),
|
||||
CorrelationDataSource.fromTSKDataSource(bbSourceFile.getDataSource()),
|
||||
bbSourceFile.getParentPath() + bbSourceFile.getName(),
|
||||
"",
|
||||
@ -229,12 +229,7 @@ public class EamArtifactUtil {
|
||||
|
||||
final AbstractFile af = (AbstractFile) content;
|
||||
|
||||
if ((af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
|
||||
|| (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)
|
||||
|| (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)
|
||||
|| (af.getKnown() == TskData.FileKnown.KNOWN)
|
||||
|| (af.isDir() == true)
|
||||
|| (!af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC))) {
|
||||
if ( ! isValidCentralRepoFile(af)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -249,7 +244,7 @@ public class EamArtifactUtil {
|
||||
CorrelationAttribute.Type filesType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID);
|
||||
eamArtifact = new CorrelationAttribute(filesType, af.getMd5Hash());
|
||||
CorrelationAttributeInstance cei = new CorrelationAttributeInstance(
|
||||
new EamCase(Case.getCurrentCase().getName(), Case.getCurrentCase().getDisplayName()),
|
||||
new CorrelationCase(Case.getCurrentCase().getName(), Case.getCurrentCase().getDisplayName()),
|
||||
CorrelationDataSource.fromTSKDataSource(af.getDataSource()),
|
||||
af.getParentPath() + af.getName(),
|
||||
comment,
|
||||
@ -263,4 +258,38 @@ public class EamArtifactUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given abstract file should be processed for
|
||||
* the central repository.
|
||||
* @param af The file to test
|
||||
* @return true if the file should be added to the central repo, false otherwise
|
||||
*/
|
||||
public static boolean isValidCentralRepoFile(AbstractFile af){
|
||||
if(af == null){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(af.getKnown() == TskData.FileKnown.KNOWN){
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (af.getType()){
|
||||
case UNALLOC_BLOCKS:
|
||||
case UNUSED_BLOCKS:
|
||||
case SLACK:
|
||||
case VIRTUAL_DIR:
|
||||
case LOCAL_DIR:
|
||||
return false;
|
||||
case CARVED:
|
||||
case DERIVED:
|
||||
case LOCAL:
|
||||
return true;
|
||||
case FS:
|
||||
return af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC);
|
||||
default:
|
||||
LOGGER.log(Level.WARNING, "Unexpected file type {0}", af.getType().getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,21 +147,21 @@ public interface EamDb {
|
||||
*
|
||||
* @param eamCase The case to add
|
||||
*/
|
||||
void newCase(EamCase eamCase) throws EamDbException;
|
||||
void newCase(CorrelationCase eamCase) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Creates new Case in the database from the given case
|
||||
*
|
||||
* @param case The case to add
|
||||
*/
|
||||
EamCase newCase(Case autopsyCase) throws EamDbException;
|
||||
CorrelationCase newCase(Case autopsyCase) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Updates an existing Case in the database
|
||||
*
|
||||
* @param eamCase The case to update
|
||||
*/
|
||||
void updateCase(EamCase eamCase) throws EamDbException;
|
||||
void updateCase(CorrelationCase eamCase) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Retrieves Case details based on Case UUID
|
||||
@ -170,14 +170,14 @@ public interface EamDb {
|
||||
*
|
||||
* @return The retrieved case
|
||||
*/
|
||||
EamCase getCaseDetails(String caseUUID) throws EamDbException;
|
||||
CorrelationCase getCaseByUUID(String caseUUID) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Retrieves cases that are in DB.
|
||||
*
|
||||
* @return List of cases
|
||||
*/
|
||||
List<EamCase> getCases() throws EamDbException;
|
||||
List<CorrelationCase> getCases() throws EamDbException;
|
||||
|
||||
/**
|
||||
* Creates new Data Source in the database
|
||||
@ -191,7 +191,7 @@ public interface EamDb {
|
||||
*
|
||||
* @param eamDataSource the data source to update
|
||||
*/
|
||||
void updateDataSource(CorrelationDataSource eamDataSource) throws EamDbException;
|
||||
//void updateDataSource(CorrelationDataSource eamDataSource) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Retrieves Data Source details based on data source device ID
|
||||
@ -312,7 +312,7 @@ public interface EamDb {
|
||||
/**
|
||||
* Executes a bulk insert of the cases
|
||||
*/
|
||||
void bulkInsertCases(List<EamCase> cases) throws EamDbException;
|
||||
void bulkInsertCases(List<CorrelationCase> cases) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Sets an eamArtifact instance to the given known status. If eamArtifact
|
||||
|
@ -271,7 +271,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
* @param case The case to add
|
||||
*/
|
||||
@Override
|
||||
public EamCase newCase(Case autopsyCase) throws EamDbException {
|
||||
public CorrelationCase newCase(Case autopsyCase) throws EamDbException {
|
||||
try{
|
||||
acquireExclusiveLock();
|
||||
return super.newCase(autopsyCase);
|
||||
@ -288,7 +288,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
* @param eamCase The case to add
|
||||
*/
|
||||
@Override
|
||||
public void newCase(EamCase eamCase) throws EamDbException {
|
||||
public void newCase(CorrelationCase eamCase) throws EamDbException {
|
||||
try{
|
||||
acquireExclusiveLock();
|
||||
super.newCase(eamCase);
|
||||
@ -303,7 +303,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
* @param eamCase The case to update
|
||||
*/
|
||||
@Override
|
||||
public void updateCase(EamCase eamCase) throws EamDbException {
|
||||
public void updateCase(CorrelationCase eamCase) throws EamDbException {
|
||||
try{
|
||||
acquireExclusiveLock();
|
||||
super.updateCase(eamCase);
|
||||
@ -320,10 +320,10 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
* @return The retrieved case
|
||||
*/
|
||||
@Override
|
||||
public EamCase getCaseDetails(String caseUUID) throws EamDbException {
|
||||
public CorrelationCase getCaseByUUID(String caseUUID) throws EamDbException {
|
||||
try{
|
||||
acquireSharedLock();
|
||||
return super.getCaseDetails(caseUUID);
|
||||
return super.getCaseByUUID(caseUUID);
|
||||
} finally {
|
||||
releaseSharedLock();
|
||||
}
|
||||
@ -335,7 +335,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
* @return List of cases
|
||||
*/
|
||||
@Override
|
||||
public List<EamCase> getCases() throws EamDbException {
|
||||
public List<CorrelationCase> getCases() throws EamDbException {
|
||||
try{
|
||||
acquireSharedLock();
|
||||
return super.getCases();
|
||||
@ -364,15 +364,15 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
*
|
||||
* @param eamDataSource the data source to update
|
||||
*/
|
||||
@Override
|
||||
public void updateDataSource(CorrelationDataSource eamDataSource) throws EamDbException {
|
||||
try{
|
||||
acquireExclusiveLock();
|
||||
super.updateDataSource(eamDataSource);
|
||||
} finally {
|
||||
releaseExclusiveLock();
|
||||
}
|
||||
}
|
||||
// @Override
|
||||
// public void updateDataSource(CorrelationDataSource eamDataSource) throws EamDbException {
|
||||
// try{
|
||||
// acquireExclusiveLock();
|
||||
// super.updateDataSource(eamDataSource);
|
||||
// } finally {
|
||||
// releaseExclusiveLock();
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Retrieves Data Source details based on data source device ID
|
||||
@ -561,7 +561,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
* Executes a bulk insert of the cases
|
||||
*/
|
||||
@Override
|
||||
public void bulkInsertCases(List<EamCase> cases) throws EamDbException {
|
||||
public void bulkInsertCases(List<CorrelationCase> cases) throws EamDbException {
|
||||
try{
|
||||
acquireExclusiveLock();
|
||||
super.bulkInsertCases(cases);
|
||||
|
@ -34,7 +34,7 @@ import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
@ -279,7 +279,7 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
LOGGER.log(Level.SEVERE, "Error adding tag.", ex); // NON-NLS
|
||||
}
|
||||
|
||||
EamCase curCeCase = new EamCase(
|
||||
CorrelationCase curCeCase = new CorrelationCase(
|
||||
-1,
|
||||
curCase.getName(), // unique case ID
|
||||
EamOrganization.getDefault(),
|
||||
@ -298,7 +298,7 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
try {
|
||||
// NOTE: Cannot determine if the opened case is a new case or a reopened case,
|
||||
// so check for existing name in DB and insert if missing.
|
||||
EamCase existingCase = dbManager.getCaseDetails(curCeCase.getCaseUUID());
|
||||
CorrelationCase existingCase = dbManager.getCaseByUUID(curCeCase.getCaseUUID());
|
||||
|
||||
if (null == existingCase) {
|
||||
dbManager.newCase(curCeCase);
|
||||
@ -321,7 +321,7 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
String newName = (String)evt.getNewValue();
|
||||
try {
|
||||
// See if the case is in the database. If it is, update the display name.
|
||||
EamCase existingCase = dbManager.getCaseDetails(Case.getCurrentCase().getName());
|
||||
CorrelationCase existingCase = dbManager.getCaseByUUID(Case.getCurrentCase().getName());
|
||||
|
||||
if (null != existingCase) {
|
||||
existingCase.setDisplayName(newName);
|
||||
|
@ -51,7 +51,7 @@ public class IngestEventsListener {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CorrelationAttribute.class.getName());
|
||||
|
||||
final Collection<String> addedCeArtifactTrackerSet = new LinkedHashSet<>();
|
||||
final Collection<String> recentlyAddedCeArtifacts = new LinkedHashSet<>();
|
||||
private static int ceModuleInstanceCount = 0;
|
||||
private final PropertyChangeListener pcl1 = new IngestModuleEventListener();
|
||||
private final PropertyChangeListener pcl2 = new IngestJobEventListener();
|
||||
@ -139,7 +139,7 @@ public class IngestEventsListener {
|
||||
for (CorrelationAttribute eamArtifact : convertedArtifacts) {
|
||||
try {
|
||||
// Only do something with this artifact if it's unique within the job
|
||||
if (addedCeArtifactTrackerSet.add(eamArtifact.toString())) {
|
||||
if (recentlyAddedCeArtifacts.add(eamArtifact.toString())) {
|
||||
// Was it previously marked as bad?
|
||||
// query db for artifact instances having this TYPE/VALUE and knownStatus = "Bad".
|
||||
// if gettKnownStatus() is "Unknown" and this artifact instance was marked bad in a previous case,
|
||||
@ -178,10 +178,10 @@ public class IngestEventsListener {
|
||||
switch (IngestManager.IngestJobEvent.valueOf(evt.getPropertyName())) {
|
||||
case DATA_SOURCE_ANALYSIS_COMPLETED: {
|
||||
// clear the tracker to reduce memory usage
|
||||
// @@@ This isnt' entirely accurate to do here. We could have multiple
|
||||
// ingest jobs at the same time
|
||||
addedCeArtifactTrackerSet.clear();
|
||||
|
||||
if (getCeModuleInstanceCount() == 0) {
|
||||
recentlyAddedCeArtifacts.clear();
|
||||
}
|
||||
//else another instance of the Correlation Engine Module is still being run.
|
||||
} // DATA_SOURCE_ANALYSIS_COMPLETED
|
||||
break;
|
||||
}
|
||||
|
@ -18,12 +18,11 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.centralrepository.ingestmodule;
|
||||
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
@ -41,6 +40,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeIns
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbPlatformEnum;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
@ -49,7 +49,6 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.centralrepository.eventlisteners.IngestEventsListener;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
|
||||
/**
|
||||
* Ingest module for inserting entries into the Central Repository database on
|
||||
@ -64,7 +63,7 @@ class IngestModule implements FileIngestModule {
|
||||
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
|
||||
private static final IngestModuleReferenceCounter warningMsgRefCounter = new IngestModuleReferenceCounter();
|
||||
private long jobId;
|
||||
private EamCase eamCase;
|
||||
private CorrelationCase eamCase;
|
||||
private CorrelationDataSource eamDataSource;
|
||||
private Blackboard blackboard;
|
||||
private CorrelationAttribute.Type filesType;
|
||||
@ -83,12 +82,7 @@ class IngestModule implements FileIngestModule {
|
||||
|
||||
blackboard = Case.getCurrentCase().getServices().getBlackboard();
|
||||
|
||||
if ((af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
|
||||
|| (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)
|
||||
|| (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)
|
||||
|| (af.getKnown() == TskData.FileKnown.KNOWN)
|
||||
|| (af.isDir() == true)
|
||||
|| (!af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC))) {
|
||||
if (! EamArtifactUtil.isValidCentralRepoFile(af)) {
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
@ -216,7 +210,7 @@ class IngestModule implements FileIngestModule {
|
||||
throw new IngestModuleException("Cannot run on a multi-user case with a SQLite central repository."); // NON-NLS
|
||||
}
|
||||
jobId = context.getJobId();
|
||||
eamCase = new EamCase(Case.getCurrentCase().getName(), Case.getCurrentCase().getDisplayName());
|
||||
eamCase = new CorrelationCase(Case.getCurrentCase().getName(), Case.getCurrentCase().getDisplayName());
|
||||
|
||||
try {
|
||||
eamDataSource = CorrelationDataSource.fromTSKDataSource(context.getDataSource());
|
||||
@ -256,9 +250,9 @@ class IngestModule implements FileIngestModule {
|
||||
}
|
||||
|
||||
// ensure we have this case defined in the EAM DB
|
||||
EamCase existingCase;
|
||||
CorrelationCase existingCase;
|
||||
Case curCase = Case.getCurrentCase();
|
||||
EamCase curCeCase = new EamCase(
|
||||
CorrelationCase curCeCase = new CorrelationCase(
|
||||
-1,
|
||||
curCase.getName(), // unique case ID
|
||||
EamOrganization.getDefault(),
|
||||
@ -270,7 +264,7 @@ class IngestModule implements FileIngestModule {
|
||||
null,
|
||||
null);
|
||||
try {
|
||||
existingCase = dbManager.getCaseDetails(curCeCase.getCaseUUID());
|
||||
existingCase = dbManager.getCaseByUUID(curCeCase.getCaseUUID());
|
||||
if (existingCase == null) {
|
||||
dbManager.newCase(curCeCase);
|
||||
}
|
||||
|
@ -147,6 +147,7 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
||||
public Action[] getActions(boolean context) {
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
actionsList.addAll(Arrays.asList(super.getActions(true)));
|
||||
|
||||
if (!this.getDirectoryBrowseMode()) {
|
||||
actionsList.add(new ViewContextAction(Bundle.FileNode_getActions_viewFileInDir_text(), this));
|
||||
actionsList.add(null); // Creates an item separator
|
||||
|
@ -77,7 +77,6 @@ public class SlackFileNode extends AbstractFsContentNode<AbstractFile> {
|
||||
for (Action a : super.getActions(true)) {
|
||||
actionsList.add(a);
|
||||
}
|
||||
|
||||
if (!this.getDirectoryBrowseMode()) {
|
||||
actionsList.add(new ViewContextAction(NbBundle.getMessage(this.getClass(), "SlackFileNode.viewFileInDir.text"), this.content));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
|
@ -36,6 +36,7 @@ import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
import org.sleuthkit.datamodel.Volume;
|
||||
import org.sleuthkit.autopsy.directorytree.FileSystemDetailsAction;
|
||||
|
||||
/**
|
||||
* This class is used to represent the "Node" for the volume. Its child is the
|
||||
@ -139,7 +140,7 @@ public class VolumeNode extends AbstractContentNode<Volume> {
|
||||
for (Action a : super.getActions(true)) {
|
||||
actionsList.add(a);
|
||||
}
|
||||
|
||||
actionsList.add(new FileSystemDetailsAction(content));
|
||||
actionsList.add(new NewWindowViewAction(
|
||||
NbBundle.getMessage(this.getClass(), "VolumeNode.getActions.viewInNewWin.text"), this));
|
||||
actionsList.addAll(ExplorerNodeActionVisitor.getActions(content));
|
||||
|
@ -3,7 +3,6 @@ HINT_DirectoryTreeTopComponent=This is a DirectoryTree window
|
||||
OpenIDE-Module-Name=DirectoryTree
|
||||
FileSystemDetailsPanel.imgOffsetLabel.text=Image Offset:
|
||||
FileSystemDetailsPanel.fsTypeLabel.text=FileSystem Type:
|
||||
FileSystemDetailsPanel.genInfoLabel.text=General File Information
|
||||
FileSystemDetailsPanel.jLabel2.text=bytes
|
||||
FileSystemDetailsPanel.jLabel3.text=bytes
|
||||
FileSystemDetailsPanel.fsTypeValue.text=...
|
||||
@ -14,7 +13,6 @@ FileSystemDetailsPanel.blockCountValue.text=...
|
||||
FileSystemDetailsPanel.rootInumValue.text=...
|
||||
FileSystemDetailsPanel.firstInumValue.text=...
|
||||
FileSystemDetailsPanel.lastInumValue.text=...
|
||||
FileSystemDetailsPanel.jLabel1.text=Detailed File Information
|
||||
FileSystemDetailsPanel.volumeIDLabel.text=Volume ID:
|
||||
FileSystemDetailsPanel.blockSizeLabel.text=Block Size:
|
||||
FileSystemDetailsPanel.blockCountLabel.text=Block Count:
|
||||
|
@ -3,7 +3,6 @@ HINT_DirectoryTreeTopComponent=\u3053\u308c\u306f\u30c7\u30a3\u30ec\u30af\u30c8\
|
||||
OpenIDE-Module-Name=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30c4\u30ea\u30fc
|
||||
FileSystemDetailsPanel.imgOffsetLabel.text=\u30a4\u30e1\u30fc\u30b8\u30aa\u30d5\u30bb\u30c3\u30c8\uff1a
|
||||
FileSystemDetailsPanel.fsTypeLabel.text=\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u30bf\u30a4\u30d7\uff1a
|
||||
FileSystemDetailsPanel.genInfoLabel.text=\u30d5\u30a1\u30a4\u30eb\u4e00\u822c\u60c5\u5831
|
||||
FileSystemDetailsPanel.jLabel2.text=\u30d0\u30a4\u30c8
|
||||
FileSystemDetailsPanel.jLabel3.text=\u30d0\u30a4\u30c8
|
||||
FileSystemDetailsPanel.fsTypeValue.text=...
|
||||
@ -14,7 +13,6 @@ FileSystemDetailsPanel.blockCountValue.text=...
|
||||
FileSystemDetailsPanel.rootInumValue.text=...
|
||||
FileSystemDetailsPanel.firstInumValue.text=...
|
||||
FileSystemDetailsPanel.lastInumValue.text=...
|
||||
FileSystemDetailsPanel.jLabel1.text=\u30d5\u30a1\u30a4\u30eb\u8a73\u7d30\u60c5\u5831
|
||||
FileSystemDetailsPanel.volumeIDLabel.text=\u30dc\u30ea\u30e5\u30fc\u30e0ID\uff1a
|
||||
FileSystemDetailsPanel.blockSizeLabel.text=\u30d6\u30ed\u30c3\u30af\u30b5\u30a4\u30ba\uff1a
|
||||
FileSystemDetailsPanel.blockCountLabel.text=\u30d6\u30ed\u30c3\u30af\u6570\uff1a
|
||||
|
@ -19,6 +19,7 @@
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
@ -42,6 +43,7 @@ import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
import org.sleuthkit.datamodel.Volume;
|
||||
|
||||
/**
|
||||
* A node filter (decorator) that sets the actions for a node in the tree view
|
||||
@ -78,9 +80,10 @@ class DirectoryTreeFilterNode extends FilterNode {
|
||||
public String getDisplayName() {
|
||||
final Node orig = getOriginal();
|
||||
String name = orig.getDisplayName();
|
||||
|
||||
if (orig instanceof AbstractContentNode) {
|
||||
AbstractFile file = getLookup().lookup(AbstractFile.class);
|
||||
if ((file != null) && (false == (orig instanceof BlackboardArtifactNode)) ){
|
||||
if ((file != null) && (false == (orig instanceof BlackboardArtifactNode))) {
|
||||
try {
|
||||
int numVisibleChildren = getVisibleChildCount(file);
|
||||
|
||||
@ -94,8 +97,7 @@ class DirectoryTreeFilterNode extends FilterNode {
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
else if (orig instanceof BlackboardArtifactNode) {
|
||||
} else if (orig instanceof BlackboardArtifactNode) {
|
||||
BlackboardArtifact artifact = ((BlackboardArtifactNode) orig).getArtifact();
|
||||
try {
|
||||
int numAttachments = artifact.getChildrenCount();
|
||||
@ -134,19 +136,18 @@ class DirectoryTreeFilterNode extends FilterNode {
|
||||
|| (purgeSlackFiles && childFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
|
||||
numVisibleChildren--;
|
||||
}
|
||||
} else if(child instanceof BlackboardArtifact){
|
||||
} else if (child instanceof BlackboardArtifact) {
|
||||
BlackboardArtifact bba = (BlackboardArtifact) child;
|
||||
|
||||
// Only message type artifacts are displayed in the tree
|
||||
if((bba.getArtifactTypeID() != ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID())
|
||||
&& (bba.getArtifactTypeID() != ARTIFACT_TYPE.TSK_MESSAGE.getTypeID())){
|
||||
if ((bba.getArtifactTypeID() != ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID())
|
||||
&& (bba.getArtifactTypeID() != ARTIFACT_TYPE.TSK_MESSAGE.getTypeID())) {
|
||||
numVisibleChildren--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return numVisibleChildren;
|
||||
}
|
||||
|
||||
@ -161,32 +162,10 @@ class DirectoryTreeFilterNode extends FilterNode {
|
||||
@Override
|
||||
public Action[] getActions(boolean context) {
|
||||
List<Action> actions = new ArrayList<>();
|
||||
|
||||
final Content content = this.getLookup().lookup(Content.class);
|
||||
if (content != null) {
|
||||
actions.addAll(ExplorerNodeActionVisitor.getActions(content));
|
||||
|
||||
Directory dir = this.getLookup().lookup(Directory.class);
|
||||
if (dir != null) {
|
||||
actions.add(ExtractAction.getInstance());
|
||||
actions.add(new RunIngestModulesAction(dir));
|
||||
}
|
||||
|
||||
final Image img = this.getLookup().lookup(Image.class);
|
||||
final VirtualDirectory virtualDirectory = this.getLookup().lookup(VirtualDirectory.class);
|
||||
boolean isRootVD = false;
|
||||
if (virtualDirectory != null) {
|
||||
try {
|
||||
if (virtualDirectory.getParent() == null) {
|
||||
isRootVD = true;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error determining the parent of the virtual directory", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
if (img != null || isRootVD) {
|
||||
actions.add(new FileSearchAction(NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.openFileSrcByAttr.text")));
|
||||
actions.add(new RunIngestModulesAction(Collections.<Content>singletonList(content)));
|
||||
}
|
||||
actions.addAll(Arrays.asList(super.getActions(true)));
|
||||
}
|
||||
actions.add(collapseAllAction);
|
||||
return actions.toArray(new Action[actions.size()]);
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.datamodel.Volume;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Action which opens a dialog containing the FileSystemDetailsPanel.
|
||||
*/
|
||||
final public class FileSystemDetailsAction extends AbstractAction {
|
||||
private static final Logger logger = Logger.getLogger(FileSystemDetailsPanel.class.getName());
|
||||
final Volume fsContent;
|
||||
|
||||
@NbBundle.Messages({"FileSystemDetailsAction.title.text=File System Details"})
|
||||
public FileSystemDetailsAction(Volume content) {
|
||||
super(Bundle.FileSystemDetailsAction_title_text());
|
||||
enabled = false;
|
||||
fsContent = content;
|
||||
try {
|
||||
if (!fsContent.getFileSystems().isEmpty()) {
|
||||
enabled = true;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Unable to create FileSystemDetailsAction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
FileSystemDetailsDialog fsDetailsDialog = new FileSystemDetailsDialog();
|
||||
fsDetailsDialog.display(fsContent);
|
||||
|
||||
}
|
||||
|
||||
private final class FileSystemDetailsDialog extends JDialog implements ActionListener {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private FileSystemDetailsDialog() {
|
||||
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
||||
Bundle.FileSystemDetailsAction_title_text(),
|
||||
false);
|
||||
}
|
||||
|
||||
private void display(Volume content) {
|
||||
FileSystemDetailsPanel fsPanel = new FileSystemDetailsPanel(content);
|
||||
fsPanel.setOKButtonActionListener(this);
|
||||
setContentPane(fsPanel);
|
||||
pack();
|
||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -19,12 +19,12 @@
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="367" max="-2" attributes="0"/>
|
||||
<Component id="OKButton" min="-2" pref="93" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="genInfoPanel" min="-2" pref="534" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jSplitPane1" min="-2" pref="786" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="221" max="-2" attributes="0"/>
|
||||
<Component id="OKButton" min="-2" pref="93" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
@ -35,10 +35,10 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jSplitPane1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="genInfoPanel" min="-2" pref="114" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="OKButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="1"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -51,14 +51,6 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="180"/>
|
||||
<Property name="orientation" type="int" value="0"/>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="genInfoPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
@ -70,66 +62,58 @@
|
||||
<Dimension value="[815, 170]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="top"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="95" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="fsTypeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="imgOffsetLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="volumeIDLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="blockSizeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="108" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="genInfoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="blockSizeValue" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="volumeIDValue" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="imgOffsetValue" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="fsTypeValue" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="blockSizeValue" pref="112" max="32767" attributes="0"/>
|
||||
<Component id="imgOffsetValue" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="31" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="33" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="volumeIDValue" max="32767" attributes="0"/>
|
||||
<Component id="fsTypeValue" alignment="0" min="-2" pref="145" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="jSeparator1" min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="31" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="blockCountLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="rootInumLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="firstInumLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lastInumLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="111" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lastInumValue" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="firstInumValue" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="rootInumValue" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="blockCountValue" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="blockCountValue" pref="128" max="32767" attributes="0"/>
|
||||
<Component id="rootInumValue" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="firstInumValue" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="lastInumValue" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="245" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace pref="23" max="32767" attributes="0"/>
|
||||
<Component id="genInfoLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
@ -177,7 +161,7 @@
|
||||
<Component id="lastInumLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="jSeparator1" pref="101" max="32767" attributes="1"/>
|
||||
<Component id="jSeparator1" max="32767" attributes="1"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -377,18 +361,6 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="genInfoLabel">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
|
||||
<FontInfo relative="true">
|
||||
<Font bold="true" component="genInfoLabel" property="font" relativeSize="false" size="18"/>
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="FileSystemDetailsPanel.genInfoLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator1">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="1"/>
|
||||
@ -420,59 +392,5 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="detailInfoPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[516, 293]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace pref="278" max="32767" attributes="0"/>
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="276" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="235" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel1">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
|
||||
<FontInfo relative="true">
|
||||
<Font bold="true" component="jLabel1" property="font" relativeSize="false" size="18"/>
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="FileSystemDetailsPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,15 +18,21 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.sleuthkit.datamodel.FileSystem;
|
||||
import org.sleuthkit.datamodel.Volume;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* This is the form / panel to show the File System Details.
|
||||
*
|
||||
* @author jantonius
|
||||
*/
|
||||
class FileSystemDetailsPanel extends javax.swing.JPanel {
|
||||
final class FileSystemDetailsPanel extends javax.swing.JPanel {
|
||||
private static final Logger logger = Logger.getLogger(FileSystemDetailsPanel.class.getName());
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates new form FileSystemDetailsPanel
|
||||
@ -35,6 +41,24 @@ class FileSystemDetailsPanel extends javax.swing.JPanel {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
FileSystemDetailsPanel(Volume content) {
|
||||
initComponents();
|
||||
try {
|
||||
FileSystem fSystem = content.getFileSystems().get(0); //Autopsy currently only supports one file system per Volume
|
||||
setFileSystemTypeValue(fSystem.getFsType().toString());
|
||||
setImageOffsetValue(Long.toString(fSystem.getImageOffset()));
|
||||
setVolumeIDValue(Long.toString(fSystem.getId()));
|
||||
setBlockSizeValue(Long.toString(fSystem.getBlock_size()));
|
||||
setBlockCountValue(Long.toString(fSystem.getBlock_count()));
|
||||
setRootInumValue(Long.toString(fSystem.getRoot_inum()));
|
||||
setFirstInumValue(Long.toString(fSystem.getFirst_inum()));
|
||||
setLastInumValue(Long.toString(fSystem.getLastInum()));
|
||||
} catch (TskCoreException|ArrayIndexOutOfBoundsException ex) {
|
||||
logger.log(Level.SEVERE, "Unable to construct FileSystemDetailsPanel",ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -45,7 +69,6 @@ class FileSystemDetailsPanel extends javax.swing.JPanel {
|
||||
private void initComponents() {
|
||||
|
||||
OKButton = new javax.swing.JButton();
|
||||
jSplitPane1 = new javax.swing.JSplitPane();
|
||||
genInfoPanel = new javax.swing.JPanel();
|
||||
fsTypeLabel = new javax.swing.JLabel();
|
||||
imgOffsetLabel = new javax.swing.JLabel();
|
||||
@ -63,18 +86,12 @@ class FileSystemDetailsPanel extends javax.swing.JPanel {
|
||||
rootInumValue = new javax.swing.JLabel();
|
||||
firstInumValue = new javax.swing.JLabel();
|
||||
lastInumValue = new javax.swing.JLabel();
|
||||
genInfoLabel = new javax.swing.JLabel();
|
||||
jSeparator1 = new javax.swing.JSeparator();
|
||||
jLabel2 = new javax.swing.JLabel();
|
||||
jLabel3 = new javax.swing.JLabel();
|
||||
detailInfoPanel = new javax.swing.JPanel();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
|
||||
OKButton.setText(org.openide.util.NbBundle.getMessage(FileSystemDetailsPanel.class, "FileSystemDetailsPanel.OKButton.text")); // NOI18N
|
||||
|
||||
jSplitPane1.setDividerLocation(180);
|
||||
jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
||||
|
||||
genInfoPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||
genInfoPanel.setPreferredSize(new java.awt.Dimension(815, 170));
|
||||
|
||||
@ -126,9 +143,6 @@ class FileSystemDetailsPanel extends javax.swing.JPanel {
|
||||
lastInumValue.setFont(lastInumValue.getFont().deriveFont(lastInumValue.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
lastInumValue.setText(org.openide.util.NbBundle.getMessage(FileSystemDetailsPanel.class, "FileSystemDetailsPanel.lastInumValue.text")); // NOI18N
|
||||
|
||||
genInfoLabel.setFont(genInfoLabel.getFont().deriveFont(genInfoLabel.getFont().getStyle() | java.awt.Font.BOLD, 18));
|
||||
genInfoLabel.setText(org.openide.util.NbBundle.getMessage(FileSystemDetailsPanel.class, "FileSystemDetailsPanel.genInfoLabel.text")); // NOI18N
|
||||
|
||||
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
|
||||
|
||||
jLabel2.setFont(jLabel2.getFont().deriveFont(jLabel2.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
@ -142,47 +156,44 @@ class FileSystemDetailsPanel extends javax.swing.JPanel {
|
||||
genInfoPanelLayout.setHorizontalGroup(
|
||||
genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(genInfoPanelLayout.createSequentialGroup()
|
||||
.addGap(95, 95, 95)
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(fsTypeLabel)
|
||||
.addComponent(imgOffsetLabel)
|
||||
.addComponent(volumeIDLabel)
|
||||
.addComponent(blockSizeLabel))
|
||||
.addGap(108, 108, 108)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(genInfoLabel)
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addGroup(genInfoPanelLayout.createSequentialGroup()
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(blockSizeValue)
|
||||
.addComponent(volumeIDValue)
|
||||
.addComponent(imgOffsetValue)
|
||||
.addComponent(fsTypeValue))
|
||||
.addGap(31, 31, 31)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(blockSizeValue, javax.swing.GroupLayout.DEFAULT_SIZE, 112, Short.MAX_VALUE)
|
||||
.addComponent(imgOffsetValue, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel2)
|
||||
.addComponent(jLabel3))
|
||||
.addGap(33, 33, 33)
|
||||
.addComponent(jLabel3)))
|
||||
.addComponent(volumeIDValue, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(fsTypeValue, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(31, 31, 31)
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(blockCountLabel)
|
||||
.addComponent(rootInumLabel)
|
||||
.addComponent(firstInumLabel)
|
||||
.addComponent(lastInumLabel))
|
||||
.addGap(111, 111, 111)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lastInumValue)
|
||||
.addComponent(firstInumValue)
|
||||
.addComponent(rootInumValue)
|
||||
.addComponent(blockCountValue))))
|
||||
.addGap(245, 245, 245))
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(blockCountValue, javax.swing.GroupLayout.DEFAULT_SIZE, 128, Short.MAX_VALUE)
|
||||
.addComponent(rootInumValue, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(firstInumValue, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(lastInumValue, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
genInfoPanelLayout.setVerticalGroup(
|
||||
genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, genInfoPanelLayout.createSequentialGroup()
|
||||
.addContainerGap(23, Short.MAX_VALUE)
|
||||
.addComponent(genInfoLabel)
|
||||
.addGap(18, 18, 18)
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(genInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -222,57 +233,30 @@ class FileSystemDetailsPanel extends javax.swing.JPanel {
|
||||
.addComponent(firstInumLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(lastInumLabel)))
|
||||
.addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 101, Short.MAX_VALUE))
|
||||
.addComponent(jSeparator1))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jSplitPane1.setTopComponent(genInfoPanel);
|
||||
|
||||
detailInfoPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||
detailInfoPanel.setPreferredSize(new java.awt.Dimension(516, 293));
|
||||
|
||||
jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() | java.awt.Font.BOLD, 18));
|
||||
jLabel1.setText(org.openide.util.NbBundle.getMessage(FileSystemDetailsPanel.class, "FileSystemDetailsPanel.jLabel1.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout detailInfoPanelLayout = new javax.swing.GroupLayout(detailInfoPanel);
|
||||
detailInfoPanel.setLayout(detailInfoPanelLayout);
|
||||
detailInfoPanelLayout.setHorizontalGroup(
|
||||
detailInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, detailInfoPanelLayout.createSequentialGroup()
|
||||
.addContainerGap(278, Short.MAX_VALUE)
|
||||
.addComponent(jLabel1)
|
||||
.addGap(276, 276, 276))
|
||||
);
|
||||
detailInfoPanelLayout.setVerticalGroup(
|
||||
detailInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(detailInfoPanelLayout.createSequentialGroup()
|
||||
.addGap(23, 23, 23)
|
||||
.addComponent(jLabel1)
|
||||
.addContainerGap(235, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
jSplitPane1.setRightComponent(detailInfoPanel);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(367, 367, 367)
|
||||
.addComponent(OKButton, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 786, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addComponent(genInfoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 534, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(221, 221, 221)
|
||||
.addComponent(OKButton, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(genInfoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(OKButton)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
@ -364,20 +348,16 @@ class FileSystemDetailsPanel extends javax.swing.JPanel {
|
||||
private javax.swing.JLabel blockCountValue;
|
||||
private javax.swing.JLabel blockSizeLabel;
|
||||
private javax.swing.JLabel blockSizeValue;
|
||||
private javax.swing.JPanel detailInfoPanel;
|
||||
private javax.swing.JLabel firstInumLabel;
|
||||
private javax.swing.JLabel firstInumValue;
|
||||
private javax.swing.JLabel fsTypeLabel;
|
||||
private javax.swing.JLabel fsTypeValue;
|
||||
private javax.swing.JLabel genInfoLabel;
|
||||
private javax.swing.JPanel genInfoPanel;
|
||||
private javax.swing.JLabel imgOffsetLabel;
|
||||
private javax.swing.JLabel imgOffsetValue;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JLabel jLabel2;
|
||||
private javax.swing.JLabel jLabel3;
|
||||
private javax.swing.JSeparator jSeparator1;
|
||||
private javax.swing.JSplitPane jSplitPane1;
|
||||
private javax.swing.JLabel lastInumLabel;
|
||||
private javax.swing.JLabel lastInumValue;
|
||||
private javax.swing.JLabel rootInumLabel;
|
||||
|
@ -72,8 +72,8 @@ public class ViewContextAction extends AbstractAction {
|
||||
*/
|
||||
public ViewContextAction(String displayName, BlackboardArtifactNode artifactNode) {
|
||||
super(displayName);
|
||||
this.content = artifactNode.getLookup().lookup(Content.class);
|
||||
if (content instanceof AbstractFile) {
|
||||
this.content = artifactNode.getLookup().lookup(AbstractFile.class);
|
||||
if(this.content != null) {
|
||||
AbstractFile file = (AbstractFile) content;
|
||||
if ((TskData.FileKnown.KNOWN == file.getKnown() && UserPreferences.hideKnownFilesInDataSourcesTree())
|
||||
|| (TskData.TSK_DB_FILES_TYPE_ENUM.SLACK == file.getType() && UserPreferences.hideSlackFilesInDataSourcesTree())) {
|
||||
|
@ -23,13 +23,12 @@ import java.awt.event.ActionEvent;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JOptionPane;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
@ -41,7 +40,7 @@ import org.sleuthkit.datamodel.Directory;
|
||||
* When the data source is pressed, it should open the wizard for ingest
|
||||
* modules.
|
||||
*/
|
||||
public final class RunIngestModulesAction extends CallableSystemAction {
|
||||
public final class RunIngestModulesAction extends AbstractAction {
|
||||
|
||||
@Messages("RunIngestModulesAction.name=Run Ingest Modules")
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -51,6 +50,21 @@ public final class RunIngestModulesAction extends CallableSystemAction {
|
||||
* used instead of this wizard and is retained for backwards compatibility.
|
||||
*/
|
||||
private static final String EXECUTION_CONTEXT = "org.sleuthkit.autopsy.ingest.RunIngestModulesDialog";
|
||||
/**
|
||||
* Display any warnings that the ingestJobSettings have.
|
||||
*
|
||||
* @param ingestJobSettings
|
||||
*/
|
||||
private static void showWarnings(IngestJobSettings ingestJobSettings) {
|
||||
List<String> warnings = ingestJobSettings.getWarnings();
|
||||
if (warnings.isEmpty() == false) {
|
||||
StringBuilder warningMessage = new StringBuilder(1024);
|
||||
for (String warning : warnings) {
|
||||
warningMessage.append(warning).append("\n");
|
||||
}
|
||||
JOptionPane.showMessageDialog(null, warningMessage.toString());
|
||||
}
|
||||
}
|
||||
private final List<Content> dataSources = new ArrayList<>();
|
||||
private final IngestJobSettings.IngestType ingestType;
|
||||
|
||||
@ -103,35 +117,9 @@ public final class RunIngestModulesAction extends CallableSystemAction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display any warnings that the ingestJobSettings have.
|
||||
*
|
||||
* @param ingestJobSettings
|
||||
*/
|
||||
private static void showWarnings(IngestJobSettings ingestJobSettings) {
|
||||
List<String> warnings = ingestJobSettings.getWarnings();
|
||||
if (warnings.isEmpty() == false) {
|
||||
StringBuilder warningMessage = new StringBuilder(1024);
|
||||
for (String warning : warnings) {
|
||||
warningMessage.append(warning).append("\n");
|
||||
}
|
||||
JOptionPane.showMessageDialog(null, warningMessage.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
actionPerformed(null);
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
throw new CloneNotSupportedException("Clone is not supported for the RunIngestModulesAction");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return Bundle.RunIngestModulesAction_name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
return HelpCtx.DEFAULT_HELP;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -208,13 +208,14 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
* is set when the stage is set.
|
||||
*
|
||||
* @param newStage The processing stage.
|
||||
* @param stageStartDate The date and time this stage started.
|
||||
*/
|
||||
synchronized void setProcessingStage(Stage newStage) {
|
||||
synchronized void setProcessingStage(Stage newStage, Date stageStartDate) {
|
||||
if (Stage.CANCELLING == this.stage && Stage.COMPLETED != newStage) {
|
||||
return;
|
||||
}
|
||||
this.stage = newStage;
|
||||
this.stageStartDate = Date.from(Instant.now());
|
||||
this.stageStartDate = stageStartDate;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -319,7 +320,7 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
* Cancels the job.
|
||||
*/
|
||||
synchronized void cancel() {
|
||||
setProcessingStage(Stage.CANCELLING);
|
||||
setProcessingStage(Stage.CANCELLING, Date.from(Instant.now()));
|
||||
cancelled = true;
|
||||
errorsOccurred = true;
|
||||
if (null != dataSourceProcessor) {
|
||||
@ -347,7 +348,7 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
* the job.
|
||||
*/
|
||||
synchronized void setCompleted() {
|
||||
setProcessingStage(Stage.COMPLETED);
|
||||
setProcessingStage(Stage.COMPLETED, Date.from(Instant.now()));
|
||||
completed = true;
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ final class AutoIngestJobNodeData {
|
||||
AutoIngestJobNodeData(AutoIngestJob job) {
|
||||
setProcessingStatus(job.getProcessingStatus());
|
||||
setPriority(job.getPriority());
|
||||
setNumberOfCrashes(numberOfCrashes); // RJCTODO
|
||||
setNumberOfCrashes(job.getNumberOfCrashes());
|
||||
setCompletedDate(job.getCompletedDate());
|
||||
setErrorsOccurred(job.getErrorsOccurred());
|
||||
this.version = CURRENT_VERSION;
|
||||
|
@ -343,6 +343,10 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
hostNamesToRunningJobs.remove(hostName);
|
||||
if (event.shouldRetry() == false) {
|
||||
synchronized (jobsLock) {
|
||||
AutoIngestJob job = event.getJob();
|
||||
if(completedJobs.contains(job)) {
|
||||
completedJobs.remove(job);
|
||||
}
|
||||
completedJobs.add(event.getJob());
|
||||
}
|
||||
}
|
||||
@ -652,9 +656,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
*/
|
||||
if (null != completedJob && !completedJob.getCaseDirectoryPath().toString().isEmpty()) {
|
||||
try {
|
||||
/**
|
||||
* We reset the status, completion date and processing stage
|
||||
* but we keep the original priority.
|
||||
*/
|
||||
completedJob.setErrorsOccurred(false);
|
||||
completedJob.setCompletedDate(new Date(0));
|
||||
completedJob.setPriority(DEFAULT_JOB_PRIORITY);
|
||||
completedJob.setProcessingStatus(PENDING);
|
||||
completedJob.setProcessingStage(AutoIngestJob.Stage.PENDING, Date.from(Instant.now()));
|
||||
updateCoordinationServiceNode(completedJob);
|
||||
pendingJobs.add(completedJob);
|
||||
} catch (CoordinationServiceException ex) {
|
||||
@ -849,7 +858,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
if (null != ingestJob) {
|
||||
IngestJob.DataSourceIngestModuleHandle moduleHandle = ingestJob.getSnapshot().runningDataSourceIngestModule();
|
||||
if (null != moduleHandle) {
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING_MODULE);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING_MODULE, Date.from(Instant.now()));
|
||||
moduleHandle.cancel();
|
||||
SYS_LOGGER.log(Level.INFO, "Cancelling {0} module for manifest {1}", new Object[]{moduleHandle.displayName(), currentJob.getManifest().getFilePath()});
|
||||
}
|
||||
@ -1224,7 +1233,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
|
||||
/*
|
||||
* Update the coordination service node for the job. If
|
||||
* this fails, leave the recovery to anoterh host.
|
||||
* this fails, leave the recovery to another host.
|
||||
*/
|
||||
try {
|
||||
updateCoordinationServiceNode(job);
|
||||
@ -1294,13 +1303,26 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
private void addCompletedJob(Manifest manifest, AutoIngestJobNodeData nodeData) throws CoordinationServiceException, InterruptedException {
|
||||
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
|
||||
if (null != caseDirectoryPath) {
|
||||
/**
|
||||
* We use the manifest rather than the nodeData here to create
|
||||
* a new AutoIngestJob instance because the AutoIngestJob
|
||||
* constructor that takes a nodeData expects the nodeData to
|
||||
* have fields that do not exist in earlier versions.
|
||||
*/
|
||||
AutoIngestJob job = new AutoIngestJob(manifest);
|
||||
/**
|
||||
* Update the job with the fields that exist in all versions
|
||||
* of the nodeData.
|
||||
*/
|
||||
job.setCompletedDate(nodeData.getCompletedDate());
|
||||
job.setErrorsOccurred(nodeData.getErrorsOccurred());
|
||||
job.setPriority(nodeData.getPriority());
|
||||
job.setNumberOfCrashes(nodeData.getNumberOfCrashes());
|
||||
job.setProcessingStage(AutoIngestJob.Stage.COMPLETED, nodeData.getCompletedDate());
|
||||
|
||||
job.setCaseDirectoryPath(caseDirectoryPath);
|
||||
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
|
||||
job.setProcessingStage(AutoIngestJob.Stage.COMPLETED);
|
||||
job.setCompletedDate(nodeData.getCompletedDate());
|
||||
job.setErrorsOccurred(true);
|
||||
newCompletedJobsList.add(new AutoIngestJob(nodeData));
|
||||
newCompletedJobsList.add(job);
|
||||
|
||||
/*
|
||||
* Try to upgrade/update the coordination service node data for
|
||||
@ -1868,7 +1890,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
Path manifestPath = currentJob.getManifest().getFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Started processing of {0}", manifestPath);
|
||||
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PROCESSING);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.STARTING);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.STARTING, Date.from(Instant.now()));
|
||||
currentJob.setProcessingHostName(AutoIngestManager.LOCAL_HOST_NAME);
|
||||
updateCoordinationServiceNode(currentJob);
|
||||
setChanged();
|
||||
@ -1990,7 +2012,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
if (AutoIngestUserPreferences.getSharedConfigEnabled()) {
|
||||
Path manifestPath = currentJob.getManifest().getFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Downloading shared configuration for {0}", manifestPath);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.UPDATING_SHARED_CONFIG);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.UPDATING_SHARED_CONFIG, Date.from(Instant.now()));
|
||||
new SharedConfiguration().downloadConfiguration();
|
||||
}
|
||||
}
|
||||
@ -2008,7 +2030,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
private void verifyRequiredSevicesAreRunning() throws ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException {
|
||||
Path manifestPath = currentJob.getManifest().getFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Checking services availability for {0}", manifestPath);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.CHECKING_SERVICES);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.CHECKING_SERVICES, Date.from(Instant.now()));
|
||||
if (!isServiceUp(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString())) {
|
||||
throw new DatabaseServerDownException("Case database server is down");
|
||||
}
|
||||
@ -2055,7 +2077,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
Manifest manifest = currentJob.getManifest();
|
||||
String caseName = manifest.getCaseName();
|
||||
SYS_LOGGER.log(Level.INFO, "Opening case {0} for {1}", new Object[]{caseName, manifest.getFilePath()});
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.OPENING_CASE);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.OPENING_CASE, Date.from(Instant.now()));
|
||||
/*
|
||||
* Acquire and hold a case name lock so that only one node at as
|
||||
* time can scan the output directory at a time. This prevents
|
||||
@ -2168,7 +2190,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
|
||||
DataSource dataSource = identifyDataSource(caseForJob);
|
||||
if (null == dataSource) {
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now()));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2178,7 +2200,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
|
||||
runDataSourceProcessor(caseForJob, dataSource);
|
||||
if (dataSource.getContent().isEmpty()) {
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now()));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2223,7 +2245,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
Manifest manifest = currentJob.getManifest();
|
||||
Path manifestPath = manifest.getFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.IDENTIFYING_DATA_SOURCE);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.IDENTIFYING_DATA_SOURCE, Date.from(Instant.now()));
|
||||
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
|
||||
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath);
|
||||
Path dataSourcePath = manifest.getDataSourcePath();
|
||||
@ -2259,7 +2281,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
Manifest manifest = currentJob.getManifest();
|
||||
Path manifestPath = manifest.getFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE, Date.from(Instant.now()));
|
||||
UUID taskId = UUID.randomUUID();
|
||||
DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId);
|
||||
DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor();
|
||||
@ -2424,7 +2446,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
Manifest manifest = currentJob.getManifest();
|
||||
Path manifestPath = manifest.getFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", manifestPath);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.ANALYZING_DATA_SOURCE);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.ANALYZING_DATA_SOURCE, Date.from(Instant.now()));
|
||||
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
|
||||
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath);
|
||||
IngestJobEventListener ingestJobEventListener = new IngestJobEventListener();
|
||||
@ -2460,7 +2482,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
}
|
||||
jobLogger.logAnalysisCompleted();
|
||||
} else {
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING, Date.from(Instant.now()));
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
jobLogger.logAnalysisCancelled();
|
||||
@ -2523,7 +2545,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
Manifest manifest = currentJob.getManifest();
|
||||
Path manifestPath = manifest.getFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Exporting files for {0}", manifestPath);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.EXPORTING_FILES);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.EXPORTING_FILES, Date.from(Instant.now()));
|
||||
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
|
||||
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath);
|
||||
try {
|
||||
|
@ -55,6 +55,8 @@ class AccountsText implements IndexedText {
|
||||
private static final Logger logger = Logger.getLogger(AccountsText.class.getName());
|
||||
private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT);
|
||||
|
||||
private static final String CCN_REGEX = "(%?)(B?)([0-9][ \\-]*?){12,19}(\\^?)";
|
||||
|
||||
private static final String HIGHLIGHT_PRE = "<span style='background:yellow'>"; //NON-NLS
|
||||
private static final String ANCHOR_NAME_PREFIX = AccountsText.class.getName() + "_";
|
||||
|
||||
@ -80,23 +82,24 @@ class AccountsText implements IndexedText {
|
||||
private int numberPagesForFile = 0;
|
||||
private Integer currentPage = 0;
|
||||
|
||||
/*
|
||||
/**
|
||||
* map from page/chunk to number of hits. value is 0 if not yet known.
|
||||
*/
|
||||
private final TreeMap<Integer, Integer> numberOfHitsPerPage = new TreeMap<>();
|
||||
/*
|
||||
|
||||
/**
|
||||
* set of pages, used for iterating back and forth. Only stores pages with
|
||||
* hits
|
||||
*/
|
||||
private final Set<Integer> pages = numberOfHitsPerPage.keySet();
|
||||
/*
|
||||
|
||||
/**
|
||||
* map from page/chunk number to current hit on that page.
|
||||
*/
|
||||
private final HashMap<Integer, Integer> currentHitPerPage = new HashMap<>();
|
||||
|
||||
AccountsText(long objectID, BlackboardArtifact artifact) {
|
||||
this(objectID, Arrays.asList(artifact));
|
||||
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
@ -201,11 +204,7 @@ class AccountsText implements IndexedText {
|
||||
|
||||
@Override
|
||||
public int currentItem() {
|
||||
if (this.currentHitPerPage.containsKey(currentPage)) {
|
||||
return currentHitPerPage.get(currentPage);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return currentHitPerPage.getOrDefault(currentPage, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -228,13 +227,9 @@ class AccountsText implements IndexedText {
|
||||
|
||||
//add both the canonical form and the form in the text as accountNumbers to highlight.
|
||||
BlackboardAttribute attribute = artifact.getAttribute(TSK_KEYWORD);
|
||||
if (attribute != null) {
|
||||
this.accountNumbers.add(attribute.getValueString());
|
||||
}
|
||||
attribute = artifact.getAttribute(TSK_CARD_NUMBER);
|
||||
if (attribute != null) {
|
||||
this.accountNumbers.add(attribute.getValueString());
|
||||
}
|
||||
|
||||
//if the chunk id is present just use that.
|
||||
Optional<Integer> chunkID =
|
||||
@ -249,6 +244,7 @@ class AccountsText implements IndexedText {
|
||||
} else {
|
||||
//otherwise we need to do a query to figure out the paging.
|
||||
needsQuery = true;
|
||||
// we can't break the for loop here because we need to accumulate all the accountNumbers
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,10 +261,11 @@ class AccountsText implements IndexedText {
|
||||
|
||||
isPageInfoLoaded = true;
|
||||
}
|
||||
private static final String CCN_REGEX = "(%?)(B?)([0-9][ \\-]*?){12,19}(\\^?)";
|
||||
|
||||
/**
|
||||
* Load the paging info from the QueryResults object.
|
||||
*
|
||||
* @param hits The QueryResults to load the paging info from.
|
||||
*/
|
||||
synchronized private void loadPageInfoFromHits(QueryResults hits) {
|
||||
//organize the hits by page, filter as needed
|
||||
@ -323,7 +320,7 @@ class AccountsText implements IndexedText {
|
||||
// extracted content (minus highlight tags) is HTML-escaped
|
||||
return "<html><pre>" + highlightedText + "</pre></html>"; //NON-NLS
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Error getting highlighted text for Solr doc id " + this.solrObjectId + ", chunkID " + this.currentPage , ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Error getting highlighted text for Solr doc id " + this.solrObjectId + ", chunkID " + this.currentPage, ex); //NON-NLS
|
||||
return Bundle.AccountsText_getMarkup_queryFailedMsg();
|
||||
}
|
||||
}
|
||||
@ -374,9 +371,6 @@ class AccountsText implements IndexedText {
|
||||
|
||||
@Override
|
||||
public int getNumberHits() {
|
||||
if (!this.numberOfHitsPerPage.containsKey(this.currentPage)) {
|
||||
return 0;
|
||||
}
|
||||
return this.numberOfHitsPerPage.get(this.currentPage);
|
||||
return numberOfHitsPerPage.getOrDefault(currentPage, 0);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,11 @@
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Range;
|
||||
import com.google.common.collect.RangeMap;
|
||||
import com.google.common.collect.TreeRangeMap;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit;
|
||||
|
||||
@ -42,6 +47,73 @@ final class CreditCardValidator {
|
||||
|
||||
private static final LuhnCheckDigit CREDIT_CARD_NUM_LUHN_CHECK = new LuhnCheckDigit();
|
||||
|
||||
/**
|
||||
* map from ccn IIN to allowed lengths
|
||||
*/
|
||||
static private final RangeMap<Integer, Set<Integer>> allowedLengths = TreeRangeMap.create();
|
||||
private static final ImmutableSet<Integer> Set12to19 = ImmutableSet.of(12, 13, 14, 15, 16, 17, 18, 19);
|
||||
private static final ImmutableSet<Integer> Set14to19 = ImmutableSet.of(14, 15, 16, 17, 18, 19);
|
||||
private static final ImmutableSet<Integer> Set16to19 = ImmutableSet.of(16, 17, 18, 29);
|
||||
|
||||
static {
|
||||
//amex
|
||||
allowedLengths.put(Range.closedOpen(34000000, 35000000), ImmutableSet.of(15));
|
||||
allowedLengths.put(Range.closedOpen(37000000, 38000000), ImmutableSet.of(15));
|
||||
|
||||
//visa
|
||||
allowedLengths.put(Range.closedOpen(40000000, 50000000), Set12to19);
|
||||
|
||||
//visa electron
|
||||
allowedLengths.put(Range.closedOpen(40260000, 40270000), ImmutableSet.of(16));
|
||||
allowedLengths.put(Range.closedOpen(41750000, 41750100), ImmutableSet.of(16));
|
||||
allowedLengths.put(Range.closedOpen(44050000, 44060000), ImmutableSet.of(16));
|
||||
allowedLengths.put(Range.closedOpen(45080000, 45090000), ImmutableSet.of(16));
|
||||
allowedLengths.put(Range.closedOpen(48440000, 48450000), ImmutableSet.of(16));
|
||||
allowedLengths.put(Range.closedOpen(49130000, 49140000), ImmutableSet.of(16));
|
||||
allowedLengths.put(Range.closedOpen(49170000, 49180000), ImmutableSet.of(16));
|
||||
|
||||
//China UnionPay
|
||||
allowedLengths.put(Range.closedOpen(62000000, 63000000), Set16to19);
|
||||
|
||||
//MasterCard
|
||||
allowedLengths.put(Range.closedOpen(51000000, 56000000), ImmutableSet.of(16));
|
||||
allowedLengths.put(Range.closedOpen(22210000, 27210000), ImmutableSet.of(16));
|
||||
|
||||
//Verve, these over lap with discover
|
||||
allowedLengths.put(Range.closedOpen(50609900, 50619900), ImmutableSet.of(16, 19));
|
||||
allowedLengths.put(Range.closedOpen(65000200, 65002700), ImmutableSet.of(16, 19));
|
||||
|
||||
//Maestro
|
||||
allowedLengths.put(Range.closedOpen(50000000, 50100000), Set12to19);
|
||||
allowedLengths.put(Range.closedOpen(56000000, 59000000), Set12to19);
|
||||
allowedLengths.put(Range.closedOpen(60000000, 70000000), Set12to19);
|
||||
allowedLengths.put(Range.closedOpen(63900000, 63910000), Set12to19);
|
||||
allowedLengths.put(Range.closedOpen(67000000, 68000000), Set12to19);
|
||||
|
||||
//Diners Club International (processed by discover
|
||||
allowedLengths.put(Range.closedOpen(30000000, 30600000), Set16to19);
|
||||
allowedLengths.put(Range.closedOpen(30950000, 30960000), Set16to19);
|
||||
allowedLengths.put(Range.closedOpen(36000000, 37000000), Set14to19);
|
||||
allowedLengths.put(Range.closedOpen(38000000, 40000000), Set16to19);
|
||||
|
||||
//Diners Club USA & Canada (MasterCard co brand)
|
||||
allowedLengths.put(Range.closedOpen(54000000, 56000000), Set14to19);
|
||||
|
||||
//Discover
|
||||
allowedLengths.put(Range.closedOpen(60110000, 60120000), Set16to19);
|
||||
allowedLengths.put(Range.closedOpen(62212600, 62292600), Set16to19);
|
||||
allowedLengths.put(Range.closedOpen(64400000, 66000000), Set16to19);
|
||||
|
||||
//JCB //process by discover
|
||||
allowedLengths.put(Range.closedOpen(35280000, 35900000), Set16to19);
|
||||
|
||||
//Dankort
|
||||
allowedLengths.put(Range.closedOpen(50190000, 50200000), Set16to19);
|
||||
|
||||
//InterPayment
|
||||
allowedLengths.put(Range.closedOpen(63600000, 63700000), Set16to19);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the given string represent a valid credit card number? It must have
|
||||
* no separators, or only '-', or only ' '. Checks digit grouping for
|
||||
@ -79,6 +151,10 @@ final class CreditCardValidator {
|
||||
splitCCN = new String[]{cannonicalCCN};
|
||||
}
|
||||
|
||||
if (false == lengthMatchesBin(cannonicalCCN)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate digit grouping for 15, 16, and 19 digit cards
|
||||
switch (cannonicalCCN.length()) {
|
||||
case 15:
|
||||
@ -105,6 +181,12 @@ final class CreditCardValidator {
|
||||
return CREDIT_CARD_NUM_LUHN_CHECK.isValid(cannonicalCCN);
|
||||
}
|
||||
|
||||
static private boolean lengthMatchesBin(String cannonicalCCN) {
|
||||
String BIN = cannonicalCCN.substring(0, 8);
|
||||
final Set<Integer> lengthsForBIN = allowedLengths.get(Integer.valueOf(BIN));
|
||||
return null == lengthsForBIN || lengthsForBIN.contains(cannonicalCCN.length());
|
||||
}
|
||||
|
||||
static private boolean isValidOtherDigitGrouping(String[] splitCCN) {
|
||||
if (splitCCN.length == 1) {
|
||||
return true;
|
||||
|
@ -87,6 +87,7 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
|
||||
private static final int MAX_RESULTS_PER_CURSOR_MARK = 512;
|
||||
private static final int MIN_EMAIL_ADDR_LENGTH = 8;
|
||||
private static final String SNIPPET_DELIMITER = String.valueOf(Character.toChars(171));
|
||||
|
||||
private final List<KeywordQueryFilter> filters = new ArrayList<>();
|
||||
private final KeywordList keywordList;
|
||||
@ -149,7 +150,7 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
final Server solrServer = KeywordSearch.getServer();
|
||||
SolrQuery solrQuery = new SolrQuery();
|
||||
|
||||
/**
|
||||
/*
|
||||
* The provided regular expression may include wildcards at the
|
||||
* beginning and/or end. These wildcards are used to indicate that the
|
||||
* user wants to find hits for the regex that are embedded within other
|
||||
@ -239,7 +240,6 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
int offset = 0;
|
||||
|
||||
while (hitMatcher.find(offset)) {
|
||||
StringBuilder snippet = new StringBuilder();
|
||||
|
||||
// If the location of the hit is beyond this chunk (i.e. it
|
||||
// exists in the overlap region), we skip the hit. It will
|
||||
@ -274,7 +274,7 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
}
|
||||
|
||||
if (artifactAttributeType == null) {
|
||||
addHit(content, snippet, hitMatcher, hit, hits, docId);
|
||||
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
|
||||
} else {
|
||||
switch (artifactAttributeType) {
|
||||
case TSK_EMAIL:
|
||||
@ -285,7 +285,7 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
*/
|
||||
if (hit.length() >= MIN_EMAIL_ADDR_LENGTH
|
||||
&& DomainValidator.getInstance(true).isValidTld(hit.substring(hit.lastIndexOf('.')))) {
|
||||
addHit(content, snippet, hitMatcher, hit, hits, docId);
|
||||
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
|
||||
}
|
||||
|
||||
break;
|
||||
@ -302,15 +302,15 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
if (ccnMatcher.find()) {
|
||||
final String group = ccnMatcher.group("ccn");
|
||||
if (CreditCardValidator.isValidCCN(group)) {
|
||||
addHit(content, snippet, hitMatcher, hit, hits, docId);
|
||||
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
addHit(content, snippet, hitMatcher, hit, hits, docId);
|
||||
|
||||
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -332,19 +332,28 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
return hits;
|
||||
}
|
||||
|
||||
private void addHit(String content, StringBuilder snippet, Matcher hitMatcher, String hit, List<KeywordHit> hits, final String docId) throws TskCoreException {
|
||||
/**
|
||||
* Get the snippet from the document if keyword search is configured to
|
||||
* use snippets.
|
||||
* Make a snippet from the given content that has the given hit plus some
|
||||
* surrounding context.
|
||||
*
|
||||
* @param content The content to extract the snippet from.
|
||||
*
|
||||
* @param hitMatcher The Matcher that has the start/end info for where the
|
||||
* hit is in the content.
|
||||
* @param hit The actual hit in the content.
|
||||
*
|
||||
* @return A snippet extracted from content that contains hit plus some
|
||||
* surrounding context.
|
||||
*/
|
||||
private String makeSnippet(String content, Matcher hitMatcher, String hit) {
|
||||
// Get the snippet from the document.
|
||||
int maxIndex = content.length() - 1;
|
||||
snippet.append(content.substring(Integer.max(0, hitMatcher.start() - 20), Integer.max(0, hitMatcher.start())));
|
||||
snippet.appendCodePoint(171);
|
||||
snippet.append(hit);
|
||||
snippet.appendCodePoint(171);
|
||||
snippet.append(content.substring(Integer.min(maxIndex, hitMatcher.end()), Integer.min(maxIndex, hitMatcher.end() + 20)));
|
||||
final int end = hitMatcher.end();
|
||||
final int start = hitMatcher.start();
|
||||
|
||||
hits.add(new KeywordHit(docId, snippet.toString(), hit));
|
||||
return content.substring(Integer.max(0, start - 20), Integer.max(0, start))
|
||||
+ SNIPPET_DELIMITER + hit + SNIPPET_DELIMITER
|
||||
+ content.substring(Integer.min(maxIndex, end), Integer.min(maxIndex, end + 20));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -559,7 +568,7 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
*/
|
||||
static private void addAttributeIfNotAlreadyCaptured(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMap, ATTRIBUTE_TYPE attrType, String groupName, Matcher matcher) {
|
||||
BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType);
|
||||
attributeMap.computeIfAbsent(type, (BlackboardAttribute.Type t) -> {
|
||||
attributeMap.computeIfAbsent(type, t -> {
|
||||
String value = matcher.group(groupName);
|
||||
if (attrType.equals(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)) {
|
||||
attributeMap.put(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD),
|
||||
@ -568,8 +577,9 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
}
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
return new BlackboardAttribute(attrType, MODULE_NAME, value);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,50 @@ public class CreditCardValidatorTest {
|
||||
public void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLengthMatchesBin() {
|
||||
System.out.println("lengthMatchesBin");
|
||||
|
||||
//amex must be 15
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("3431 136294 58529"));
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("3431-136294-5850")); //too short
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("34311362945850"));// too short
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("3431 1362 9458 5034")); //too long
|
||||
|
||||
//verve 16 or 19
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("506099002418342")); // 15 too short
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("5060990024183426")); //16
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("50609900241834267")); // 17
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("506099002418342675")); //18
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("5060990024183426759")); //19
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("50609900241834267591")); //20
|
||||
|
||||
//visa (theoretically 12-19 digits)
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4000 0000 000")); //11 visa
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("4000 0000 0002")); //12 visa
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("4000 0000 0002 2")); //13 visa
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("4000 0000 0002 26")); //14 visa
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4000 0000 0002 267")); //15 visa
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("4000 000000 02267")); //15 visa //is this right to enforce grouping?
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("4000 0000 0002 2675")); //16 visa
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("4000 0000 0002 2675 9")); //17 visa
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("4000 0000 0002 2675 91")); //18 visa
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("4000 0000 0002 2675 918")); //19 visa
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4000 0000 0002 2675 9183")); //20 visa
|
||||
|
||||
//vs visa electron (only 16 digits (?))
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4026 1200 006")); //11 visa electron
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4026 0000 0065")); //12 visa electron
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4026 0000 0065 9")); //13 visa electron
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4026 0000 0065 91")); //14 visa electron
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4026 0000 0065 918")); //15 visa electron
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("4026 0000 0065 9187")); //16 visa electron
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4026 0000 0065 9187 0")); //17 visa electron
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4026 0000 0065 9183 00")); //18 visa electron
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4026 0000 0065 9183 000")); //19 visa electron
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("4026 0000 0065 9183 0000")); //20 visa electron
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of isValidCCN method, of class CreditCardValidator.
|
||||
*/
|
||||
@ -114,8 +158,7 @@ public class CreditCardValidatorTest {
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("623974 7947839518659"));
|
||||
assertEquals(true, CreditCardValidator.isValidCCN("623974-7947839518659"));
|
||||
/*
|
||||
* China UnionPay may not use luhn ???
|
||||
*
|
||||
* China UnionPay may not use luhn ??? *
|
||||
* https://stackoverflow.com/questions/7863058/does-the-luhn-algorithm-work-for-all-mainstream-credit-cards-discover-visa-m
|
||||
*/
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("6239747947839518658")); //luhn
|
||||
@ -187,4 +230,5 @@ public class CreditCardValidatorTest {
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("123 456789031")); //grouping
|
||||
assertEquals(false, CreditCardValidator.isValidCCN("1234-56789 031")); //separators
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ The \ref content_viewer_page panel is where previous instances of properties are
|
||||
|
||||
If at least one other case or data source has been ingested with this module enabled, there is a potential that data will be displayed in the Other Occurrences content viewer. Note that the Correlation Engine Ingest Module does not have to have been run on the current data source to see correlated files from other cases/data sources. If the selected file or artifact is associated by one of the supported Correlation Types, to one or more file(s) or artifact(s) in the database, the associated files/artifacts will be displayed. Note: the Content Viewer will display ALL associated files and artifacts available in the database. It ignores the user's enabled/disabled Correlation Properties.
|
||||
|
||||
By default, the rows in the content viewer will have background colors to indicate if they are known to be of interest. Files/artifacts that are notable will have a Red background, unknown will have Yellow background, and known will have a White background.
|
||||
By default, the rows in the content viewer will have background colors to indicate if they are known to be of interest. Files/artifacts that are notable will have a Red background, all others will have a White background.
|
||||
|
||||
\image html central_repo_content_viewer.png
|
||||
|
||||
@ -149,7 +149,7 @@ This menu has several options.
|
||||
-# Select All
|
||||
-# Export Selected Rows to CSV
|
||||
-# Show Case Details
|
||||
-# Show Commonality Details
|
||||
-# Show Frequency
|
||||
|
||||
<b>Select All</b>
|
||||
|
||||
@ -177,9 +177,9 @@ details will include:
|
||||
These details would have been entered by the examiner of the selected case, by visiting
|
||||
the Case -> Central Repository Case Properties menu, when that case was open.
|
||||
|
||||
<b>Show Commonality Details</b>
|
||||
<b>Show Frequency</b>
|
||||
|
||||
The concept of Commonality simply means, how common is the selected file. The value is the percentage of case/data source tuples that have the selected file or artifact.
|
||||
This shows how common the selected file is. The value is the percentage of case/data source tuples that have the selected file or artifact.
|
||||
|
||||
\subsection cr_interesting_items Interesting Items
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Loading…
x
Reference in New Issue
Block a user