From bbc65f6afdec4b8337459768ed85a73cd6825d78 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Mon, 26 Nov 2018 17:45:16 -0500 Subject: [PATCH 01/12] Fixed JIRA-1144 about incorrect dialogs when opening single-user case with single data source during ingest --- .../imagegallery/ImageGalleryController.java | 2 +- .../imagegallery/ImageGalleryModule.java | 2 +- .../imagegallery/actions/OpenAction.java | 112 ++++++++++-------- .../imagegallery/datamodel/DrawableDB.java | 2 +- .../imagegallery/gui/DataSourceCell.java | 2 +- 5 files changed, 64 insertions(+), 56 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 862713a807..6ba0216604 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -160,7 +160,7 @@ public final class ImageGalleryController { } } - boolean isListeningEnabled() { + public boolean isListeningEnabled() { synchronized (listeningEnabled) { return listeningEnabled.get(); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java index 5341e0be27..1ab7caf246 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java @@ -277,7 +277,7 @@ public class ImageGalleryModule { if (((AutopsyEvent) evt).getSourceType() == AutopsyEvent.SourceType.LOCAL) { Content newDataSource = (Content) evt.getNewValue(); if (con.isListeningEnabled()) { - controller.getDatabase().insertOrUpdateDataSource(newDataSource.getId(), DrawableDB.DrawableDbBuildStatusEnum.DEFAULT); + controller.getDatabase().insertOrUpdateDataSource(newDataSource.getId(), DrawableDB.DrawableDbBuildStatusEnum.UNKNOWN); } } break; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java index 5a921e6130..606cb0c369 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java @@ -192,72 +192,80 @@ public final class OpenAction extends CallableSystemAction { addFXCallback(dataSourceStatusMapFuture, dataSourceStatusMap -> { - boolean dbIsStale = false; + int numUnknown = 0; for (Map.Entry entry : dataSourceStatusMap.entrySet()) { DrawableDbBuildStatusEnum status = entry.getValue(); - if (DrawableDbBuildStatusEnum.COMPLETE != status) { - dbIsStale = true; + if (DrawableDbBuildStatusEnum.UNKNOWN == status) { + numUnknown++; } } - //back on fx thread. - if (false == dbIsStale) { - //drawable db is not stale, just open it - openTopComponent(); - } else { + // NOTE: we are running on the fx thread. + + // If there are data sources in the "UNKNOWN" state, then we MAY need to rebuild. + // Or not because single-user cases can have UNKNOWN states if ingest was not run yet + if (numUnknown > 0) { + /* A rebuild should occur if either + * - Multi-user case and at least one DS is UNKNOWN + * - Single-user case and case listening has been disabled + */ + if ((controller.getAutopsyCase().getCaseType() == Case.CaseType.MULTI_USER_CASE) || + ((controller.getAutopsyCase().getCaseType() == Case.CaseType.SINGLE_USER_CASE) && + (controller.isListeningEnabled() == false))) { - // If there is only one datasource and it's in DEFAULT State - - // ingest modules need to be run on the data source - if (dataSourceStatusMap.size()== 1) { - Map.Entry entry = dataSourceStatusMap.entrySet().iterator().next(); - if (entry.getValue() == DrawableDbBuildStatusEnum.DEFAULT ) { + // See if user wants to rebuild, cancel out, or open as is + Alert alert = new Alert(Alert.AlertType.WARNING, + Bundle.OpenAction_stale_confDlg_msg(), + ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setTitle(Bundle.OpenAction_stale_confDlg_title()); + GuiUtils.setDialogIcons(alert); + ButtonType answer = alert.showAndWait().orElse(ButtonType.CANCEL); + + if (answer == ButtonType.CANCEL) { + //just do nothing - don't open window + return; + } else if (answer == ButtonType.NO) { + // They don't want to rebuild. Just open the UI as is. + // NOTE: There could be no data.... + } else if (answer == ButtonType.YES) { + if (controller.getAutopsyCase().getCaseType() == Case.CaseType.SINGLE_USER_CASE) { + /* For a single-user case, we favor user + * experience, and rebuild the database as soon + * as Image Gallery is enabled for the case. + * + * Turning listening off is necessary in order + * to invoke the listener that will call + * controller.rebuildDB(); + */ + controller.setListeningEnabled(false); + controller.setListeningEnabled(true); + } else { + /* + * For a multi-user case, we favor overall + * performance and user experience, not every + * user may want to review images, so we rebuild + * the database only when a user launches Image + * Gallery. + */ + controller.rebuildDB(); + } + } + } + else { // single user and listening is enabled + // give them a dialog to enable modules if no data sources have been analyzed + if (numUnknown == dataSourceStatusMap.size()) { Alert alert = new Alert(Alert.AlertType.WARNING, Bundle.OpenAction_notAnalyzedDlg_msg(), ButtonType.OK); alert.setTitle(Bundle.OpenAction_stale_confDlg_title()); alert.initModality(Modality.APPLICATION_MODAL); - alert.showAndWait(); return; } - } - - //drawable db is stale, - //ask what to do - Alert alert = new Alert(Alert.AlertType.WARNING, - Bundle.OpenAction_stale_confDlg_msg(), - ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); - alert.initModality(Modality.APPLICATION_MODAL); - alert.setTitle(Bundle.OpenAction_stale_confDlg_title()); - GuiUtils.setDialogIcons(alert); - ButtonType answer = alert.showAndWait().orElse(ButtonType.CANCEL); - if (answer == ButtonType.CANCEL) { - //just do nothing - } else if (answer == ButtonType.NO) { - openTopComponent(); - } else if (answer == ButtonType.YES) { - if (controller.getAutopsyCase().getCaseType() == Case.CaseType.SINGLE_USER_CASE) { - /* For a single-user case, we favor user - * experience, and rebuild the database as soon - * as Image Gallery is enabled for the case. - * - * Turning listening off is necessary in order - * to invoke the listener that will call - * controller.rebuildDB(); - */ - controller.setListeningEnabled(false); - controller.setListeningEnabled(true); - } else { - /* - * For a multi-user case, we favor overall - * performance and user experience, not every - * user may want to review images, so we rebuild - * the database only when a user launches Image - * Gallery. - */ - controller.rebuildDB(); - } - openTopComponent(); } } + + // otherwise, lets open the UI + openTopComponent(); }, throwable -> logger.log(Level.SEVERE, "Error checking if drawable db is stale.", throwable)//NON-NLS ); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index c981c91b3e..4b9fde00f7 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -178,7 +178,7 @@ public final class DrawableDB { * DO NOT add in the middle. */ public enum DrawableDbBuildStatusEnum { - UNKNOWN, /// no known status + UNKNOWN, /// no known status - not yet analyzed IN_PROGRESS, /// ingest or db rebuild is in progress COMPLETE, /// All files in the data source have had file type detected DEFAULT; /// Not all files in the data source have had file type detected diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DataSourceCell.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DataSourceCell.java index 7626c4fd77..f151fbd750 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DataSourceCell.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DataSourceCell.java @@ -63,7 +63,7 @@ public class DataSourceCell extends ListCell> { DrawableDbBuildStatusEnum dataSourceDBStatus = (dataSource != null) ? dataSourcesDrawableDBStatus.get(dataSource.getId()) : DrawableDbBuildStatusEnum.UNKNOWN; - Boolean dataSourceNotAnalyzed = (dataSourceDBStatus == DrawableDbBuildStatusEnum.DEFAULT); + Boolean dataSourceNotAnalyzed = (dataSourceDBStatus == DrawableDbBuildStatusEnum.UNKNOWN); if (tooManyFilesInDataSource) { text += " - Too many files"; } From 969a70a7f00663165041f5b95378166c4d53f51a Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 27 Nov 2018 17:32:02 -0500 Subject: [PATCH 02/12] fixed bug where 'All' was marked as unanalyzed --- .../imagegallery/gui/DataSourceCell.java | 52 ++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DataSourceCell.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DataSourceCell.java index f151fbd750..7f8bb397f6 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DataSourceCell.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DataSourceCell.java @@ -50,6 +50,11 @@ public class DataSourceCell extends ListCell> { } + /** + * + * @param item + * @param empty + */ @Override protected void updateItem(Optional item, boolean empty) { super.updateItem(item, empty); @@ -57,31 +62,42 @@ public class DataSourceCell extends ListCell> { setText(""); } else { DataSource dataSource = item.orElse(null); - String text = (dataSource == null) ? "All" : dataSource.getName() + " (Id: " + dataSource.getId() + ")"; - Boolean tooManyFilesInDataSource = dataSourcesTooManyFiles.getOrDefault(dataSource, false); + String dataSourceName; + boolean shouldEnable = true; // false if user should not be able to select the item - DrawableDbBuildStatusEnum dataSourceDBStatus = (dataSource != null) ? - dataSourcesDrawableDBStatus.get(dataSource.getId()) : DrawableDbBuildStatusEnum.UNKNOWN; - - Boolean dataSourceNotAnalyzed = (dataSourceDBStatus == DrawableDbBuildStatusEnum.UNKNOWN); - if (tooManyFilesInDataSource) { - text += " - Too many files"; - } - if (dataSourceNotAnalyzed) { - text += " - Not Analyzed"; - } - - // check if item should be disabled - if (tooManyFilesInDataSource || dataSourceNotAnalyzed) { - setDisable(true); - setStyle("-fx-opacity : .5"); + if (dataSource == null) { + dataSourceName = "All"; + // NOTE: openAction verifies that there is at least one data source with data. + // So, at this point, "All" should never need to be disabled because none of the data sources + // are analyzed. } else { + dataSourceName = dataSource.getName() + " (Id: " + dataSource.getId() + ")"; + if (dataSourcesDrawableDBStatus.get(dataSource.getId()) == DrawableDbBuildStatusEnum.UNKNOWN) { + dataSourceName += " - Not Analyzed"; + shouldEnable = false; + } + } + + // if it's analyzed, then make sure there aren't too many files + if (shouldEnable) { + if (dataSourcesTooManyFiles.getOrDefault(dataSource, false)) { + dataSourceName += " - Too Many Files"; + shouldEnable = false; + } + } + + // check if item should be disabled + if (shouldEnable) { setGraphic(null); setStyle("-fx-opacity : 1"); } + else { + setDisable(true); + setStyle("-fx-opacity : .5"); + } - setText(text); + setText(dataSourceName); } } } From 8511958f379528e3dbf38e3ad1202a30205ab920 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Tue, 27 Nov 2018 22:41:00 -0500 Subject: [PATCH 03/12] Added conditional for opened case. --- .../corecomponents/ViewPreferencesPanel.form | 9 +++++++-- .../corecomponents/ViewPreferencesPanel.java | 18 ++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.form index 1f9dfc4ceb..eb04956a1d 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.form @@ -1,6 +1,11 @@
+ + + + + @@ -32,7 +37,7 @@ - + @@ -41,7 +46,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.java index ae314da16d..18cc71a752 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.java @@ -79,7 +79,8 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { commentsOccurencesColumnsCheckbox.setEnabled(EamDbUtil.useCentralRepo()); commentsOccurencesColumnWrapAroundText.setEnabled(EamDbUtil.useCentralRepo()); commentsOccurencesColumnsCheckbox.setSelected(UserPreferences.hideCentralRepoCommentsAndOccurrences()); - + + hideOtherUsersTagsCheckbox.setSelected(UserPreferences.showOnlyCurrentUserTags()); deletedFilesLimitCheckbox.setSelected(DeletedFilePreferences.getDefault().getShouldLimitDeletedFiles()); translateNamesInTableRadioButton.setSelected(UserPreferences.displayTranslatedFileNames()); @@ -91,8 +92,11 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { currentCaseSettingsPanel.setEnabled(caseIsOpen); groupByDataSourceCheckbox.setEnabled(caseIsOpen); - hideOtherUsersTagsCheckbox.setSelected(UserPreferences.showOnlyCurrentUserTags()); - groupByDataSourceCheckbox.setSelected(Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)); + if (caseIsOpen) { + groupByDataSourceCheckbox.setSelected(Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)); + } else { + groupByDataSourceCheckbox.setSelected(false); + } // Current Session Settings hideRejectedResultsCheckbox.setSelected(DirectoryTreeTopComponent.getDefault().getShowRejectedResults() == false); @@ -174,10 +178,12 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { currentSessionSettingsPanel = new javax.swing.JPanel(); hideRejectedResultsCheckbox = new javax.swing.JCheckBox(); - viewPreferencesScrollPane.setBorder(null); - viewPreferencesScrollPane.setPreferredSize(new java.awt.Dimension(625, 452)); + setPreferredSize(new java.awt.Dimension(625, 465)); - viewPreferencesPanel.setPreferredSize(new java.awt.Dimension(625, 452)); + viewPreferencesScrollPane.setBorder(null); + viewPreferencesScrollPane.setPreferredSize(new java.awt.Dimension(625, 465)); + + viewPreferencesPanel.setPreferredSize(new java.awt.Dimension(625, 465)); globalSettingsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.globalSettingsPanel.border.title"))); // NOI18N From 551d5429b0820874b2dc054b08e207e5315bf496 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 28 Nov 2018 00:48:26 -0500 Subject: [PATCH 04/12] cleaned up IG states. Made more consistent. --- .../imagegallery/ImageGalleryController.java | 79 +++++++++++-------- .../imagegallery/ImageGalleryModule.java | 26 ++++-- .../imagegallery/actions/OpenAction.java | 10 +-- .../imagegallery/datamodel/DrawableDB.java | 22 +++--- 4 files changed, 79 insertions(+), 58 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 6ba0216604..1efa5ddad9 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -166,6 +166,10 @@ public final class ImageGalleryController { } } + /** + * + * @param b True if any data source in the case is stale + */ @ThreadConfined(type = ThreadConfined.ThreadType.ANY) void setStale(Boolean b) { Platform.runLater(() -> { @@ -177,6 +181,10 @@ public final class ImageGalleryController { return stale.getReadOnlyProperty(); } + /** + * + * @return true if any data source in the case is stale + */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) boolean isStale() { return stale.get(); @@ -344,7 +352,7 @@ public final class ImageGalleryController { * Returns a set of data source object ids that are stale. * * This includes any data sources already in the table, that are not in - * COMPLETE status, or any data sources that might have been added to the + * COMPLETE or IN_PROGRESS status, or any data sources that might have been added to the * case, but are not in the datasources table. * * @return list of data source object ids that are stale. @@ -368,7 +376,7 @@ public final class ImageGalleryController { // collect all data sources already in the table, that are not yet COMPLETE knownDataSourceIds.entrySet().stream().forEach((Map.Entry t) -> { DrawableDbBuildStatusEnum status = t.getValue(); - if (DrawableDbBuildStatusEnum.COMPLETE != status) { + if ((status != DrawableDbBuildStatusEnum.COMPLETE) && (status != DrawableDbBuildStatusEnum.IN_PROGRESS)) { staleDataSourceIds.add(t.getKey()); } }); @@ -451,12 +459,12 @@ public final class ImageGalleryController { * * @throws TskCoreException */ - public boolean hasFilesWithNoMimetype(Content datasource) throws TskCoreException { + public boolean hasFilesWithNoMimeType(long dataSourceId) throws TskCoreException { // There are some special files/attributes in the root folder, like $BadClus:$Bad and $Security:$SDS // The IngestTasksScheduler does not push them down to the ingest modules, // and hence they do not have any assigned mimetype - String whereClause = "data_source_obj_id = " + datasource.getId() + String whereClause = "data_source_obj_id = " + dataSourceId + " AND ( meta_type = " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue() + ")" + " AND ( mime_type IS NULL )" + " AND ( meta_addr >= 32 ) " @@ -465,6 +473,15 @@ public final class ImageGalleryController { return sleuthKitCase.countFilesWhere(whereClause) > 0; } + + public boolean hasFilesWithMimeType(long dataSourceId) throws TskCoreException { + + String whereClause = "data_source_obj_id = " + dataSourceId + + " AND ( meta_type = " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue() + ")" + + " AND ( mime_type IS NOT NULL )"; + + return sleuthKitCase.countFilesWhere(whereClause) > 0; + } synchronized private void shutDownDBExecutor() { if (dbExecutor != null) { @@ -645,12 +662,6 @@ public final class ImageGalleryController { "BulkTask.stopCopy.status=Stopping copy to drawable db task.", "BulkTask.errPopulating.errMsg=There was an error populating Image Gallery database."}) abstract static class BulkTransferTask extends BackgroundTask { - - static private final String FILE_EXTENSION_CLAUSE - = "(extension LIKE '" //NON-NLS - + String.join("' OR extension LIKE '", FileTypeUtils.getAllSupportedExtensions()) //NON-NLS - + "') "; - static private final String MIMETYPE_CLAUSE = "(mime_type LIKE '" //NON-NLS + String.join("' OR mime_type LIKE '", FileTypeUtils.getAllSupportedMimeTypes()) //NON-NLS @@ -679,20 +690,16 @@ public final class ImageGalleryController { = DATASOURCE_CLAUSE + " AND ( meta_type = " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue() + ")" + " AND ( " - + //grab files with supported extension - FILE_EXTENSION_CLAUSE //grab files with supported mime-types - + " OR " + MIMETYPE_CLAUSE //NON-NLS + + MIMETYPE_CLAUSE //NON-NLS //grab files with image or video mime-types even if we don't officially support them + " OR mime_type LIKE 'video/%' OR mime_type LIKE 'image/%' )"; //NON-NLS } /** * Do any cleanup for this task. - * - * @param success true if the transfer was successful */ - abstract void cleanup(boolean success); + abstract void cleanup(); abstract void processFile(final AbstractFile f, DrawableDB.DrawableTransaction tr, CaseDbTransaction caseDBTransaction) throws TskCoreException; @@ -715,17 +722,23 @@ public final class ImageGalleryController { DrawableDB.DrawableTransaction drawableDbTransaction = null; CaseDbTransaction caseDbTransaction = null; + boolean hasFilesWithNoMime = true; + boolean endedEarly = false; + try { - //grab all files with supported extension or detected mime types + // See if there are any files in the DS w/out a MIME TYPE + hasFilesWithNoMime = controller.hasFilesWithNoMimeType(dataSourceObjId); + + //grab all files with detected mime types final List files = getFiles(); progressHandle.switchToDeterminate(files.size()); taskDB.insertOrUpdateDataSource(dataSourceObjId, DrawableDB.DrawableDbBuildStatusEnum.IN_PROGRESS); updateProgress(0.0); - taskCompletionStatus = true; int workDone = 0; + // Cycle through all of the files returned and call processFile on each //do in transaction drawableDbTransaction = taskDB.beginTransaction(); @@ -743,8 +756,9 @@ public final class ImageGalleryController { if (isCancelled() || Thread.interrupted()) { logger.log(Level.WARNING, "Task cancelled or interrupted: not all contents may be transfered to drawable database."); //NON-NLS - taskCompletionStatus = false; + endedEarly = true; progressHandle.finish(); + break; } @@ -798,27 +812,25 @@ public final class ImageGalleryController { progressHandle.progress(Bundle.BulkTask_stopCopy_status()); logger.log(Level.WARNING, "Stopping copy to drawable db task. Failed to transfer all database contents", ex); //NON-NLS MessageNotifyUtil.Notify.warn(Bundle.BulkTask_errPopulating_errMsg(), ex.getMessage()); - cleanup(false); + endedEarly = true; } finally { progressHandle.finish(); + // Mark to REBUILT_STALE if some files didnt' have MIME (ingest was still ongoing) or + // if there was cancellation or errors DrawableDB.DrawableDbBuildStatusEnum datasourceDrawableDBStatus - = (taskCompletionStatus) - ? DrawableDB.DrawableDbBuildStatusEnum.COMPLETE - : DrawableDB.DrawableDbBuildStatusEnum.DEFAULT; + = ((hasFilesWithNoMime == true) || (endedEarly == true)) + ? DrawableDB.DrawableDbBuildStatusEnum.REBUILT_STALE + : DrawableDB.DrawableDbBuildStatusEnum.COMPLETE; taskDB.insertOrUpdateDataSource(dataSourceObjId, datasourceDrawableDBStatus); updateMessage(""); updateProgress(-1.0); } - cleanup(taskCompletionStatus); + cleanup(); } abstract ProgressHandle getInitialProgressHandle(); - - protected void setTaskCompletionStatus(boolean status) { - taskCompletionStatus = status; - } } /** @@ -839,7 +851,7 @@ public final class ImageGalleryController { } @Override - protected void cleanup(boolean success) { + protected void cleanup() { taskDB.freeFileMetaDataCache(); // at the end of the task, set the stale status based on the // cumulative status of all data sources @@ -853,12 +865,9 @@ public final class ImageGalleryController { if (known) { taskDB.removeFile(f.getId(), tr); //remove known files } else { - // if mimetype of the file hasn't been ascertained, ingest might not have completed yet. - if (null == f.getMIMEType()) { - // set to false to force the DB to be marked as stale - this.setTaskCompletionStatus(false); - } //supported mimetype => analyzed - else if (FileTypeUtils.hasDrawableMIMEType(f)) { + // NOTE: Files are being processed because they have the right MIME type, + // so we do not need to worry about this calculating them + if (FileTypeUtils.hasDrawableMIMEType(f)) { taskDB.updateFile(DrawableFile.create(f, true, false), tr, caseDbTransaction); } //unsupported mimtype => analyzed but shouldn't include else { diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java index 1ab7caf246..a9899cc048 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java @@ -329,10 +329,14 @@ public class ImageGalleryModule { if (((AutopsyEvent) evt).getSourceType() == AutopsyEvent.SourceType.LOCAL) { if (controller.isListeningEnabled()) { - DataSourceAnalysisStartedEvent dataSourceAnalysisStartedEvent = (DataSourceAnalysisStartedEvent) evt; + DataSourceAnalysisStartedEvent dataSourceAnalysisStartedEvent = (DataSourceAnalysisStartedEvent) evt; Content dataSource = dataSourceAnalysisStartedEvent.getDataSource(); - - controller.getDatabase().insertOrUpdateDataSource(dataSource.getId(), DrawableDB.DrawableDbBuildStatusEnum.IN_PROGRESS); + + DrawableDB drawableDb = controller.getDatabase(); + // Don't update status if it is is already marked as COMPLETE + if (drawableDb.getDataSourceDbBuildStatus(dataSource.getId()) != DrawableDB.DrawableDbBuildStatusEnum.COMPLETE) { + drawableDb.insertOrUpdateDataSource(dataSource.getId(), DrawableDB.DrawableDbBuildStatusEnum.IN_PROGRESS); + } } } } else if (eventType == IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED) { @@ -342,12 +346,18 @@ public class ImageGalleryModule { DataSourceAnalysisCompletedEvent dataSourceAnalysisCompletedEvent = (DataSourceAnalysisCompletedEvent) evt; Content dataSource = dataSourceAnalysisCompletedEvent.getDataSource(); - DrawableDB.DrawableDbBuildStatusEnum datasourceDrawableDBStatus = - controller.hasFilesWithNoMimetype(dataSource) ? - DrawableDB.DrawableDbBuildStatusEnum.DEFAULT : - DrawableDB.DrawableDbBuildStatusEnum.COMPLETE; + DrawableDB drawableDb = controller.getDatabase(); + if (drawableDb.getDataSourceDbBuildStatus(dataSource.getId()) == DrawableDB.DrawableDbBuildStatusEnum.IN_PROGRESS) { - controller.getDatabase().insertOrUpdateDataSource(dataSource.getId(), datasourceDrawableDBStatus); + // If at least one file in CaseDB has mime type, then set to COMPLETE + // Otherwise, back to UNKNOWN since we assume file type module was not run + DrawableDB.DrawableDbBuildStatusEnum datasourceDrawableDBStatus = + controller.hasFilesWithMimeType(dataSource.getId()) ? + DrawableDB.DrawableDbBuildStatusEnum.COMPLETE : + DrawableDB.DrawableDbBuildStatusEnum.UNKNOWN; + + controller.getDatabase().insertOrUpdateDataSource(dataSource.getId(), datasourceDrawableDBStatus); + } } return; } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java index 606cb0c369..34c102e74b 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java @@ -192,11 +192,11 @@ public final class OpenAction extends CallableSystemAction { addFXCallback(dataSourceStatusMapFuture, dataSourceStatusMap -> { - int numUnknown = 0; + int numStale = 0; for (Map.Entry entry : dataSourceStatusMap.entrySet()) { DrawableDbBuildStatusEnum status = entry.getValue(); - if (DrawableDbBuildStatusEnum.UNKNOWN == status) { - numUnknown++; + if ((DrawableDbBuildStatusEnum.UNKNOWN == status) || (DrawableDbBuildStatusEnum.REBUILT_STALE == status)) { + numStale++; } } @@ -204,7 +204,7 @@ public final class OpenAction extends CallableSystemAction { // If there are data sources in the "UNKNOWN" state, then we MAY need to rebuild. // Or not because single-user cases can have UNKNOWN states if ingest was not run yet - if (numUnknown > 0) { + if (numStale > 0) { /* A rebuild should occur if either * - Multi-user case and at least one DS is UNKNOWN * - Single-user case and case listening has been disabled @@ -254,7 +254,7 @@ public final class OpenAction extends CallableSystemAction { } else { // single user and listening is enabled // give them a dialog to enable modules if no data sources have been analyzed - if (numUnknown == dataSourceStatusMap.size()) { + if (numStale == dataSourceStatusMap.size()) { Alert alert = new Alert(Alert.AlertType.WARNING, Bundle.OpenAction_notAnalyzedDlg_msg(), ButtonType.OK); alert.setTitle(Bundle.OpenAction_stale_confDlg_title()); alert.initModality(Modality.APPLICATION_MODAL); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index 4b9fde00f7..122ebbd75a 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -180,8 +180,8 @@ public final class DrawableDB { public enum DrawableDbBuildStatusEnum { UNKNOWN, /// no known status - not yet analyzed IN_PROGRESS, /// ingest or db rebuild is in progress - COMPLETE, /// All files in the data source have had file type detected - DEFAULT; /// Not all files in the data source have had file type detected + COMPLETE, /// At least one file in the data source had a MIME type. Ingest filters may have been applied. + REBUILT_STALE; /// data source was rebuilt, but MIME types were missing during rebuild } private void dbWriteLock() { @@ -1209,6 +1209,15 @@ public final class DrawableDB { } return map; } + + + public DrawableDbBuildStatusEnum getDataSourceDbBuildStatus(Long dataSourceId) throws TskCoreException { + Map statusMap = getDataSourceDbBuildStatus(); + if (statusMap.containsKey(dataSourceId) == false) { + throw new TskCoreException("Data Source ID not found: " + dataSourceId); + } + return statusMap.get(dataSourceId); + } /** * Insert/update given data source object id and it's DB rebuild status in @@ -1554,16 +1563,9 @@ public final class DrawableDB { } public long countAllFiles() throws TskCoreException { - return countAllFiles(null); + return countFilesWhere(" 1 "); } - public long countAllFiles(DataSource dataSource) throws TskCoreException { - if (null != dataSource) { - return countFilesWhere(" data_source_obj_id = "); - } else { - return countFilesWhere(" 1 "); - } - } /** * delete the row with obj_id = id. From 938d5128d0358d6c576cf01bc99f53e90a82d536 Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 28 Nov 2018 12:28:40 -0500 Subject: [PATCH 05/12] Revert changes to AbstractFilePropertyType public enum. --- .../datamodel/AbstractAbstractFileNode.java | 82 +++++++++++-------- .../autopsy/datamodel/Bundle_ja.properties | 8 ++ 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index e5016b89ec..09c60b9f5c 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -107,7 +107,7 @@ public abstract class AbstractAbstractFileNode extends A static { //Initialize this pool only once! This will be used by every instance of AAFN //to do their heavy duty SCO column and translation updates. - translationPool = Executors.newFixedThreadPool(MAX_POOL_SIZE, + translationPool = Executors.newFixedThreadPool(MAX_POOL_SIZE, new ThreadFactoryBuilder().setNameFormat("translation-task-thread-%d").build()); } @@ -191,8 +191,8 @@ public abstract class AbstractAbstractFileNode extends A Score value = scorePropAndDescr.getLeft(); String descr = scorePropAndDescr.getRight(); CorrelationAttributeInstance attribute = getCorrelationAttributeInstance(); - updateSheet(new NodeProperty<>(SCORE.toString(),SCORE.toString(),descr,value), - new NodeProperty<>(COMMENT.toString(),COMMENT.toString(),NO_DESCR,getCommentProperty(tags, attribute)) + updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value), + new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute)) ); } } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { @@ -203,8 +203,8 @@ public abstract class AbstractAbstractFileNode extends A Score value = scorePropAndDescr.getLeft(); String descr = scorePropAndDescr.getRight(); CorrelationAttributeInstance attribute = getCorrelationAttributeInstance(); - updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(),descr,value), - new NodeProperty<>(COMMENT.toString(), COMMENT.toString(),NO_DESCR,getCommentProperty(tags, attribute)) + updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value), + new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute)) ); } } else if (eventType.equals(Case.Events.CR_COMMENT_CHANGED.toString())) { @@ -212,14 +212,14 @@ public abstract class AbstractAbstractFileNode extends A if (event.getContentID() == content.getId()) { List tags = getContentTagsFromDatabase(); CorrelationAttributeInstance attribute = getCorrelationAttributeInstance(); - updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(),NO_DESCR,getCommentProperty(tags, attribute))); + updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute))); } - /* - * Data that was being computed in the background task. Kicked off by a - * call to createSheet(). - */ + /* + * Data that was being computed in the background task. Kicked off + * by a call to createSheet(). + */ } else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) { - updateSheet(new NodeProperty<>(TRANSLATION.toString(),TRANSLATION.toString(),NO_DESCR,evt.getNewValue())); + updateSheet(new NodeProperty<>(TRANSLATION.toString(), TRANSLATION.toString(), NO_DESCR, evt.getNewValue())); } }; /** @@ -251,9 +251,9 @@ public abstract class AbstractAbstractFileNode extends A Sheet visibleSheet = this.getSheet(); Sheet.Set visibleSheetSet = visibleSheet.get(Sheet.PROPERTIES); Property[] visibleProps = visibleSheetSet.getProperties(); - for(NodeProperty newProp: newProps) { - for(int i = 0; i < visibleProps.length; i++) { - if(visibleProps[i].getName().equals(newProp.getName())) { + for (NodeProperty newProp : newProps) { + for (int i = 0; i < visibleProps.length; i++) { + if (visibleProps[i].getName().equals(newProp.getName())) { visibleProps[i] = newProp; } } @@ -281,10 +281,10 @@ public abstract class AbstractAbstractFileNode extends A newProperties.forEach((property) -> { sheetSet.put(property); }); - + /* - * Submit the translation task ASAP. Keep all weak references so - * this task doesn't block the ability of this node to be GC'd. + * Submit the translation task ASAP. Keep all weak references so this + * task doesn't block the ability of this node to be GC'd. */ translationPool.submit(new TranslationTask(new WeakReference<>(this), weakPcl)); @@ -304,8 +304,16 @@ public abstract class AbstractAbstractFileNode extends A "AbstractAbstractFileNode.sizeColLbl=Size", "AbstractAbstractFileNode.flagsDirColLbl=Flags(Dir)", "AbstractAbstractFileNode.flagsMetaColLbl=Flags(Meta)", + "AbstractAbstractFileNode.modeColLbl=Mode", + "AbstractAbstractFileNode.useridColLbl=UserID", + "AbstractAbstractFileNode.groupidColLbl=GroupID", + "AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.", + "AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.", + "AbstractAbstractFileNode.typeDirColLbl=Type(Dir)", + "AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)", "AbstractAbstractFileNode.knownColLbl=Known", "AbstractAbstractFileNode.md5HashColLbl=MD5 Hash", + "AbstractAbstractFileNode.objectId=Object ID", "AbstractAbstractFileNode.mimeType=MIME Type", "AbstractAbstractFileNode.extensionColLbl=Extension"}) public enum AbstractFilePropertyType { @@ -323,8 +331,16 @@ public abstract class AbstractAbstractFileNode extends A SIZE(AbstractAbstractFileNode_sizeColLbl()), FLAGS_DIR(AbstractAbstractFileNode_flagsDirColLbl()), FLAGS_META(AbstractAbstractFileNode_flagsMetaColLbl()), + MODE(AbstractAbstractFileNode_modeColLbl()), + USER_ID(AbstractAbstractFileNode_useridColLbl()), + GROUP_ID(AbstractAbstractFileNode_groupidColLbl()), + META_ADDR(AbstractAbstractFileNode_metaAddrColLbl()), + ATTR_ADDR(AbstractAbstractFileNode_attrAddrColLbl()), + TYPE_DIR(AbstractAbstractFileNode_typeDirColLbl()), + TYPE_META(AbstractAbstractFileNode_typeMetaColLbl()), KNOWN(AbstractAbstractFileNode_knownColLbl()), MD5HASH(AbstractAbstractFileNode_md5HashColLbl()), + ObjectID(AbstractAbstractFileNode_objectId()), MIMETYPE(AbstractAbstractFileNode_mimeType()), EXTENSION(AbstractAbstractFileNode_extensionColLbl()); @@ -345,12 +361,12 @@ public abstract class AbstractAbstractFileNode extends A */ private List> getProperties() { List> properties = new ArrayList<>(); - properties.add(new NodeProperty<>(NAME.toString(), NAME.toString(), NO_DESCR, getContentDisplayName(content))); + properties.add(new NodeProperty<>(NAME.toString(), NAME.toString(), NO_DESCR, getContentDisplayName(content))); /* * Initialize an empty place holder value. At the bottom, we kick off a * background task that promises to update these values. */ - + if (UserPreferences.displayTranslatedFileNames()) { properties.add(new NodeProperty<>(TRANSLATION.toString(), TRANSLATION.toString(), NO_DESCR, "")); } @@ -358,7 +374,7 @@ public abstract class AbstractAbstractFileNode extends A //SCO column prereq info.. List tags = getContentTagsFromDatabase(); CorrelationAttributeInstance attribute = getCorrelationAttributeInstance(); - + Pair scoreAndDescription = getScorePropertyAndDescription(tags); properties.add(new NodeProperty<>(SCORE.toString(), SCORE.toString(), scoreAndDescription.getRight(), scoreAndDescription.getLeft())); DataResultViewerTable.HasCommentStatus comment = getCommentProperty(tags, attribute); @@ -379,7 +395,7 @@ public abstract class AbstractAbstractFileNode extends A properties.add(new NodeProperty<>(MD5HASH.toString(), MD5HASH.toString(), NO_DESCR, StringUtils.defaultString(content.getMd5Hash()))); properties.add(new NodeProperty<>(MIMETYPE.toString(), MIMETYPE.toString(), NO_DESCR, StringUtils.defaultString(content.getMIMEType()))); properties.add(new NodeProperty<>(EXTENSION.toString(), EXTENSION.toString(), NO_DESCR, content.getNameExtension())); - + return properties; } @@ -421,7 +437,7 @@ public abstract class AbstractAbstractFileNode extends A return ""; } } - + @NbBundle.Messages({ "AbstractAbstractFileNode.createSheet.count.displayName=O", "AbstractAbstractFileNode.createSheet.count.noCentralRepo.description=Central repository was not enabled when this column was populated", @@ -447,7 +463,7 @@ public abstract class AbstractAbstractFileNode extends A return Pair.of(count, description); } - + @NbBundle.Messages({ "AbstractAbstractFileNode.createSheet.score.displayName=S", "AbstractAbstractFileNode.createSheet.notableFile.description=File recognized as notable.", @@ -483,7 +499,7 @@ public abstract class AbstractAbstractFileNode extends A } return Pair.of(score, description); } - + @NbBundle.Messages({ "AbstractAbstractFileNode.createSheet.comment.displayName=C"}) HasCommentStatus getCommentProperty(List tags, CorrelationAttributeInstance attribute) { @@ -506,10 +522,10 @@ public abstract class AbstractAbstractFileNode extends A } return status; } - + /** - * Translates this nodes content name. Doesn't attempt translation if - * the name is in english or if there is now translation service available. + * Translates this nodes content name. Doesn't attempt translation if the + * name is in english or if there is now translation service available. */ String getTranslatedFileName() { //If already in complete English, don't translate. @@ -542,7 +558,7 @@ public abstract class AbstractAbstractFileNode extends A } return ""; } - + /** * Get all tags from the case database that are associated with the file * @@ -565,7 +581,7 @@ public abstract class AbstractAbstractFileNode extends A } return attribute; } - + static String getContentPath(AbstractFile file) { try { return file.getUniquePath(); @@ -575,7 +591,7 @@ public abstract class AbstractAbstractFileNode extends A } } - static String getContentDisplayName(AbstractFile file) { + static String getContentDisplayName(AbstractFile file) { String name = file.getName(); switch (name) { case "..": @@ -593,9 +609,9 @@ public abstract class AbstractAbstractFileNode extends A * @param map map with preserved ordering, where property names/values * are put * @param content The content to get properties for. - * - * TODO JIRA-4421: Deprecate this method and resolve warnings that appear - * in other locations. + * + * TODO JIRA-4421: Deprecate this method and resolve warnings that appear in + * other locations. */ static public void fillPropertyMap(Map map, AbstractFile content) { map.put(NAME.toString(), getContentDisplayName(content)); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle_ja.properties index 34a1274c32..2f91dfb27a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle_ja.properties @@ -6,6 +6,9 @@ AbstractAbstractFileNode.changeTimeColLbl=\u5909\u66f4\u65e5\u6642 AbstractAbstractFileNode.accessTimeColLbl=\u30a2\u30af\u30bb\u30b9\u65e5\u6642 AbstractAbstractFileNode.createdTimeColLbl=\u4f5c\u6210\u65e5\u6642 AbstractAbstractFileNode.sizeColLbl=\u30b5\u30a4\u30ba +AbstractAbstractFileNode.modeColLbl=\u30e2\u30fc\u30c9 +AbstractAbstractFileNode.useridColLbl=\u30e6\u30fc\u30b6ID +AbstractAbstractFileNode.groupidColLbl=\u30b0\u30eb\u30fc\u30d7ID AbstractAbstractFileNode.knownColLbl=\u65e2\u77e5 AbstractAbstractFileNode.md5HashColLbl=MD5\u30cf\u30c3\u30b7\u30e5 AbstractContentChildren.CreateTSKNodeVisitor.exception.noNodeMsg=\u6307\u5b9a\u3055\u308c\u305fSleuthkitItem\u306e\u30ce\u30fc\u30c9\u304c\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u307e\u305b\u3093 @@ -195,6 +198,10 @@ TagsNode.displayName.text=\u30bf\u30b0 TagsNode.createSheet.name.name=\u540d\u524d AbstractAbstractFileNode.flagsDirColLbl=\u30d5\u30e9\u30b0\uff08\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\uff09 AbstractAbstractFileNode.flagsMetaColLbl=\u30d5\u30e9\u30b0\uff08\u30e1\u30bf\u30c7\u30fc\u30bf\uff09 +AbstractAbstractFileNode.metaAddrColLbl=\u30e1\u30bf\u30c7\u30fc\u30bf\u30a2\u30c9\u30ec\u30b9 +AbstractAbstractFileNode.attrAddrColLbl=\u5c5e\u6027\u30a2\u30c9\u30ec\u30b9 +AbstractAbstractFileNode.typeDirColLbl=\u30bf\u30a4\u30d7\uff08\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\uff09 +AbstractAbstractFileNode.typeMetaColLbl=\u30bf\u30a4\u30d7\uff08\u30e1\u30bf\u30c7\u30fc\u30bf\uff09 ArtifactTypeNode.createSheet.childCnt.displayName=\u30c1\u30e3\u30a4\u30eb\u30c9\u6570 TagsNode.createSheet.name.displayName=\u540d\u524d ViewsNode.name.text=\u30d3\u30e5\u30fc @@ -231,6 +238,7 @@ KeywordHits.createSheet.numChildren.name=\u30c1\u30e3\u30a4\u30eb\u30c9\u6570 KeywordHits.createSheet.numChildren.displayName=\u30c1\u30e3\u30a4\u30eb\u30c9\u6570 KeywordHits.simpleLiteralSearch.text=\u30b7\u30f3\u30b0\u30eb\u30ea\u30c6\u30e9\u30eb\u691c\u7d22 KeywordHits.singleRegexSearch.text=\u30b7\u30f3\u30b0\u30eb\u6b63\u898f\u8868\u73fe\u691c\u7d22 +AbstractAbstractFileNode.objectId=\u30aa\u30d6\u30b8\u30a7\u30af\u30c8ID ArtifactStringContent.getStr.artifactId.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8ID OpenReportAction.actionDisplayName=\u30ec\u30dd\u30fc\u30c8\u3092\u958b\u304f OpenReportAction.actionPerformed.MessageBoxTitle=\u5931\u6557\u30ec\u30dd\u30fc\u30c8\u3092\u958b\u304f From 8adb630c19c552420bd95bd8d35d6bd5e4ccd680 Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 28 Nov 2018 12:35:29 -0500 Subject: [PATCH 06/12] Revert formatting. --- .../datamodel/AbstractAbstractFileNode.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 09c60b9f5c..30e88cc923 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -191,8 +191,8 @@ public abstract class AbstractAbstractFileNode extends A Score value = scorePropAndDescr.getLeft(); String descr = scorePropAndDescr.getRight(); CorrelationAttributeInstance attribute = getCorrelationAttributeInstance(); - updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value), - new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute)) + updateSheet(new NodeProperty<>(SCORE.toString(),SCORE.toString(),descr,value), + new NodeProperty<>(COMMENT.toString(),COMMENT.toString(),NO_DESCR,getCommentProperty(tags, attribute)) ); } } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { @@ -212,14 +212,14 @@ public abstract class AbstractAbstractFileNode extends A if (event.getContentID() == content.getId()) { List tags = getContentTagsFromDatabase(); CorrelationAttributeInstance attribute = getCorrelationAttributeInstance(); - updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute))); + updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(),NO_DESCR,getCommentProperty(tags, attribute))); } /* - * Data that was being computed in the background task. Kicked off - * by a call to createSheet(). + * Data that was being computed in the background task. Kicked off by a + * call to createSheet(). */ } else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) { - updateSheet(new NodeProperty<>(TRANSLATION.toString(), TRANSLATION.toString(), NO_DESCR, evt.getNewValue())); + updateSheet(new NodeProperty<>(TRANSLATION.toString(),TRANSLATION.toString(),NO_DESCR,evt.getNewValue())); } }; /** @@ -251,9 +251,9 @@ public abstract class AbstractAbstractFileNode extends A Sheet visibleSheet = this.getSheet(); Sheet.Set visibleSheetSet = visibleSheet.get(Sheet.PROPERTIES); Property[] visibleProps = visibleSheetSet.getProperties(); - for (NodeProperty newProp : newProps) { - for (int i = 0; i < visibleProps.length; i++) { - if (visibleProps[i].getName().equals(newProp.getName())) { + for(NodeProperty newProp: newProps) { + for(int i = 0; i < visibleProps.length; i++) { + if(visibleProps[i].getName().equals(newProp.getName())) { visibleProps[i] = newProp; } } @@ -283,8 +283,8 @@ public abstract class AbstractAbstractFileNode extends A }); /* - * Submit the translation task ASAP. Keep all weak references so this - * task doesn't block the ability of this node to be GC'd. + * Submit the translation task ASAP. Keep all weak references so + * this task doesn't block the ability of this node to be GC'd. */ translationPool.submit(new TranslationTask(new WeakReference<>(this), weakPcl)); @@ -524,8 +524,8 @@ public abstract class AbstractAbstractFileNode extends A } /** - * Translates this nodes content name. Doesn't attempt translation if the - * name is in english or if there is now translation service available. + * Translates this nodes content name. Doesn't attempt translation if + * the name is in english or if there is now translation service available. */ String getTranslatedFileName() { //If already in complete English, don't translate. @@ -591,7 +591,7 @@ public abstract class AbstractAbstractFileNode extends A } } - static String getContentDisplayName(AbstractFile file) { + static String getContentDisplayName(AbstractFile file) { String name = file.getName(); switch (name) { case "..": @@ -610,8 +610,8 @@ public abstract class AbstractAbstractFileNode extends A * are put * @param content The content to get properties for. * - * TODO JIRA-4421: Deprecate this method and resolve warnings that appear in - * other locations. + * TODO JIRA-4421: Deprecate this method and resolve warnings that appear + * in other locations. */ static public void fillPropertyMap(Map map, AbstractFile content) { map.put(NAME.toString(), getContentDisplayName(content)); From 7c4a3aa31682c740d1efd25308cada20b0eddf5f Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 28 Nov 2018 12:50:35 -0500 Subject: [PATCH 07/12] Reverting more formatting changes. --- .../datamodel/AbstractAbstractFileNode.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 30e88cc923..98cae1ae0d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -107,7 +107,7 @@ public abstract class AbstractAbstractFileNode extends A static { //Initialize this pool only once! This will be used by every instance of AAFN //to do their heavy duty SCO column and translation updates. - translationPool = Executors.newFixedThreadPool(MAX_POOL_SIZE, + translationPool = Executors.newFixedThreadPool(MAX_POOL_SIZE, new ThreadFactoryBuilder().setNameFormat("translation-task-thread-%d").build()); } @@ -203,8 +203,8 @@ public abstract class AbstractAbstractFileNode extends A Score value = scorePropAndDescr.getLeft(); String descr = scorePropAndDescr.getRight(); CorrelationAttributeInstance attribute = getCorrelationAttributeInstance(); - updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value), - new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute)) + updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(),descr,value), + new NodeProperty<>(COMMENT.toString(), COMMENT.toString(),NO_DESCR,getCommentProperty(tags, attribute)) ); } } else if (eventType.equals(Case.Events.CR_COMMENT_CHANGED.toString())) { @@ -215,8 +215,8 @@ public abstract class AbstractAbstractFileNode extends A updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(),NO_DESCR,getCommentProperty(tags, attribute))); } /* - * Data that was being computed in the background task. Kicked off by a - * call to createSheet(). + * Data that was being computed in the background task. Kicked off + * by a call to createSheet(). */ } else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) { updateSheet(new NodeProperty<>(TRANSLATION.toString(),TRANSLATION.toString(),NO_DESCR,evt.getNewValue())); @@ -281,7 +281,7 @@ public abstract class AbstractAbstractFileNode extends A newProperties.forEach((property) -> { sheetSet.put(property); }); - + /* * Submit the translation task ASAP. Keep all weak references so * this task doesn't block the ability of this node to be GC'd. @@ -361,12 +361,12 @@ public abstract class AbstractAbstractFileNode extends A */ private List> getProperties() { List> properties = new ArrayList<>(); - properties.add(new NodeProperty<>(NAME.toString(), NAME.toString(), NO_DESCR, getContentDisplayName(content))); + properties.add(new NodeProperty<>(NAME.toString(), NAME.toString(), NO_DESCR, getContentDisplayName(content))); /* * Initialize an empty place holder value. At the bottom, we kick off a * background task that promises to update these values. */ - + if (UserPreferences.displayTranslatedFileNames()) { properties.add(new NodeProperty<>(TRANSLATION.toString(), TRANSLATION.toString(), NO_DESCR, "")); } @@ -374,7 +374,7 @@ public abstract class AbstractAbstractFileNode extends A //SCO column prereq info.. List tags = getContentTagsFromDatabase(); CorrelationAttributeInstance attribute = getCorrelationAttributeInstance(); - + Pair scoreAndDescription = getScorePropertyAndDescription(tags); properties.add(new NodeProperty<>(SCORE.toString(), SCORE.toString(), scoreAndDescription.getRight(), scoreAndDescription.getLeft())); DataResultViewerTable.HasCommentStatus comment = getCommentProperty(tags, attribute); @@ -395,7 +395,7 @@ public abstract class AbstractAbstractFileNode extends A properties.add(new NodeProperty<>(MD5HASH.toString(), MD5HASH.toString(), NO_DESCR, StringUtils.defaultString(content.getMd5Hash()))); properties.add(new NodeProperty<>(MIMETYPE.toString(), MIMETYPE.toString(), NO_DESCR, StringUtils.defaultString(content.getMIMEType()))); properties.add(new NodeProperty<>(EXTENSION.toString(), EXTENSION.toString(), NO_DESCR, content.getNameExtension())); - + return properties; } @@ -437,7 +437,7 @@ public abstract class AbstractAbstractFileNode extends A return ""; } } - + @NbBundle.Messages({ "AbstractAbstractFileNode.createSheet.count.displayName=O", "AbstractAbstractFileNode.createSheet.count.noCentralRepo.description=Central repository was not enabled when this column was populated", @@ -463,7 +463,7 @@ public abstract class AbstractAbstractFileNode extends A return Pair.of(count, description); } - + @NbBundle.Messages({ "AbstractAbstractFileNode.createSheet.score.displayName=S", "AbstractAbstractFileNode.createSheet.notableFile.description=File recognized as notable.", @@ -499,7 +499,7 @@ public abstract class AbstractAbstractFileNode extends A } return Pair.of(score, description); } - + @NbBundle.Messages({ "AbstractAbstractFileNode.createSheet.comment.displayName=C"}) HasCommentStatus getCommentProperty(List tags, CorrelationAttributeInstance attribute) { @@ -522,7 +522,7 @@ public abstract class AbstractAbstractFileNode extends A } return status; } - + /** * Translates this nodes content name. Doesn't attempt translation if * the name is in english or if there is now translation service available. @@ -558,7 +558,7 @@ public abstract class AbstractAbstractFileNode extends A } return ""; } - + /** * Get all tags from the case database that are associated with the file * @@ -581,7 +581,7 @@ public abstract class AbstractAbstractFileNode extends A } return attribute; } - + static String getContentPath(AbstractFile file) { try { return file.getUniquePath(); From 9c6a2b238337db974a3af492e3e83611cb2199ab Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 28 Nov 2018 12:52:56 -0500 Subject: [PATCH 08/12] Reverting more formatting changes. --- .../autopsy/datamodel/AbstractAbstractFileNode.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 98cae1ae0d..5fbfd140ec 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -215,8 +215,8 @@ public abstract class AbstractAbstractFileNode extends A updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(),NO_DESCR,getCommentProperty(tags, attribute))); } /* - * Data that was being computed in the background task. Kicked off - * by a call to createSheet(). + * Data that was being computed in the background task. Kicked off by a + * call to createSheet(). */ } else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) { updateSheet(new NodeProperty<>(TRANSLATION.toString(),TRANSLATION.toString(),NO_DESCR,evt.getNewValue())); @@ -609,7 +609,7 @@ public abstract class AbstractAbstractFileNode extends A * @param map map with preserved ordering, where property names/values * are put * @param content The content to get properties for. - * + * * TODO JIRA-4421: Deprecate this method and resolve warnings that appear * in other locations. */ From fcb37a584a4d5ab87e18c2ce6581d6ffe128d584 Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 28 Nov 2018 13:13:44 -0500 Subject: [PATCH 09/12] Removed unhelpful comment. --- .../sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 5fbfd140ec..162b3b978c 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -214,10 +214,6 @@ public abstract class AbstractAbstractFileNode extends A CorrelationAttributeInstance attribute = getCorrelationAttributeInstance(); updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(),NO_DESCR,getCommentProperty(tags, attribute))); } - /* - * Data that was being computed in the background task. Kicked off by a - * call to createSheet(). - */ } else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) { updateSheet(new NodeProperty<>(TRANSLATION.toString(),TRANSLATION.toString(),NO_DESCR,evt.getNewValue())); } From 62feed235013993844c2253e1554c6facb262e0a Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 28 Nov 2018 15:16:05 -0500 Subject: [PATCH 10/12] Fixed bug for multi-user case with no ingest run --- .../imagegallery/actions/OpenAction.java | 124 ++++++++++-------- 1 file changed, 66 insertions(+), 58 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java index 34c102e74b..32cce686e0 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java @@ -39,6 +39,7 @@ import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionReferences; import org.openide.awt.ActionRegistration; +import org.openide.util.Exceptions; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; @@ -193,75 +194,82 @@ public final class OpenAction extends CallableSystemAction { dataSourceStatusMap -> { int numStale = 0; + int numNoAnalysis = 0; for (Map.Entry entry : dataSourceStatusMap.entrySet()) { DrawableDbBuildStatusEnum status = entry.getValue(); - if ((DrawableDbBuildStatusEnum.UNKNOWN == status) || (DrawableDbBuildStatusEnum.REBUILT_STALE == status)) { + if (DrawableDbBuildStatusEnum.UNKNOWN == status) { + try { + // likely a data source analyzed on a remote node in multi-user case OR single-user case with listening off + if (controller.hasFilesWithMimeType(entry.getKey())) { + numStale++; + // likely a data source (local or remote) that has no analysis yet (note there is also IN_PROGRESS state) + } else { + numNoAnalysis++; + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error querying case database", ex); + } + } + // was already rebuilt, but wasn't complete at the end + else if (DrawableDbBuildStatusEnum.REBUILT_STALE == status) { numStale++; } } // NOTE: we are running on the fx thread. - // If there are data sources in the "UNKNOWN" state, then we MAY need to rebuild. - // Or not because single-user cases can have UNKNOWN states if ingest was not run yet + // If there are any that are STALE, give them a prompt to do so. if (numStale > 0) { - /* A rebuild should occur if either - * - Multi-user case and at least one DS is UNKNOWN - * - Single-user case and case listening has been disabled - */ - if ((controller.getAutopsyCase().getCaseType() == Case.CaseType.MULTI_USER_CASE) || - ((controller.getAutopsyCase().getCaseType() == Case.CaseType.SINGLE_USER_CASE) && - (controller.isListeningEnabled() == false))) { - - // See if user wants to rebuild, cancel out, or open as is - Alert alert = new Alert(Alert.AlertType.WARNING, - Bundle.OpenAction_stale_confDlg_msg(), - ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); - alert.initModality(Modality.APPLICATION_MODAL); - alert.setTitle(Bundle.OpenAction_stale_confDlg_title()); - GuiUtils.setDialogIcons(alert); - ButtonType answer = alert.showAndWait().orElse(ButtonType.CANCEL); - - if (answer == ButtonType.CANCEL) { - //just do nothing - don't open window - return; - } else if (answer == ButtonType.NO) { - // They don't want to rebuild. Just open the UI as is. - // NOTE: There could be no data.... - } else if (answer == ButtonType.YES) { - if (controller.getAutopsyCase().getCaseType() == Case.CaseType.SINGLE_USER_CASE) { - /* For a single-user case, we favor user - * experience, and rebuild the database as soon - * as Image Gallery is enabled for the case. - * - * Turning listening off is necessary in order - * to invoke the listener that will call - * controller.rebuildDB(); - */ - controller.setListeningEnabled(false); - controller.setListeningEnabled(true); - } else { - /* - * For a multi-user case, we favor overall - * performance and user experience, not every - * user may want to review images, so we rebuild - * the database only when a user launches Image - * Gallery. - */ - controller.rebuildDB(); - } - } - } - else { // single user and listening is enabled - // give them a dialog to enable modules if no data sources have been analyzed - if (numStale == dataSourceStatusMap.size()) { - Alert alert = new Alert(Alert.AlertType.WARNING, Bundle.OpenAction_notAnalyzedDlg_msg(), ButtonType.OK); - alert.setTitle(Bundle.OpenAction_stale_confDlg_title()); - alert.initModality(Modality.APPLICATION_MODAL); - alert.showAndWait(); - return; + // See if user wants to rebuild, cancel out, or open as is + Alert alert = new Alert(Alert.AlertType.WARNING, + Bundle.OpenAction_stale_confDlg_msg(), + ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setTitle(Bundle.OpenAction_stale_confDlg_title()); + GuiUtils.setDialogIcons(alert); + ButtonType answer = alert.showAndWait().orElse(ButtonType.CANCEL); + + if (answer == ButtonType.CANCEL) { + //just do nothing - don't open window + return; + } else if (answer == ButtonType.NO) { + // They don't want to rebuild. Just open the UI as is. + // NOTE: There could be no data.... + } else if (answer == ButtonType.YES) { + if (controller.getAutopsyCase().getCaseType() == Case.CaseType.SINGLE_USER_CASE) { + /* For a single-user case, we favor user + * experience, and rebuild the database as soon + * as Image Gallery is enabled for the case. + * + * Turning listening off is necessary in order + * to invoke the listener that will call + * controller.rebuildDB(); + */ + controller.setListeningEnabled(false); + controller.setListeningEnabled(true); + } else { + /* + * For a multi-user case, we favor overall + * performance and user experience, not every + * user may want to review images, so we rebuild + * the database only when a user launches Image + * Gallery. + */ + controller.rebuildDB(); } } + openTopComponent(); + return; + } + + // if there is no data to display, then let them know + if (numNoAnalysis == dataSourceStatusMap.size()) { + // give them a dialog to enable modules if no data sources have been analyzed + Alert alert = new Alert(Alert.AlertType.WARNING, Bundle.OpenAction_notAnalyzedDlg_msg(), ButtonType.OK); + alert.setTitle(Bundle.OpenAction_stale_confDlg_title()); + alert.initModality(Modality.APPLICATION_MODAL); + alert.showAndWait(); + return; } // otherwise, lets open the UI From 48ac8d11bf557598f3406415328677006b48f863 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 28 Nov 2018 15:53:09 -0500 Subject: [PATCH 11/12] ensure stale IDs are only if there is data that has been analyzed. Refined stale message --- .../imagegallery/ImageGalleryController.java | 40 ++++++++++++++----- .../imagegallery/ImageGalleryModule.java | 2 +- .../imagegallery/actions/OpenAction.java | 2 + .../autopsy/imagegallery/gui/StatusBar.fxml | 2 +- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 1efa5ddad9..a0ecbee39f 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -51,6 +51,7 @@ import javax.annotation.Nonnull; import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; import org.netbeans.api.progress.ProgressHandle; import org.openide.util.Cancellable; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; @@ -99,7 +100,7 @@ public final class ImageGalleryController { private final SimpleBooleanProperty listeningEnabled = new SimpleBooleanProperty(false); @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - private final ReadOnlyBooleanWrapper stale = new ReadOnlyBooleanWrapper(false); + private final ReadOnlyBooleanWrapper isCaseStale = new ReadOnlyBooleanWrapper(false); private final ReadOnlyBooleanWrapper metaDataCollapsed = new ReadOnlyBooleanWrapper(false); private final SimpleDoubleProperty thumbnailSizeProp = new SimpleDoubleProperty(100); @@ -171,14 +172,14 @@ public final class ImageGalleryController { * @param b True if any data source in the case is stale */ @ThreadConfined(type = ThreadConfined.ThreadType.ANY) - void setStale(Boolean b) { + void setCaseStale(Boolean b) { Platform.runLater(() -> { - stale.set(b); + isCaseStale.set(b); }); } public ReadOnlyBooleanProperty staleProperty() { - return stale.getReadOnlyProperty(); + return isCaseStale.getReadOnlyProperty(); } /** @@ -186,8 +187,8 @@ public final class ImageGalleryController { * @return true if any data source in the case is stale */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - boolean isStale() { - return stale.get(); + boolean isCaseStale() { + return isCaseStale.get(); } ImageGalleryController(@Nonnull Case newCase) throws TskCoreException { @@ -205,7 +206,7 @@ public final class ImageGalleryController { tagsManager.registerListener(categoryManager); hashSetManager = new HashSetManager(drawableDB); - setStale(isDataSourcesTableStale()); + setCaseStale(isDataSourcesTableStale()); dbExecutor = getNewDBExecutor(); @@ -376,9 +377,27 @@ public final class ImageGalleryController { // collect all data sources already in the table, that are not yet COMPLETE knownDataSourceIds.entrySet().stream().forEach((Map.Entry t) -> { DrawableDbBuildStatusEnum status = t.getValue(); - if ((status != DrawableDbBuildStatusEnum.COMPLETE) && (status != DrawableDbBuildStatusEnum.IN_PROGRESS)) { - staleDataSourceIds.add(t.getKey()); + switch (status) { + case COMPLETE: + case IN_PROGRESS: + // not stale + break; + case REBUILT_STALE: + staleDataSourceIds.add(t.getKey()); + break; + case UNKNOWN: + try { + // stale if there are files in CaseDB with MIME types + if (hasFilesWithMimeType(t.getKey())) { + staleDataSourceIds.add(t.getKey()); + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting MIME types", ex); + } + + break; } + }); // collect any new data sources in the case. @@ -393,7 +412,6 @@ public final class ImageGalleryController { logger.log(Level.SEVERE, "Image Gallery failed to check if datasources table is stale.", ex); return staleDataSourceIds; } - } /** @@ -855,7 +873,7 @@ public final class ImageGalleryController { taskDB.freeFileMetaDataCache(); // at the end of the task, set the stale status based on the // cumulative status of all data sources - controller.setStale(controller.isDataSourcesTableStale()); + controller.setCaseStale(controller.isDataSourcesTableStale()); } @Override diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java index a9899cc048..ad7ebc72f5 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java @@ -365,7 +365,7 @@ public class ImageGalleryModule { if (((AutopsyEvent) evt).getSourceType() == AutopsyEvent.SourceType.REMOTE) { // A remote node added a new data source and just finished ingest on it. //drawable db is stale, and if ImageGallery is open, ask user what to do - controller.setStale(true); + controller.setCaseStale(true); if (controller.isListeningEnabled()) { SwingUtilities.invokeLater(() -> { if (ImageGalleryTopComponent.isImageGalleryOpen()) { diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java index 32cce686e0..4cf4f10b25 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java @@ -195,6 +195,8 @@ public final class OpenAction extends CallableSystemAction { int numStale = 0; int numNoAnalysis = 0; + // NOTE: There is some overlapping code here with Controller.getStaleDataSourceIds(). We could possibly just use + // that method to figure out stale and then do more simple stuff here to figure out if there is no data at all for (Map.Entry entry : dataSourceStatusMap.entrySet()) { DrawableDbBuildStatusEnum status = entry.getValue(); if (DrawableDbBuildStatusEnum.UNKNOWN == status) { diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/StatusBar.fxml b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/StatusBar.fxml index c0ee4488b1..386183a88a 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/StatusBar.fxml +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/StatusBar.fxml @@ -16,7 +16,7 @@ -