diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 4e35eebeed..d2233a93cb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -29,6 +29,7 @@ import java.awt.event.ActionListener; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.File; +import java.lang.reflect.InvocationTargetException; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; @@ -1214,9 +1215,7 @@ public class Case { /** * Update the GUI to to reflect the current case. */ - private static void updateGUIForCaseOpened(Case newCurrentCase) { - if (RuntimeProperties.runningWithGUI()) { - SwingUtilities.invokeLater(() -> { + private static void updateGUIForCaseOpened(Case newCurrentCase) { /* * If the case database was upgraded for a new schema and a * backup database was created, notify the user. @@ -1242,17 +1241,31 @@ public class Case { String path = entry.getValue(); boolean fileExists = (new File(path).isFile() || DriveUtils.driveExists(path)); if (!fileExists) { - int response = JOptionPane.showConfirmDialog( - mainFrame, - NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", path), - NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.title"), - JOptionPane.YES_NO_OPTION); - if (response == JOptionPane.YES_OPTION) { - MissingImageDialog.makeDialog(obj_id, caseDb); - } else { - logger.log(Level.SEVERE, "User proceeding with missing image files"); //NON-NLS + try { + // Using invokeAndWait means that the dialog will + // open on the EDT but this thread will wait for an + // answer. Using invokeLater would cause this loop to + // end before all of the dialogs appeared. + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + int response = JOptionPane.showConfirmDialog( + mainFrame, + NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", path), + NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.title"), + JOptionPane.YES_NO_OPTION); + if (response == JOptionPane.YES_OPTION) { + MissingImageDialog.makeDialog(obj_id, caseDb); + } else { + logger.log(Level.SEVERE, "User proceeding with missing image files"); //NON-NLS - } + } + } + + }); + } catch (InterruptedException | InvocationTargetException ex) { + logger.log(Level.SEVERE, "Failed to show missing image confirmation dialog", ex); //NON-NLS + } } } @@ -1270,14 +1283,16 @@ public class Case { CallableSystemAction.get(CommonAttributeSearchAction.class).setEnabled(true); CallableSystemAction.get(OpenOutputFolderAction.class).setEnabled(false); CallableSystemAction.get(OpenDiscoveryAction.class).setEnabled(true); - - /* - * Add the case to the recent cases tracker that supplies a list - * of recent cases to the recent cases menu item and the - * open/create case dialog. - */ - RecentCases.getInstance().addRecentCase(newCurrentCase.getDisplayName(), newCurrentCase.getMetadata().getFilePath().toString()); - + + /* + * Add the case to the recent cases tracker that supplies a list + * of recent cases to the recent cases menu item and the + * open/create case dialog. + */ + RecentCases.getInstance().addRecentCase(newCurrentCase.getDisplayName(), newCurrentCase.getMetadata().getFilePath().toString()); + final boolean hasData = newCurrentCase.hasData(); + + SwingUtilities.invokeLater(() -> { /* * Open the top components (windows within the main application * window). @@ -1286,7 +1301,7 @@ public class Case { * opened via the DirectoryTreeTopComponent 'propertyChange()' * method on a DATA_SOURCE_ADDED event. */ - if (newCurrentCase.hasData()) { + if (hasData) { CoreComponentControl.openCoreWindows(); } else { //ensure that the DirectoryTreeTopComponent is open so that it's listener can open the core windows including making it visible. @@ -1300,7 +1315,6 @@ public class Case { */ mainFrame.setTitle(newCurrentCase.getDisplayName() + " - " + getNameForTitle()); }); - } } /* diff --git a/Core/src/org/sleuthkit/autopsy/rejview/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/rejview/Bundle.properties-MERGED index c633b9838e..84a54f1640 100644 --- a/Core/src/org/sleuthkit/autopsy/rejview/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/rejview/Bundle.properties-MERGED @@ -15,6 +15,7 @@ RejTreeKeyView.columns.type=Type RejTreeKeyView.columns.value=Value RejTreeKeyView.failedToParse.keyName=FAILED TO PARSE KEY NAME RejTreeKeyView.metadataBorder.title=Metadata +RejTreeKeyView.template.dateTime=Modification Time: RejTreeKeyView.template.name=Name: RejTreeKeyView.template.numberOfSubkeys=Number of subkeys: RejTreeKeyView.template.numberOfValues=Number of values: diff --git a/Core/src/org/sleuthkit/autopsy/rejview/RejTreeKeyView.java b/Core/src/org/sleuthkit/autopsy/rejview/RejTreeKeyView.java index a74d4d26b4..6d2d55ba1a 100644 --- a/Core/src/org/sleuthkit/autopsy/rejview/RejTreeKeyView.java +++ b/Core/src/org/sleuthkit/autopsy/rejview/RejTreeKeyView.java @@ -28,6 +28,8 @@ import java.awt.Dimension; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import java.io.UnsupportedEncodingException; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.Iterator; import java.util.logging.Level; import javax.swing.BorderFactory; @@ -54,7 +56,8 @@ public final class RejTreeKeyView extends RejTreeNodeView { "RejTreeKeyView.valuesBorder.title=Values", "RejTreeKeyView.template.name=Name:", "RejTreeKeyView.template.numberOfSubkeys=Number of subkeys:", - "RejTreeKeyView.template.numberOfValues=Number of values:"}) + "RejTreeKeyView.template.numberOfValues=Number of values:", + "RejTreeKeyView.template.dateTime=Modification Time:"}) public RejTreeKeyView(RejTreeKeyNode node) { super(new BorderLayout()); @@ -62,6 +65,7 @@ public final class RejTreeKeyView extends RejTreeNodeView { * param 1 Name * param 2 Number of subkeys * param 3 Number of values + * param 4 Date/time */ String metadataTemplate = "" + Bundle.RejTreeKeyView_template_name() @@ -69,10 +73,13 @@ public final class RejTreeKeyView extends RejTreeNodeView { + Bundle.RejTreeKeyView_template_numberOfSubkeys() + " %2$d
" + Bundle.RejTreeKeyView_template_numberOfValues() - + " %3$d
"; + + " %3$d
" + + Bundle.RejTreeKeyView_template_dateTime() + + " %4$s
"; String keyName; int numSubkeys; int numValues; + String dateTime; try { keyName = node.getKey().getName(); @@ -95,7 +102,12 @@ public final class RejTreeKeyView extends RejTreeNodeView { numValues = -1; } - JLabel metadataLabel = new JLabel(String.format(metadataTemplate, keyName, numSubkeys, numValues), JLabel.LEFT); + Date date = new java.util.Date(node.getKey().getTimestamp().getTimeInMillis()); + SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); + sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT+0")); + dateTime = sdf.format(date); + + JLabel metadataLabel = new JLabel(String.format(metadataTemplate, keyName, numSubkeys, numValues, dateTime), JLabel.LEFT); metadataLabel.setBorder(BorderFactory.createTitledBorder(Bundle.RejTreeKeyView_metadataBorder_title())); metadataLabel.setVerticalAlignment(SwingConstants.TOP); diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 5951ac504c..b0d7fe08c3 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -742,7 +742,7 @@ class ExtractRegistry extends Extract { } else { results.get(0).addAttributes(bbattributes); } - for (Map.Entry userMap : userNameMap.entrySet()) { + for (Map.Entry userMap : getUserNameMap().entrySet()) { String sid = ""; try{ sid = (String)userMap.getKey(); @@ -1116,17 +1116,6 @@ class ExtractRegistry extends Extract { accountMgr.newOsAccountInstance(osAccount, (DataSource)dataSource, OsAccountInstance.OsAccountInstanceType.LAUNCHED); updateOsAccount(osAccount, userInfo, groupMap.get(userInfo.get(SID_KEY)), regAbstractFile); } - - // Get a mapping of user sids to user names and save globally so it can be used for other areas - // of the registry, ie: BAM key - try { - userNameMap = makeUserNameMap(dataSource); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to create OS Account user name map", ex); - // This is not the end of the world we will just continue without - // user names - userNameMap = new HashMap<>(); - } return true; } catch (FileNotFoundException ex) { logger.log(Level.WARNING, "Error finding the registry file.", ex); //NON-NLS @@ -1261,7 +1250,7 @@ class ExtractRegistry extends Extract { // We can add the S- back to the string that we split on since S- is a valid beginning of a User SID String fileNameSid[] = tokens[4].split("\\s+\\(S-"); String userSid = "S-" + fileNameSid[1].substring(0, fileNameSid[1].length() - 1); - String userName = userNameMap.get(userSid); + String userName = getUserNameMap().get(userSid); if (userName == null) { userName = userSid; } @@ -1738,6 +1727,28 @@ class ExtractRegistry extends Extract { return map; } + + /** + * Returns a mapping of user sids to user names. + * + * @return username man or empty list if none where found. + */ + private Map getUserNameMap() { + if(userNameMap == null) { + // Get a mapping of user sids to user names and save globally so it can be used for other areas + // of the registry, ie: BAM key + try { + userNameMap = makeUserNameMap(dataSource); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to create OS Account user name map", ex); + // This is not the end of the world we will just continue without + // user names + userNameMap = new HashMap<>(); + } + } + + return userNameMap; + } /** * Gets the attribute for the given type from the given artifact.