mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
merged with upstream and resolved conflicts.
This commit is contained in:
commit
f6d916f3ea
1
.gitignore
vendored
1
.gitignore
vendored
@ -76,4 +76,5 @@ hs_err_pid*.log
|
||||
/ImageGallery/release/
|
||||
/thunderbirdparser/release/
|
||||
/RecentActivity/release/
|
||||
/CentralRepository/release/
|
||||
|
||||
|
@ -24,6 +24,7 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Renderer for cells in data content viewer table
|
||||
@ -49,19 +50,15 @@ public class DataContentViewerOtherCasesTableCellRenderer implements TableCellRe
|
||||
background = Color.BLUE;
|
||||
} else {
|
||||
String known_status = (String) table.getModel().getValueAt(row, 5);
|
||||
switch (known_status) {
|
||||
case "Bad":
|
||||
if (known_status.equals(TskData.FileKnown.BAD.getName())) {
|
||||
foreground = Color.WHITE;
|
||||
background = Color.RED;
|
||||
break;
|
||||
case "Unknown":
|
||||
} else if (known_status.equals(TskData.FileKnown.UNKNOWN.getName())) {
|
||||
foreground = Color.BLACK;
|
||||
background = Color.YELLOW;
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
foreground = Color.BLACK;
|
||||
background = Color.WHITE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
renderer.setForeground(foreground);
|
||||
|
@ -48,7 +48,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
DEVICE(Bundle.DataContentViewerOtherCasesTableModel_device(), 145),
|
||||
TYPE(Bundle.DataContentViewerOtherCasesTableModel_type(), 40),
|
||||
VALUE(Bundle.DataContentViewerOtherCasesTableModel_value(), 145),
|
||||
KNOWN(Bundle.DataContentViewerOtherCasesTableModel_known(), 25),
|
||||
KNOWN(Bundle.DataContentViewerOtherCasesTableModel_known(), 45),
|
||||
SCOPE(Bundle.DataContentViewerOtherCasesTableModel_scope(), 20),
|
||||
COMMENT(Bundle.DataContentViewerOtherCasesTableModel_comment(), 200),
|
||||
FILE_PATH(Bundle.DataContentViewerOtherCasesTableModel_path(), 250);
|
||||
@ -160,7 +160,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
value = eamArtifactInstance.getGlobalStatus().toString();
|
||||
break;
|
||||
case KNOWN:
|
||||
value = eamArtifactInstance.getKnownStatus().toString();
|
||||
value = eamArtifactInstance.getKnownStatus().getName();
|
||||
break;
|
||||
case COMMENT:
|
||||
value = eamArtifactInstance.getComment();
|
||||
|
@ -32,9 +32,9 @@ import java.sql.Types;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -100,7 +100,6 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
// }
|
||||
// // else, schema is current
|
||||
// }
|
||||
|
||||
/**
|
||||
* Setup and create a connection to the selected database implementation
|
||||
*/
|
||||
@ -550,8 +549,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves eamArtifact instances from the database that are associated with
|
||||
* the eamArtifactType and eamArtifactValue of the given eamArtifact.
|
||||
* Retrieves eamArtifact instances from the database that are associated
|
||||
* with the eamArtifactType and eamArtifactValue of the given eamArtifact.
|
||||
*
|
||||
* @param eamArtifact The type/value to look up (artifact with 0 instances)
|
||||
*
|
||||
@ -599,8 +598,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves eamArtifact instances from the database that are associated with
|
||||
* the aType and filePath
|
||||
* Retrieves eamArtifact instances from the database that are associated
|
||||
* with the aType and filePath
|
||||
*
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param filePath File path to search for
|
||||
@ -655,7 +654,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* associated with the ArtifactType and artifactValue of the given artifact.
|
||||
*
|
||||
* @param eamArtifact Artifact with artifactType and artifactValue to search
|
||||
* for
|
||||
* for
|
||||
*
|
||||
* @return Number of artifact instances having ArtifactType and
|
||||
* ArtifactValue.
|
||||
@ -698,7 +697,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* case_id/datasource_id tuples in the database) expressed as a percentage.
|
||||
*
|
||||
* @param eamArtifact Artifact with artifactType and artifactValue to search
|
||||
* for
|
||||
* for
|
||||
*
|
||||
* @return Int between 0 and 100
|
||||
*/
|
||||
@ -716,7 +715,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* the given artifact.
|
||||
*
|
||||
* @param eamArtifact Artifact with artifactType and artifactValue to search
|
||||
* for
|
||||
* for
|
||||
*
|
||||
* @return Number of unique tuples
|
||||
*/
|
||||
@ -806,7 +805,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* @param eamInstance Instance with caseName and dataSource to search for
|
||||
*
|
||||
* @param eamInstance Instance with caseDisplayName and dataSource to search
|
||||
* for
|
||||
* for
|
||||
*
|
||||
* @return Number of artifact instances having caseDisplayName and
|
||||
* dataSource
|
||||
@ -874,6 +873,13 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the conflict clause for bulk update statements
|
||||
*
|
||||
* @return The conflict clause for bulk update statements
|
||||
*/
|
||||
protected abstract String getConflictClause();
|
||||
|
||||
/**
|
||||
* Executes a bulk insert of the eamArtifacts added from the
|
||||
* prepareBulkArtifact() method
|
||||
@ -899,7 +905,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
sql.append(tableName);
|
||||
sql.append(" (case_id, data_source_id, value, file_path, known_status, comment) ");
|
||||
sql.append("VALUES ((SELECT id FROM cases WHERE case_uid=? LIMIT 1), ");
|
||||
sql.append("(SELECT id FROM data_sources WHERE device_id=? LIMIT 1), ?, ?, ?, ?)");
|
||||
sql.append("(SELECT id FROM data_sources WHERE device_id=? LIMIT 1), ?, ?, ?, ?) ");
|
||||
sql.append(getConflictClause());
|
||||
|
||||
bulkPs = conn.prepareStatement(sql.toString());
|
||||
|
||||
@ -949,7 +956,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
try {
|
||||
String sql = "INSERT INTO cases(case_uid, org_id, case_name, creation_date, case_number, "
|
||||
+ "examiner_name, examiner_email, examiner_phone, notes) "
|
||||
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) "
|
||||
+ getConflictClause();
|
||||
bulkPs = conn.prepareStatement(sql);
|
||||
|
||||
for (EamCase eamCase : cases) {
|
||||
@ -987,8 +995,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an eamArtifact instance as knownStatus = "Bad". If eamArtifact exists,
|
||||
* it is updated. If eamArtifact does not exist nothing happens
|
||||
* Sets an eamArtifact instance as knownStatus = "Bad". If eamArtifact
|
||||
* exists, it is updated. If eamArtifact does not exist nothing happens
|
||||
*
|
||||
* @param eamArtifact Artifact containing exactly one (1) ArtifactInstance.
|
||||
*/
|
||||
@ -1034,13 +1042,13 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
int instance_id = resultSet.getInt("id");
|
||||
preparedUpdate = conn.prepareStatement(sqlUpdate.toString());
|
||||
|
||||
preparedUpdate.setString(1, EamArtifactInstance.KnownStatus.BAD.name());
|
||||
preparedUpdate.setString(1, TskData.FileKnown.BAD.name());
|
||||
preparedUpdate.setString(2, eamInstance.getComment());
|
||||
preparedUpdate.setInt(3, instance_id);
|
||||
|
||||
preparedUpdate.executeUpdate();
|
||||
} else {
|
||||
eamArtifact.getInstances().get(0).setKnownStatus(EamArtifactInstance.KnownStatus.BAD);
|
||||
eamArtifact.getInstances().get(0).setKnownStatus(TskData.FileKnown.BAD);
|
||||
addArtifact(eamArtifact);
|
||||
}
|
||||
|
||||
@ -1055,7 +1063,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets list of matching eamArtifact instances that have knownStatus = "Bad".
|
||||
* Gets list of matching eamArtifact instances that have knownStatus =
|
||||
* "Bad".
|
||||
*
|
||||
* @param eamArtifact Artifact containing Type and Value
|
||||
*
|
||||
@ -1086,7 +1095,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
try {
|
||||
preparedStatement = conn.prepareStatement(sql.toString());
|
||||
preparedStatement.setString(1, eamArtifact.getArtifactValue());
|
||||
preparedStatement.setString(2, EamArtifactInstance.KnownStatus.BAD.name());
|
||||
preparedStatement.setString(2, TskData.FileKnown.BAD.name());
|
||||
resultSet = preparedStatement.executeQuery();
|
||||
while (resultSet.next()) {
|
||||
artifactInstance = getEamArtifactInstanceFromResultSet(resultSet);
|
||||
@ -1127,7 +1136,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
try {
|
||||
preparedStatement = conn.prepareStatement(sql.toString());
|
||||
preparedStatement.setString(1, eamArtifact.getArtifactValue());
|
||||
preparedStatement.setString(2, EamArtifactInstance.KnownStatus.BAD.name());
|
||||
preparedStatement.setString(2, TskData.FileKnown.BAD.name());
|
||||
resultSet = preparedStatement.executeQuery();
|
||||
resultSet.next();
|
||||
badInstances = resultSet.getLong(1);
|
||||
@ -1177,7 +1186,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
try {
|
||||
preparedStatement = conn.prepareStatement(sql.toString());
|
||||
preparedStatement.setString(1, eamArtifact.getArtifactValue());
|
||||
preparedStatement.setString(2, EamArtifactInstance.KnownStatus.BAD.name());
|
||||
preparedStatement.setString(2, TskData.FileKnown.BAD.name());
|
||||
resultSet = preparedStatement.executeQuery();
|
||||
while (resultSet.next()) {
|
||||
caseNames.add(resultSet.getString("case_name"));
|
||||
@ -1218,7 +1227,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
try {
|
||||
preparedStatement = conn.prepareStatement(sql);
|
||||
preparedStatement.setString(1, eamArtifact.getArtifactValue());
|
||||
preparedStatement.setString(2, EamArtifactInstance.KnownStatus.BAD.name());
|
||||
preparedStatement.setString(2, TskData.FileKnown.BAD.name());
|
||||
resultSet = preparedStatement.executeQuery();
|
||||
resultSet.next();
|
||||
badInstances = resultSet.getLong(1);
|
||||
@ -1442,9 +1451,10 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
|
||||
/**
|
||||
* Add a new global file instance to the bulk collection
|
||||
*
|
||||
*
|
||||
* @param eamGlobalFileInstance The global file instance to add
|
||||
* @throws EamDbException
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@Override
|
||||
public void prepareGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException {
|
||||
@ -1460,8 +1470,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
|
||||
/**
|
||||
* Insert the bulk collection of Global File Instances
|
||||
*
|
||||
* @throws EamDbException
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@Override
|
||||
public void bulkInsertGlobalFileInstances() throws EamDbException {
|
||||
@ -1476,7 +1486,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
PreparedStatement bulkPs = null;
|
||||
try {
|
||||
for (EamArtifact.Type type : artifactTypes) {
|
||||
String sql = "INSERT INTO global_files(global_reference_set_id, value, known_status, comment) VALUES (?, ?, ?, ?)";
|
||||
String sql = "INSERT INTO global_files(global_reference_set_id, value, known_status, comment) VALUES (?, ?, ?, ?) "
|
||||
+ getConflictClause();
|
||||
|
||||
bulkPs = conn.prepareStatement(sql);
|
||||
|
||||
@ -1507,10 +1518,12 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
|
||||
/**
|
||||
* Get all global file instances having a given MD5 hash
|
||||
*
|
||||
*
|
||||
* @param MD5Hash The hash to lookup
|
||||
*
|
||||
* @return List of all global file instances with a given hash
|
||||
* @throws EamDbException
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@Override
|
||||
public List<EamGlobalFileInstance> getGlobalFileInstancesByHash(String MD5Hash) throws EamDbException {
|
||||
@ -1543,7 +1556,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* Add a new EamArtifact.Type to the db.
|
||||
*
|
||||
* @param newType New type to add.
|
||||
* @throws EamDbException
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@Override
|
||||
public void newCorrelationArtifactType(EamArtifact.Type newType) throws EamDbException {
|
||||
@ -1575,7 +1589,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
*
|
||||
* @return List of EamArtifact.Type's. If none are defined in the database,
|
||||
* the default list will be returned.
|
||||
* @throws EamDbException
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@Override
|
||||
public List<EamArtifact.Type> getCorrelationArtifactTypes() throws EamDbException {
|
||||
@ -1609,7 +1624,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
*
|
||||
* @return List of enabled EamArtifact.Type's. If none are defined in the
|
||||
* database, the default list will be returned.
|
||||
* @throws EamDbException
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@Override
|
||||
public List<EamArtifact.Type> getEnabledCorrelationArtifactTypes() throws EamDbException {
|
||||
@ -1643,7 +1659,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
*
|
||||
* @return List of supported EamArtifact.Type's. If none are defined in the
|
||||
* database, the default list will be returned.
|
||||
* @throws EamDbException
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@Override
|
||||
public List<EamArtifact.Type> getSupportedCorrelationArtifactTypes() throws EamDbException {
|
||||
@ -1675,7 +1692,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* Update a EamArtifact.Type.
|
||||
*
|
||||
* @param aType EamArtifact.Type to update.
|
||||
* @throws EamDbException
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@Override
|
||||
public void updateCorrelationArtifactType(EamArtifact.Type aType) throws EamDbException {
|
||||
@ -1707,7 +1725,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
* @param typeName Name of Type to get
|
||||
*
|
||||
* @return EamArtifact.Type or null if it doesn't exist.
|
||||
* @throws EamDbException
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@Override
|
||||
public EamArtifact.Type getCorrelationArtifactTypeByName(String typeName) throws EamDbException {
|
||||
@ -1824,7 +1843,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
new EamDataSource(resultSet.getString("device_id"), resultSet.getString("name")),
|
||||
resultSet.getString("file_path"),
|
||||
resultSet.getString("comment"),
|
||||
EamArtifactInstance.KnownStatus.valueOf(resultSet.getString("known_status")),
|
||||
TskData.FileKnown.valueOf(resultSet.getString("known_status")),
|
||||
EamArtifactInstance.GlobalStatus.LOCAL
|
||||
);
|
||||
|
||||
@ -1872,7 +1891,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
resultSet.getInt("id"),
|
||||
resultSet.getInt("global_reference_set_id"),
|
||||
resultSet.getString("value"),
|
||||
EamArtifactInstance.KnownStatus.valueOf(resultSet.getString("known_status")),
|
||||
TskData.FileKnown.valueOf(resultSet.getString("known_status")),
|
||||
resultSet.getString("comment")
|
||||
);
|
||||
|
||||
|
@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -49,22 +50,22 @@ public class EamArtifactInstance implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum KnownStatus {
|
||||
UNKNOWN(Bundle.EamArtifactInstances_knownStatus_unknown()),
|
||||
KNOWN(Bundle.EamArtifactInstances_knownStatus_known()),
|
||||
BAD(Bundle.EamArtifactInstances_knownStatus_bad());
|
||||
|
||||
private final String knownStatus;
|
||||
|
||||
private KnownStatus(String knownStatus) {
|
||||
this.knownStatus = knownStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return knownStatus;
|
||||
}
|
||||
}
|
||||
// public enum FileKnown {
|
||||
// UNKNOWN(Bundle.EamArtifactInstances_knownStatus_unknown()),
|
||||
// KNOWN(Bundle.EamArtifactInstances_knownStatus_known()),
|
||||
// BAD(Bundle.EamArtifactInstances_knownStatus_bad());
|
||||
//
|
||||
// private final String knownStatus;
|
||||
//
|
||||
// private FileKnown(String knownStatus) {
|
||||
// this.knownStatus = knownStatus;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String toString() {
|
||||
// return knownStatus;
|
||||
// }
|
||||
// }
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ -73,14 +74,14 @@ public class EamArtifactInstance implements Serializable {
|
||||
private EamDataSource eamDataSource;
|
||||
private String filePath;
|
||||
private String comment;
|
||||
private KnownStatus knownStatus;
|
||||
private TskData.FileKnown knownStatus;
|
||||
private GlobalStatus globalStatus;
|
||||
|
||||
public EamArtifactInstance(
|
||||
EamCase eamCase,
|
||||
EamDataSource eamDataSource
|
||||
) {
|
||||
this("", eamCase, eamDataSource, "", "", KnownStatus.UNKNOWN, GlobalStatus.LOCAL);
|
||||
this("", eamCase, eamDataSource, "", "", TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
}
|
||||
|
||||
public EamArtifactInstance(
|
||||
@ -88,7 +89,7 @@ public class EamArtifactInstance implements Serializable {
|
||||
EamDataSource eamDataSource,
|
||||
String filePath
|
||||
) {
|
||||
this("", eamCase, eamDataSource, filePath, "", KnownStatus.UNKNOWN, GlobalStatus.LOCAL);
|
||||
this("", eamCase, eamDataSource, filePath, "", TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
}
|
||||
|
||||
public EamArtifactInstance(
|
||||
@ -97,7 +98,7 @@ public class EamArtifactInstance implements Serializable {
|
||||
String filePath,
|
||||
String comment
|
||||
) {
|
||||
this("", eamCase, eamDataSource, filePath, comment, KnownStatus.UNKNOWN, GlobalStatus.LOCAL);
|
||||
this("", eamCase, eamDataSource, filePath, comment, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
}
|
||||
|
||||
public EamArtifactInstance(
|
||||
@ -105,7 +106,7 @@ public class EamArtifactInstance implements Serializable {
|
||||
EamDataSource eamDataSource,
|
||||
String filePath,
|
||||
String comment,
|
||||
KnownStatus knownStatus,
|
||||
TskData.FileKnown knownStatus,
|
||||
GlobalStatus globalStatus
|
||||
) {
|
||||
this("", eamCase, eamDataSource, filePath, comment, knownStatus, globalStatus);
|
||||
@ -117,7 +118,7 @@ public class EamArtifactInstance implements Serializable {
|
||||
EamDataSource eamDataSource,
|
||||
String filePath,
|
||||
String comment,
|
||||
KnownStatus knownStatus,
|
||||
TskData.FileKnown knownStatus,
|
||||
GlobalStatus globalStatus
|
||||
) {
|
||||
this.ID = ID;
|
||||
@ -223,14 +224,14 @@ public class EamArtifactInstance implements Serializable {
|
||||
/**
|
||||
* @return the knownStatus
|
||||
*/
|
||||
public KnownStatus getKnownStatus() {
|
||||
public TskData.FileKnown getKnownStatus() {
|
||||
return knownStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param knownStatus the knownStatus to set
|
||||
*/
|
||||
public void setKnownStatus(KnownStatus knownStatus) {
|
||||
public void setKnownStatus(TskData.FileKnown knownStatus) {
|
||||
this.knownStatus = knownStatus;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
|
||||
/**
|
||||
@ -88,7 +89,7 @@ public class EamArtifactUtil {
|
||||
new EamDataSource(deviceId, af.getDataSource().getName()),
|
||||
af.getParentPath() + af.getName(),
|
||||
"",
|
||||
EamArtifactInstance.KnownStatus.UNKNOWN,
|
||||
TskData.FileKnown.UNKNOWN,
|
||||
EamArtifactInstance.GlobalStatus.LOCAL
|
||||
);
|
||||
eamArtifact.addInstance(eamInstance);
|
||||
|
@ -18,7 +18,8 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance.KnownStatus;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
|
||||
/**
|
||||
* Global file hash instance
|
||||
@ -28,14 +29,14 @@ public class EamGlobalFileInstance {
|
||||
private int instanceID;
|
||||
private int globalSetID;
|
||||
private String MD5Hash;
|
||||
private KnownStatus knownStatus;
|
||||
private TskData.FileKnown knownStatus;
|
||||
private String comment;
|
||||
|
||||
public EamGlobalFileInstance(
|
||||
int instanceID,
|
||||
int globalSetID,
|
||||
String MD5Hash,
|
||||
KnownStatus knownStatus,
|
||||
TskData.FileKnown knownStatus,
|
||||
String comment) {
|
||||
this.instanceID = instanceID;
|
||||
this.globalSetID = globalSetID;
|
||||
@ -47,7 +48,7 @@ public class EamGlobalFileInstance {
|
||||
public EamGlobalFileInstance(
|
||||
int globalSetID,
|
||||
String MD5Hash,
|
||||
KnownStatus knownStatus,
|
||||
TskData.FileKnown knownStatus,
|
||||
String comment) {
|
||||
this(-1, globalSetID, MD5Hash, knownStatus, comment);
|
||||
}
|
||||
@ -97,14 +98,14 @@ public class EamGlobalFileInstance {
|
||||
/**
|
||||
* @return the knownStatus
|
||||
*/
|
||||
public KnownStatus getKnownStatus() {
|
||||
public TskData.FileKnown getKnownStatus() {
|
||||
return knownStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param knownStatus the knownStatus to set
|
||||
*/
|
||||
public void setKnownStatus(KnownStatus knownStatus) {
|
||||
public void setKnownStatus(TskData.FileKnown knownStatus) {
|
||||
this.knownStatus = knownStatus;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,8 @@ public class PostgresEamDb extends AbstractSqlEamDb {
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(PostgresEamDb.class.getName());
|
||||
|
||||
private final static String CONFLICT_CLAUSE = "ON CONFLICT DO NOTHING";
|
||||
|
||||
private static PostgresEamDb instance;
|
||||
|
||||
private static final int CONN_POOL_SIZE = 10;
|
||||
@ -162,6 +164,11 @@ public class PostgresEamDb extends AbstractSqlEamDb {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getConflictClause() {
|
||||
return CONFLICT_CLAUSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getBadTags() {
|
||||
return dbSettings.getBadTags();
|
||||
|
@ -36,8 +36,7 @@ import org.sleuthkit.autopsy.coreutils.TextConverter;
|
||||
import org.sleuthkit.autopsy.coreutils.TextConverterException;
|
||||
|
||||
/**
|
||||
* Settings for the Postgres implementation of the Central Repository
|
||||
* database
|
||||
* Settings for the Postgres implementation of the Central Repository database
|
||||
*/
|
||||
public final class PostgresEamDbSettings {
|
||||
|
||||
@ -148,8 +147,8 @@ public final class PostgresEamDbSettings {
|
||||
* Get the full connection URL as a String
|
||||
*
|
||||
* @param usePostgresDb Connect to the 'postgres' database when testing
|
||||
* connectivity and creating the main database.
|
||||
*
|
||||
* connectivity and creating the main database.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getConnectionURL(boolean usePostgresDb) {
|
||||
@ -167,8 +166,9 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the current settings to get an ephemeral client connection for testing.
|
||||
*
|
||||
* Use the current settings to get an ephemeral client connection for
|
||||
* testing.
|
||||
*
|
||||
* @return Connection or null.
|
||||
*/
|
||||
private Connection getEphemeralConnection(boolean usePostgresDb) {
|
||||
@ -191,9 +191,9 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the current settings and the validation query
|
||||
* to test the connection to the database.
|
||||
*
|
||||
* Use the current settings and the validation query to test the connection
|
||||
* to the database.
|
||||
*
|
||||
* @return true if successfull connection, else false.
|
||||
*/
|
||||
public boolean verifyConnection() {
|
||||
@ -201,7 +201,7 @@ public final class PostgresEamDbSettings {
|
||||
if (null == conn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
boolean result = EamDbUtil.executeValidationQuery(conn, VALIDATION_QUERY);
|
||||
EamDbUtil.closeConnection(conn);
|
||||
return result;
|
||||
@ -209,7 +209,7 @@ public final class PostgresEamDbSettings {
|
||||
|
||||
/**
|
||||
* Check to see if the database exists.
|
||||
*
|
||||
*
|
||||
* @return true if exists, else false
|
||||
*/
|
||||
public boolean verifyDatabaseExists() {
|
||||
@ -238,11 +238,11 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use the current settings and the schema version query
|
||||
* to test the database schema.
|
||||
*
|
||||
* Use the current settings and the schema version query to test the
|
||||
* database schema.
|
||||
*
|
||||
* @return true if successfull connection, else false.
|
||||
*/
|
||||
public boolean verifyDatabaseSchema() {
|
||||
@ -275,8 +275,9 @@ public final class PostgresEamDbSettings {
|
||||
EamDbUtil.closeConnection(conn);
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the database schema.
|
||||
*
|
||||
@ -305,7 +306,6 @@ public final class PostgresEamDbSettings {
|
||||
|
||||
// NOTE: The organizations will only have a small number of rows, so
|
||||
// an index is probably not worthwhile.
|
||||
|
||||
StringBuilder createCasesTable = new StringBuilder();
|
||||
createCasesTable.append("CREATE TABLE IF NOT EXISTS cases (");
|
||||
createCasesTable.append("id SERIAL PRIMARY KEY,");
|
||||
@ -402,7 +402,6 @@ public final class PostgresEamDbSettings {
|
||||
|
||||
// NOTE: the db_info table currenly only has 1 row, so having an index
|
||||
// provides no benefit.
|
||||
|
||||
Connection conn = null;
|
||||
try {
|
||||
conn = getEphemeralConnection(false);
|
||||
@ -514,9 +513,9 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* To prevent issues where one command can honor case and another cannot,
|
||||
* we will force the dbname to lower case.
|
||||
*
|
||||
* To prevent issues where one command can honor case and another cannot, we
|
||||
* will force the dbname to lower case.
|
||||
*
|
||||
* @return the dbName
|
||||
*/
|
||||
public String getDbName() {
|
||||
|
@ -25,7 +25,6 @@ import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.dbcp2.BasicDataSource;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
@ -162,6 +161,12 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getConflictClause() {
|
||||
// For sqlite, our conflict clause is part of the table schema
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getBadTags() {
|
||||
return dbSettings.getBadTags();
|
||||
|
@ -256,8 +256,8 @@ public final class SqliteEamDbSettings {
|
||||
createCasesTable.append("examiner_email text NOT NULL,");
|
||||
createCasesTable.append("examiner_phone text NOT NULL,");
|
||||
createCasesTable.append("notes text NOT NULL,");
|
||||
createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null,");
|
||||
createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE(case_uid)");
|
||||
createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE(case_uid) ON CONFLICT IGNORE,");
|
||||
createCasesTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createCasesTable.append(")");
|
||||
|
||||
// NOTE: when there are few cases in the cases table, these indices may not be worthwhile
|
||||
@ -281,7 +281,7 @@ public final class SqliteEamDbSettings {
|
||||
createGlobalReferenceSetsTable.append("set_name text NOT NULL,");
|
||||
createGlobalReferenceSetsTable.append("version text NOT NULL,");
|
||||
createGlobalReferenceSetsTable.append("import_date text NOT NULL,");
|
||||
createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null");
|
||||
createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createGlobalReferenceSetsTable.append(")");
|
||||
|
||||
String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)";
|
||||
@ -293,8 +293,8 @@ public final class SqliteEamDbSettings {
|
||||
createGlobalFilesTable.append("value text NOT NULL,");
|
||||
createGlobalFilesTable.append("known_status text NOT NULL,");
|
||||
createGlobalFilesTable.append("comment text NOT NULL,");
|
||||
createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE(global_reference_set_id, value)");
|
||||
createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null");
|
||||
createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE(global_reference_set_id, value) ON CONFLICT IGNORE,");
|
||||
createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createGlobalFilesTable.append(")");
|
||||
|
||||
String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)";
|
||||
|
@ -48,8 +48,8 @@ import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
|
||||
/**
|
||||
* Listen for case events and update entries in the Central Repository
|
||||
* database accordingly
|
||||
* Listen for case events and update entries in the Central Repository database
|
||||
* accordingly
|
||||
*/
|
||||
@Messages({"caseeventlistener.evidencetag=Evidence"})
|
||||
public class CaseEventListener implements PropertyChangeListener {
|
||||
@ -75,7 +75,8 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
|| (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.isDir() == true)
|
||||
|| (!af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC))) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -108,7 +109,7 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
new EamDataSource(deviceId, dsName),
|
||||
af.getParentPath() + af.getName(),
|
||||
tagAdded.getComment(),
|
||||
EamArtifactInstance.KnownStatus.BAD,
|
||||
TskData.FileKnown.BAD,
|
||||
EamArtifactInstance.GlobalStatus.LOCAL
|
||||
);
|
||||
eamArtifact.addInstance(cei);
|
||||
|
@ -49,8 +49,8 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
|
||||
/**
|
||||
* Ingest module for inserting entries into the Central Repository
|
||||
* database on ingest of a data source
|
||||
* Ingest module for inserting entries into the Central Repository database on
|
||||
* ingest of a data source
|
||||
*/
|
||||
@Messages({"IngestModule.prevcases.text=Previous Cases"})
|
||||
class IngestModule implements FileIngestModule {
|
||||
@ -83,7 +83,8 @@ class IngestModule implements FileIngestModule {
|
||||
|| (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.isDir() == true)
|
||||
|| (!af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC))) {
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
@ -134,7 +135,7 @@ class IngestModule implements FileIngestModule {
|
||||
eamDataSource,
|
||||
af.getParentPath() + af.getName(),
|
||||
"",
|
||||
EamArtifactInstance.KnownStatus.UNKNOWN,
|
||||
TskData.FileKnown.UNKNOWN,
|
||||
EamArtifactInstance.GlobalStatus.LOCAL
|
||||
);
|
||||
eamArtifact.addInstance(cefi);
|
||||
@ -158,7 +159,7 @@ class IngestModule implements FileIngestModule {
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
try {
|
||||
dbManager.bulkInsertArtifacts();
|
||||
|
@ -56,7 +56,7 @@ AddNewOrganizationDialog.bnOK.text=OK
|
||||
AddNewOrganizationDialog.tfName.tooltip=POC Name
|
||||
ManageTagsDialog.okButton.text=OK
|
||||
ManageTagsDialog.cancelButton.text=Cancel
|
||||
ManageArtifactTypesDialog.taInstructionsMsg.text=Enable one or more correlation properties to use for correlation during Ingest.
|
||||
ManageArtifactTypesDialog.taInstructionsMsg.text=Enable one or more correlation properties to use for correlation during ingest. Note, these properties are global and impact all users of the central repository.
|
||||
EamSqliteSettingsDialog.bnOk.text=OK
|
||||
EamPostgresSettingsDialog.bnSave.text=Save
|
||||
EamDbSettingsDialog.pnDatabaseConnectionSettings.border.title=Database Settings
|
||||
|
@ -53,6 +53,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalFileInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Instances of this class allow a user to select an existing hash database and
|
||||
@ -509,11 +510,11 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
}
|
||||
|
||||
// insert hashes
|
||||
EamArtifactInstance.KnownStatus knownStatus = EamArtifactInstance.KnownStatus.UNKNOWN;
|
||||
TskData.FileKnown knownStatus = TskData.FileKnown.UNKNOWN;
|
||||
if (knownRadioButton.isSelected()) {
|
||||
knownStatus = EamArtifactInstance.KnownStatus.KNOWN;
|
||||
knownStatus = TskData.FileKnown.KNOWN;
|
||||
} else if (knownBadRadioButton.isSelected()) {
|
||||
knownStatus = EamArtifactInstance.KnownStatus.BAD;
|
||||
knownStatus = TskData.FileKnown.BAD;
|
||||
}
|
||||
|
||||
String errorMessage = NbBundle.getMessage(this.getClass(),
|
||||
@ -562,10 +563,10 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
private class ImportHashDatabaseWorker extends SwingWorker<Object, Void> {
|
||||
|
||||
private final File file;
|
||||
private final EamArtifactInstance.KnownStatus knownStatus;
|
||||
private final TskData.FileKnown knownStatus;
|
||||
private final int globalSetID;
|
||||
|
||||
public ImportHashDatabaseWorker(String filename, EamArtifactInstance.KnownStatus knownStatus, int globalSetID) throws EamDbException, UnknownHostException {
|
||||
public ImportHashDatabaseWorker(String filename, TskData.FileKnown knownStatus, int globalSetID) throws EamDbException, UnknownHostException {
|
||||
this.file = new File(filename);
|
||||
this.knownStatus = knownStatus;
|
||||
this.globalSetID = globalSetID;
|
||||
|
@ -32,8 +32,14 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.TableColumnModelEvent;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.event.TableColumnModelListener;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import javax.swing.text.View;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.Lookup;
|
||||
@ -52,8 +58,8 @@ import org.netbeans.swing.etable.ETable;
|
||||
|
||||
/**
|
||||
* Instances of this class display the BlackboardArtifacts associated with the
|
||||
* Content represented by a Node. Each BlackboardArtifact is rendered displayed in a JTable
|
||||
* representation of its BlackboardAttributes.
|
||||
* Content represented by a Node. Each BlackboardArtifact is rendered displayed
|
||||
* in a JTable representation of its BlackboardAttributes.
|
||||
*/
|
||||
@ServiceProvider(service = DataContentViewer.class, position = 3)
|
||||
public class DataContentViewerArtifact extends javax.swing.JPanel implements DataContentViewer {
|
||||
@ -78,6 +84,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
Bundle.DataContentViewerArtifact_attrsTableHeader_value(),
|
||||
Bundle.DataContentViewerArtifact_attrsTableHeader_sources()};
|
||||
private static final int[] COLUMN_WIDTHS = {100, 800, 100};
|
||||
private static final int CELL_BOTTOM_MARGIN = 5;
|
||||
|
||||
public DataContentViewerArtifact() {
|
||||
initResultsTable();
|
||||
@ -85,6 +92,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
resultsTableScrollPane.setViewportView(resultsTable);
|
||||
customizeComponents();
|
||||
resetComponents();
|
||||
resultsTable.setDefaultRenderer(Object.class, new MultiLineTableCellRenderer());
|
||||
}
|
||||
|
||||
private void initResultsTable() {
|
||||
@ -100,11 +108,71 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
resultsTable.getTableHeader().setReorderingAllowed(false);
|
||||
resultsTable.setColumnHidingAllowed(false);
|
||||
resultsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||
updateColumnSizes();
|
||||
resultsTable.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
|
||||
|
||||
@Override
|
||||
public void columnAdded(TableColumnModelEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columnRemoved(TableColumnModelEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columnMoved(TableColumnModelEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columnMarginChanged(ChangeEvent e) {
|
||||
updateRowHeights(); //When the user changes column width we may need to resize row height
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columnSelectionChanged(ListSelectionEvent e) {
|
||||
}
|
||||
});
|
||||
resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the row heights to the heights of the content in their Value column.
|
||||
*/
|
||||
private void updateRowHeights() {
|
||||
int valueColIndex = -1;
|
||||
for (int col = 0; col < resultsTable.getColumnCount(); col++) {
|
||||
if (resultsTable.getColumnName(col).equals(COLUMN_HEADERS[1])) {
|
||||
valueColIndex = col;
|
||||
}
|
||||
}
|
||||
if (valueColIndex != -1) {
|
||||
for (int row = 0; row < resultsTable.getRowCount(); row++) {
|
||||
Component comp = resultsTable.prepareRenderer(
|
||||
resultsTable.getCellRenderer(row, valueColIndex), row, valueColIndex);
|
||||
final int rowHeight;
|
||||
if (comp instanceof JTextComponent) {
|
||||
final JTextComponent tc = (JTextComponent) comp;
|
||||
final View rootView = tc.getUI().getRootView(tc);
|
||||
java.awt.Insets i = tc.getInsets(null);
|
||||
rootView.setSize(resultsTable.getColumnModel().getColumn(valueColIndex)
|
||||
.getPreferredWidth() - i.left - i.right,
|
||||
Integer.MAX_VALUE);
|
||||
rowHeight = (int) rootView.getPreferredSpan(View.Y_AXIS);
|
||||
} else {
|
||||
rowHeight = comp.getPreferredSize().height;
|
||||
}
|
||||
if (rowHeight > 0) {
|
||||
resultsTable.setRowHeight(row, rowHeight + CELL_BOTTOM_MARGIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the column widths so that the Value column has most of the space.
|
||||
*/
|
||||
private void updateColumnSizes() {
|
||||
resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN);
|
||||
Enumeration<TableColumn> columns = resultsTable.getColumnModel().getColumns();
|
||||
while (columns.hasMoreElements()) {
|
||||
TableColumn col = columns.nextElement();
|
||||
@ -551,6 +619,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
|
||||
tModel.setDataVector(viewUpdate.tableContents.getRows(), COLUMN_HEADERS);
|
||||
updateColumnSizes();
|
||||
updateRowHeights();
|
||||
resultsTable.clearSelection();
|
||||
|
||||
this.setCursor(null);
|
||||
@ -568,6 +637,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
|
||||
tModel.setDataVector(waitRow, COLUMN_HEADERS);
|
||||
updateColumnSizes();
|
||||
updateRowHeights();
|
||||
resultsTable.clearSelection();
|
||||
// The output of the previous task is no longer relevant.
|
||||
if (currentTask != null) {
|
||||
@ -758,4 +828,27 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TableCellRenderer for displaying multiline text.
|
||||
*/
|
||||
private class MultiLineTableCellRenderer implements javax.swing.table.TableCellRenderer {
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
javax.swing.JTextArea jtex = new javax.swing.JTextArea();
|
||||
if (value instanceof String) {
|
||||
jtex.setText((String) value);
|
||||
jtex.setLineWrap(true);
|
||||
jtex.setWrapStyleWord(true);
|
||||
}
|
||||
//cell backgroud color when selected
|
||||
if (isSelected) {
|
||||
jtex.setBackground(javax.swing.UIManager.getColor("Table.selectionBackground"));
|
||||
} else {
|
||||
jtex.setBackground(javax.swing.UIManager.getColor("Table.background"));
|
||||
}
|
||||
return jtex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,9 @@ import org.sleuthkit.datamodel.TskData;
|
||||
/**
|
||||
* Filters database results by file extension.
|
||||
*/
|
||||
public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(FileTypesByExtension.class.getName());
|
||||
|
||||
private final SleuthkitCase skCase;
|
||||
|
||||
@ -72,13 +74,63 @@ import org.sleuthkit.datamodel.TskData;
|
||||
* Listens for case and ingest invest. Updates observers when events are
|
||||
* fired. FileType and FileTypes nodes are all listening to this.
|
||||
*/
|
||||
private static class FileTypesByExtObservable extends Observable {
|
||||
static private class FileTypesByExtObservable extends Observable {
|
||||
|
||||
private FileTypesByExtObservable() {
|
||||
private boolean showCounts = true;
|
||||
private final PropertyChangeListener pcl;
|
||||
|
||||
private FileTypesByExtObservable(SleuthkitCase skCase) {
|
||||
super();
|
||||
this.pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString()) || eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked
|
||||
* out. Currently, remote events may be received for a case
|
||||
* that is already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
shouldShowCounts(skCase);
|
||||
update();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||
if (evt.getNewValue() == null) {
|
||||
removeListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(pcl);
|
||||
Case.addPropertyChangeListener(pcl);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the nodes show counts?
|
||||
*
|
||||
*
|
||||
* @return True, unless the DB has more than 200k rows.
|
||||
*/
|
||||
private boolean shouldShowCounts(SleuthkitCase skCase) {
|
||||
if (showCounts) {
|
||||
try {
|
||||
if (skCase.countFilesWhere("1=1") > 200000) {
|
||||
showCounts = false;
|
||||
}
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
showCounts = false;
|
||||
LOGGER.log(Level.SEVERE, "Error counting files.", tskCoreException);
|
||||
}
|
||||
}
|
||||
return showCounts;
|
||||
}
|
||||
|
||||
private void removeListeners() {
|
||||
@ -88,31 +140,6 @@ import org.sleuthkit.datamodel.TskData;
|
||||
Case.removePropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString()) || eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked out.
|
||||
* Currently, remote events may be received for a case that is
|
||||
* already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
update();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||
if (evt.getNewValue() == null) {
|
||||
removeListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void update() {
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
@ -146,7 +173,7 @@ import org.sleuthkit.datamodel.TskData;
|
||||
* @param o Observable that was created by a higher-level node that
|
||||
* provides updates on events
|
||||
*/
|
||||
private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, Observable o) {
|
||||
private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
||||
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName()));
|
||||
this.filter = filter;
|
||||
init();
|
||||
@ -206,7 +233,7 @@ import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
private final SleuthkitCase skCase;
|
||||
private final FileTypesByExtension.RootFilter filter;
|
||||
private final Observable notifier;
|
||||
private final FileTypesByExtObservable notifier;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -215,12 +242,12 @@ import org.sleuthkit.datamodel.TskData;
|
||||
* @param o Observable that provides updates based on events
|
||||
* being fired (or null if one needs to be created)
|
||||
*/
|
||||
private FileTypesByExtNodeChildren(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, Observable o) {
|
||||
private FileTypesByExtNodeChildren(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
||||
super();
|
||||
this.skCase = skCase;
|
||||
this.filter = filter;
|
||||
if (o == null) {
|
||||
this.notifier = new FileTypesByExtObservable();
|
||||
this.notifier = new FileTypesByExtObservable(skCase);
|
||||
} else {
|
||||
this.notifier = o;
|
||||
}
|
||||
@ -263,6 +290,7 @@ import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
FileTypesByExtension.SearchFilterInterface filter;
|
||||
SleuthkitCase skCase;
|
||||
private final FileTypesByExtObservable notifier;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -271,10 +299,11 @@ import org.sleuthkit.datamodel.TskData;
|
||||
* @param o Observable that sends updates when the child factories
|
||||
* should refresh
|
||||
*/
|
||||
FileExtensionNode(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) {
|
||||
FileExtensionNode(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, FileTypesByExtObservable o) {
|
||||
super(Children.create(new FileExtensionNodeChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
|
||||
this.filter = filter;
|
||||
this.skCase = skCase;
|
||||
this.notifier = o;
|
||||
init();
|
||||
o.addObserver(new ByExtNodeObserver());
|
||||
}
|
||||
@ -295,8 +324,10 @@ import org.sleuthkit.datamodel.TskData;
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
final long count = FileExtensionNodeChildren.calculateItems(skCase, filter);
|
||||
super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
|
||||
final String count = notifier.shouldShowCounts(skCase)
|
||||
? " (" + Long.toString(FileExtensionNodeChildren.calculateItems(skCase, filter)) + ")"
|
||||
: "";
|
||||
super.setDisplayName(filter.getDisplayName() + count);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,41 +71,18 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
private final HashMap<String, List<String>> existingMimeTypes = new HashMap<>();
|
||||
private static final Logger LOGGER = Logger.getLogger(FileTypesByMimeType.class.getName());
|
||||
|
||||
private boolean showCounts = true;
|
||||
|
||||
private void removeListeners() {
|
||||
deleteObservers();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
Case.removePropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
/*
|
||||
* The pcl is in the class because it has the easiest mechanisms to add and
|
||||
* remove itself during its life cycles.
|
||||
*/
|
||||
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked out.
|
||||
* Currently, remote events may be received for a case that is
|
||||
* already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
populateHashMap();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
if (evt.getNewValue() == null) {
|
||||
removeListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
private final PropertyChangeListener pcl;
|
||||
|
||||
/**
|
||||
* Retrieve the media types by retrieving the keyset from the hashmap.
|
||||
@ -140,7 +117,6 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
existingMimeTypes.clear();
|
||||
|
||||
if (skCase == null) {
|
||||
|
||||
return;
|
||||
}
|
||||
try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(allDistinctMimeTypesQuery.toString())) {
|
||||
@ -170,12 +146,59 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
}
|
||||
|
||||
FileTypesByMimeType(SleuthkitCase skCase) {
|
||||
this.pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked out.
|
||||
* Currently, remote events may be received for a case that is
|
||||
* already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
shouldShowCounts(skCase);
|
||||
|
||||
populateHashMap();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
if (evt.getNewValue() == null) {
|
||||
removeListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
||||
Case.addPropertyChangeListener(pcl);
|
||||
this.skCase = skCase;
|
||||
populateHashMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the nodes show counts?
|
||||
*
|
||||
*
|
||||
* @return True, unless the DB has more than 200k rows.
|
||||
*/
|
||||
private boolean shouldShowCounts(final SleuthkitCase skCase) {
|
||||
if (showCounts) {
|
||||
try {
|
||||
if (skCase.countFilesWhere("1=1") > 200000) {
|
||||
showCounts = false;
|
||||
}
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
showCounts = false;
|
||||
LOGGER.log(Level.SEVERE, "Error counting files.", tskCoreException);
|
||||
}
|
||||
}
|
||||
return showCounts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
@ -358,10 +381,12 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
* results
|
||||
*/
|
||||
private void updateDisplayName(String mimeType) {
|
||||
final long count = new MediaSubTypeNodeChildren(mimeType).calculateItems(skCase, mimeType);
|
||||
final String count = shouldShowCounts(skCase)
|
||||
? " (" + Long.toString(new MediaSubTypeNodeChildren(mimeType).calculateItems(skCase, mimeType)) + ")"
|
||||
: "";
|
||||
String[] mimeTypeParts = mimeType.split("/");
|
||||
//joins up all remaining parts of the mimeType into one sub-type string
|
||||
super.setDisplayName(StringUtils.join(ArrayUtils.subarray(mimeTypeParts, 1, mimeTypeParts.length), "/") + " (" + count + ")");
|
||||
super.setDisplayName(StringUtils.join(ArrayUtils.subarray(mimeTypeParts, 1, mimeTypeParts.length), "/") + count);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -236,10 +236,10 @@ KeywordSearchGlobalLanguageSettingsPanel.ingestSettingsLabel.text=Ingest setting
|
||||
KeywordSearchGlobalLanguageSettingsPanel.enableUTF16Checkbox.text=Enable UTF16LE and UTF16BE string extraction
|
||||
KeywordSearchGlobalLanguageSettingsPanel.languagesLabel.text=Enabled scripts (languages):
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.toolTipText=20 mins. (fastest ingest time)
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20 minutes
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20 minutes (slowest feedback, fastest ingest)
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.toolTipText=10 minutes (faster overall ingest time than default)
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text=10 minutes
|
||||
KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text=Results update frequency during ingest (we have not seen significant performance differences between 5, 10, or 20 minute intervals):
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text=10 minutes (slower feedback, faster ingest)
|
||||
KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text=Results update frequency during ingest:
|
||||
KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.toolTipText=Requires Hash DB service to had run previously, or be selected for next ingest.
|
||||
KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.text=Do not add files in NSRL (known files) to keyword index during ingest
|
||||
KeywordSearchGlobalSearchSettingsPanel.informationLabel.text=Information
|
||||
@ -249,7 +249,7 @@ KeywordSearchGlobalSearchSettingsPanel.filesIndexedLabel.text=Files in keyword i
|
||||
KeywordSearchGlobalSearchSettingsPanel.showSnippetsCB.text=Show Keyword Preview in Keyword Search Results (will result in longer search times)
|
||||
KeywordSearchGlobalSearchSettingsPanel.chunksValLabel.text=0
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.toolTipText=1 minute (overall ingest time will be longest)
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1=1 minute
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1=1 minute (faster feedback, longest ingest)
|
||||
KeywordSearchGlobalSearchSettingsPanel.chunksLabel.text=Chunks in keyword index:
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.toolTipText=5 minutes (overall ingest time will be longer)
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.text=5 minutes (default)
|
||||
|
Loading…
x
Reference in New Issue
Block a user