resolved merge conflicts.

This commit is contained in:
Nick Davis 2017-06-28 13:11:35 -04:00
commit 6b2316e2b8
18 changed files with 373 additions and 210 deletions

View File

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

View File

@ -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();

View File

@ -35,6 +35,7 @@ import java.util.Map;
import java.util.Set;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.TskData;
/**
*
@ -100,7 +101,6 @@ public abstract class AbstractSqlEamDb implements EamDb {
// }
// // else, schema is current
// }
/**
* Setup and create a connection to the selected database implementation
*/
@ -550,8 +550,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 +599,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 +655,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 +698,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 +716,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 +806,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 +874,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 +906,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 +957,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 +996,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 +1043,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 +1064,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 +1096,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 +1137,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 +1187,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 +1228,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);
@ -1440,28 +1450,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
*/
// @Override
// public void prepareGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException {
// synchronized (bulkGlobalArtifacts) {
// bulkGlobalArtifacts.get("FILES").add(eamGlobalFileInstance); // NON-NLS
// bulkGlobalArtifactsCount++;
//
// if (bulkGlobalArtifactsCount >= bulkArtifactsThreshold) {
// bulkInsertGlobalFileInstances();
// }
// }
// }
/**
* Insert the bulk collection of Global File Instances
*
* @throws EamDbException
*
* @throws EamDbException
*/
@Override
public void bulkInsertGlobalFileInstances(Set<EamGlobalFileInstance> globalInstances, EamArtifact.Type contentType) throws EamDbException {
@ -1470,7 +1462,8 @@ public abstract class AbstractSqlEamDb implements EamDb {
PreparedStatement bulkPs = null;
try {
// FUTURE: have a separate global_files table for each Type.
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);
@ -1493,10 +1486,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 {
@ -1529,7 +1524,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 {
@ -1561,7 +1557,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 {
@ -1595,7 +1592,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 {
@ -1629,7 +1627,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 {
@ -1661,7 +1660,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 {
@ -1693,7 +1693,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 {
@ -1810,7 +1811,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
);
@ -1858,7 +1859,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")
);

View File

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

View File

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

View File

@ -19,7 +19,7 @@
package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.util.Objects;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance.KnownStatus;
import org.sleuthkit.datamodel.TskData;
/**
* Global file hash instance
@ -29,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;
@ -48,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);
}
@ -69,7 +69,7 @@ public class EamGlobalFileInstance {
int hash = 5;
hash = 59 * hash + this.globalSetID;
hash = 59 * hash + Objects.hashCode(this.MD5Hash);
hash = 59 * hash + Objects.hashCode(this.knownStatus);
hash = 59 * hash + this.knownStatus.hashCode();
return hash;
}
/**
@ -117,14 +117,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;
}

View File

@ -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();

View File

@ -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() {

View File

@ -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();

View File

@ -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)";
@ -321,9 +321,9 @@ public final class SqliteEamDbSettings {
createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
createArtifactInstancesTableTemplate.append("known_status text NOT NULL,");
createArtifactInstancesTableTemplate.append("comment text NOT NULL,");
createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique UNIQUE(case_id, data_source_id, value, file_path),");
createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,");
createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null");
createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique UNIQUE(case_id, data_source_id, value, file_path) ON CONFLICT IGNORE,");
createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
createArtifactInstancesTableTemplate.append(")");
// TODO: do we need any more indices?

View File

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

View File

@ -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();

View File

@ -49,7 +49,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

View File

@ -60,6 +60,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.datamodel.TskData;
/**
* Instances of this class allow a user to select an existing hash database and
@ -515,11 +516,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 = Bundle.ImportHashDatabaseDialog_errorMessage_failedToOpenHashDbMsg(selectedFilePath);
@ -529,7 +530,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
// run in the background and close dialog
SwingUtilities.invokeLater(new ImportHashDatabaseWorker(selectedFilePath, knownStatus, globalSetID, contentType)::execute);
dispose();
} catch (EamDbException ex) {
} catch (EamDbException | UnknownHostException ex) {
Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.SEVERE, errorMessage, ex);
lbWarningMsg.setText(ex.getMessage());
}
@ -564,12 +565,12 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
private class ImportHashDatabaseWorker extends SwingWorker<Void, Void> {
private final File file;
private final EamArtifactInstance.KnownStatus knownStatus;
private final TskData.FileKnown knownStatus;
private final int globalSetID;
private final ProgressHandle progress;
private final EamArtifact.Type contentType;
public ImportHashDatabaseWorker(String filename, EamArtifactInstance.KnownStatus knownStatus, int globalSetID, EamArtifact.Type contentType) throws EamDbException {
public ImportHashDatabaseWorker(String filename, TskData.FileKnown knownStatus, int globalSetID, EamArtifact.Type contentType) throws EamDbException, UnknownHostException {
this.file = new File(filename);
this.knownStatus = knownStatus;
this.globalSetID = globalSetID;

View File

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

View File

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

View File

@ -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);
}
/**

View File

@ -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)