Updated with changes per standup conversation

This commit is contained in:
Kelly Kelly 2021-05-25 17:25:03 -04:00
parent f1c25b4fef
commit 1ff145c80e
3 changed files with 92 additions and 80 deletions

View File

@ -65,6 +65,7 @@ import javax.annotation.concurrent.ThreadSafe;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.openide.util.Exceptions;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
@ -507,6 +508,7 @@ public class Case {
@Subscribe @Subscribe
public void publishOsAccountAddedEvent(TskEvent.OsAccountsAddedTskEvent event) { public void publishOsAccountAddedEvent(TskEvent.OsAccountsAddedTskEvent event) {
hasData = true;
for (OsAccount account : event.getOsAcounts()) { for (OsAccount account : event.getOsAcounts()) {
eventPublisher.publish(new OsAccountAddedEvent(account)); eventPublisher.publish(new OsAccountAddedEvent(account));
} }
@ -521,6 +523,12 @@ public class Case {
@Subscribe @Subscribe
public void publishOsAccountDeletedEvent(TskEvent.OsAccountsDeletedTskEvent event) { public void publishOsAccountDeletedEvent(TskEvent.OsAccountsDeletedTskEvent event) {
try {
hasData = dbHasData();
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex);
}
for (Long accountId : event.getOsAcountObjectIds()) { for (Long accountId : event.getOsAcountObjectIds()) {
eventPublisher.publish(new OsAccountDeletedEvent(accountId)); eventPublisher.publish(new OsAccountDeletedEvent(accountId));
} }
@ -534,6 +542,7 @@ public class Case {
*/ */
@Subscribe @Subscribe
public void publishHostsAddedEvent(TskEvent.HostsAddedTskEvent event) { public void publishHostsAddedEvent(TskEvent.HostsAddedTskEvent event) {
hasData = true;
eventPublisher.publish(new HostsAddedEvent( eventPublisher.publish(new HostsAddedEvent(
event == null ? Collections.emptyList() : event.getHosts())); event == null ? Collections.emptyList() : event.getHosts()));
} }
@ -558,6 +567,12 @@ public class Case {
*/ */
@Subscribe @Subscribe
public void publishHostsDeletedEvent(TskEvent.HostsDeletedTskEvent event) { public void publishHostsDeletedEvent(TskEvent.HostsDeletedTskEvent event) {
try {
hasData = dbHasData();
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex);
}
eventPublisher.publish(new HostsRemovedEvent( eventPublisher.publish(new HostsRemovedEvent(
event == null ? Collections.emptyList() : event.getHosts())); event == null ? Collections.emptyList() : event.getHosts()));
} }
@ -1036,7 +1051,6 @@ public class Case {
progressIndicatorTitle = Bundle.Case_progressIndicatorTitle_openingCase(); progressIndicatorTitle = Bundle.Case_progressIndicatorTitle_openingCase();
openCaseAction = newCurrentCase::open; openCaseAction = newCurrentCase::open;
} }
newCurrentCase.initializeDataListners();
newCurrentCase.doOpenCaseAction(progressIndicatorTitle, openCaseAction, CaseLockType.SHARED, true, null); newCurrentCase.doOpenCaseAction(progressIndicatorTitle, openCaseAction, CaseLockType.SHARED, true, null);
currentCase = newCurrentCase; currentCase = newCurrentCase;
logger.log(Level.INFO, "Opened {0} ({1}) in {2} as the current case", new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()}); //NON-NLS logger.log(Level.INFO, "Opened {0} ({1}) in {2} as the current case", new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()}); //NON-NLS
@ -1671,8 +1685,7 @@ public class Case {
} }
/** /**
* Queries whether or not the case has data, i.e., whether or not at least * Returns true if there is any data in the case.
* one data source has been added to the case.
* *
* @return True or false. * @return True or false.
*/ */
@ -1680,7 +1693,12 @@ public class Case {
return hasData; return hasData;
} }
public boolean hasDataSources() { /**
* Returns true if there is one or more data sources in the case.
*
* @return True or false.
*/
public boolean hasDataSource() {
return hasDataSource; return hasDataSource;
} }
@ -1695,6 +1713,8 @@ public class Case {
* notifyNewDataSource after the data source is added. * notifyNewDataSource after the data source is added.
*/ */
public void notifyAddingDataSource(UUID eventId) { public void notifyAddingDataSource(UUID eventId) {
hasDataSource = true;
hasData = true;
eventPublisher.publish(new AddingDataSourceEvent(eventId)); eventPublisher.publish(new AddingDataSourceEvent(eventId));
} }
@ -1947,6 +1967,8 @@ public class Case {
String errorMsg = "Invalid local path provided: " + localPath; // NON-NLS String errorMsg = "Invalid local path provided: " + localPath; // NON-NLS
throw new TskCoreException(errorMsg, ex); throw new TskCoreException(errorMsg, ex);
} }
hasData = true;
Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName, parent); Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName, parent);
eventPublisher.publish(new ReportAddedEvent(report)); eventPublisher.publish(new ReportAddedEvent(report));
return report; return report;
@ -1975,6 +1997,15 @@ public class Case {
public void deleteReports(Collection<? extends Report> reports) throws TskCoreException { public void deleteReports(Collection<? extends Report> reports) throws TskCoreException {
for (Report report : reports) { for (Report report : reports) {
this.caseDb.deleteReport(report); this.caseDb.deleteReport(report);
}
try {
hasData = dbHasData();
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex);
}
for (Report report : reports) {
eventPublisher.publish(new AutopsyEvent(Events.REPORT_DELETED.toString(), report, null)); eventPublisher.publish(new AutopsyEvent(Events.REPORT_DELETED.toString(), report, null));
} }
} }
@ -2727,13 +2758,12 @@ public class Case {
String databaseName = metadata.getCaseDatabaseName(); String databaseName = metadata.getCaseDatabaseName();
if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) { if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) {
caseDb = SleuthkitCase.openCase(Paths.get(metadata.getCaseDirectory(), databaseName).toString()); caseDb = SleuthkitCase.openCase(Paths.get(metadata.getCaseDirectory(), databaseName).toString());
initializeDataParameters();
} else if (UserPreferences.getIsMultiUserModeEnabled()) { } else if (UserPreferences.getIsMultiUserModeEnabled()) {
caseDb = SleuthkitCase.openCase(databaseName, UserPreferences.getDatabaseConnectionInfo(), metadata.getCaseDirectory()); caseDb = SleuthkitCase.openCase(databaseName, UserPreferences.getDatabaseConnectionInfo(), metadata.getCaseDirectory());
initializeDataParameters();
} else { } else {
throw new CaseActionException(Bundle.Case_open_exception_multiUserCaseNotEnabled()); throw new CaseActionException(Bundle.Case_open_exception_multiUserCaseNotEnabled());
} }
updateDataParameters();
} catch (TskUnsupportedSchemaVersionException ex) { } catch (TskUnsupportedSchemaVersionException ex) {
throw new CaseActionException(Bundle.Case_exceptionMessage_unsupportedSchemaVersionMessage(ex.getLocalizedMessage()), ex); throw new CaseActionException(Bundle.Case_exceptionMessage_unsupportedSchemaVersionMessage(ex.getLocalizedMessage()), ex);
} catch (UserPreferencesException ex) { } catch (UserPreferencesException ex) {
@ -3511,22 +3541,6 @@ public class Case {
} }
} }
private long getDataSourceCount() throws TskCoreException {
long numDataSources = 0;
String query = "SELECT count(*) AS count FROM data_source_info";
try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet();
if (resultSet.next()) {
numDataSources = resultSet.getLong("count");
}
} catch ( SQLException ex) {
logger.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS
throw new TskCoreException("Error accessing case databse", ex);
}
return numDataSources;
}
/** /**
* Initialize the hasData and hasDataSource parameters by checking the * Initialize the hasData and hasDataSource parameters by checking the
* database. * database.
@ -3538,66 +3552,64 @@ public class Case {
* *
* @throws TskCoreException * @throws TskCoreException
*/ */
private void initializeDataParameters() throws TskCoreException { private void updateDataParameters() throws TskCoreException {
hasDataSource = getDataSourceCount() > 0; hasDataSource = dbHasDataSource();
if(!hasDataSource) { if (!hasDataSource) {
// Check to see if there are objects like os accounts or reports hasData = dbHasData();
// which both have object ids assocated with them.
String query = "SELECT count(*) AS count FROM tsk_objects";
try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet();
if (resultSet.next()) {
hasData = resultSet.getLong("count") > 0;
}
} catch ( SQLException ex) {
logger.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS
throw new TskCoreException("Error accessing case databse", ex);
}
} else { } else {
hasData = true; hasData = true;
} }
if(!hasData) {
// No object, but check to see if there are any hosts.
String query = "SELECT count(*) AS count FROM tsk_hosts";
try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet();
if (resultSet.next()) {
hasData = resultSet.getLong("count") > 0;
}
} catch ( SQLException ex) {
logger.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS
throw new TskCoreException("Error accessing case databse", ex);
}
}
} }
/** /**
* Create the listeners, if needed, to update hasDataSource and hasData. * Returns true of there are any data sources in the case database.
*
* @return True if this case as a data source.
*
* @throws TskCoreException
*/ */
private void initializeDataListners() { private boolean dbHasDataSource() throws TskCoreException {
if(!hasDataSource) { String query = "SELECT count(*) AS count FROM (SELECT * FROM data_source_info LIMIT 1)t";
addEventTypeSubscriber(Collections.singleton(Case.Events.DATA_SOURCE_ADDED), new PropertyChangeListener() { try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
@Override ResultSet resultSet = dbQuery.getResultSet();
public void propertyChange(PropertyChangeEvent evt) { if (resultSet.next()) {
hasDataSource = true; return resultSet.getLong("count") > 0;
hasData = true; }
} return false;
}); } catch (SQLException ex) {
logger.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS
throw new TskCoreException("Error accessing case databse", ex);
} }
}
if(!hasData) { /**
PropertyChangeListener listener = new PropertyChangeListener() { * Returns true if the case has data. A case has data if there is at least
@Override * one row in either the tsk_objects or tsk_hosts table.
public void propertyChange(PropertyChangeEvent evt) { *
hasData = true; * @return True if there is data in this case.
} *
}; * @throws TskCoreException
*/
addEventTypeSubscriber(Collections.singleton(Case.Events.HOSTS_ADDED),listener); private boolean dbHasData() throws TskCoreException {
addEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNT_ADDED),listener); // The LIMIT 1 in the subquery should limit the data returned and
addEventTypeSubscriber(Collections.singleton(Case.Events.REPORT_ADDED),listener); // make the overall query more efficent.
String query = "SELECT SUM(cnt) total FROM "
+ "(SELECT COUNT(*) AS cnt FROM "
+ "(SELECT * FROM tsk_objects LIMIT 1)t "
+ "UNION ALL "
+ "SELECT COUNT(*) AS cnt FROM "
+ "(SELECT * FROM tsk_hosts LIMIT 1)r) s";
try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet();
if (resultSet.next()) {
return resultSet.getLong("total") > 0;
} else {
return false;
}
} catch ( SQLException ex) {
logger.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS
throw new TskCoreException("Error accessing case databse", ex);
} }
} }

View File

@ -85,7 +85,7 @@ public final class RunIngestAction extends CallableSystemAction implements Prese
public boolean isEnabled() { public boolean isEnabled() {
try { try {
Case openCase = Case.getCurrentCaseThrows(); Case openCase = Case.getCurrentCaseThrows();
return openCase.hasData(); return openCase.hasDataSource();
} catch (NoCurrentCaseException ex) { } catch (NoCurrentCaseException ex) {
return false; return false;
} }

View File

@ -104,7 +104,7 @@ public final class OpenTimelineAction extends CallableSystemAction {
synchronized private void showTimeline(AbstractFile file, BlackboardArtifact artifact, Interval timeSpan) throws TskCoreException { synchronized private void showTimeline(AbstractFile file, BlackboardArtifact artifact, Interval timeSpan) throws TskCoreException {
try { try {
Case currentCase = Case.getCurrentCaseThrows(); Case currentCase = Case.getCurrentCaseThrows();
if (currentCase.hasData() == false) { if (currentCase.hasDataSource() == false) {
MessageNotifyUtil.Message.info(Bundle.OpenTimeLineAction_msgdlg_text()); MessageNotifyUtil.Message.info(Bundle.OpenTimeLineAction_msgdlg_text());
logger.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS logger.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS
return; return;