diff --git a/Core/manifest.mf b/Core/manifest.mf index 67d3366e22..5eb077ef30 100644 --- a/Core/manifest.mf +++ b/Core/manifest.mf @@ -2,7 +2,7 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.core/10 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml -OpenIDE-Module-Implementation-Version: 23 +OpenIDE-Module-Implementation-Version: 24 OpenIDE-Module-Requires: org.openide.windows.WindowManager AutoUpdate-Show-In-Client: true AutoUpdate-Essential-Module: true diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index b596512161..80bb473653 100644 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -17,7 +17,6 @@ file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbi file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar file.reference.sqlite-jdbc-3.8.11.jar=release/modules/ext/sqlite-jdbc-3.8.11.jar file.reference.StixLib.jar=release/modules/ext/StixLib.jar -file.reference.sleuthkit-postgresql-4.6.1.jar=release/modules/ext/sleuthkit-postgresql-4.6.1.jar file.reference.bcprov-jdk15on-1.54.jar=release/modules/ext/bcprov-jdk15on-1.54.jar file.reference.jackcess-2.1.8.jar=release/modules/ext/jackcess-2.1.8.jar file.reference.jackcess-encrypt-2.1.2.jar=release/modules/ext/jackcess-encrypt-2.1.2.jar @@ -30,7 +29,7 @@ file.reference.cxf-rt-transports-http-3.0.16.jar=release/modules/ext/cxf-rt-tran file.reference.fontbox-2.0.8.jar=release/modules/ext/fontbox-2.0.8.jar file.reference.pdfbox-2.0.8.jar=release/modules/ext/pdfbox-2.0.8.jar file.reference.pdfbox-tools-2.0.8.jar=release/modules/ext/pdfbox-tools-2.0.8.jar -file.reference.sleuthkit-postgresql-4.6.1.jar=release/modules/ext/sleuthkit-postgresql-4.6.1.jar +file.reference.sleuthkit-postgresql-4.6.2.jar=release/modules/ext/sleuthkit-postgresql-4.6.2.jar file.reference.tika-core-1.17.jar=release/modules/ext/tika-core-1.17.jar file.reference.tika-parsers-1.17.jar=release/modules/ext/tika-parsers-1.17.jar file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar @@ -47,5 +46,5 @@ nbm.homepage=http://www.sleuthkit.org/ nbm.module.author=Brian Carrier nbm.needs.restart=true source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar -spec.version.base=10.11 +spec.version.base=10.12 diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index dba056009d..e1da2d18d0 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -251,7 +251,7 @@ 3 - 1.1 + 1.2 @@ -413,8 +413,8 @@ release/modules/ext/metadata-extractor-2.10.1.jar - ext/sleuthkit-postgresql-4.6.1.jar - release/modules/ext/sleuthkit-postgresql-4.6.1.jar + ext/sleuthkit-postgresql-4.6.2.jar + release/modules/ext/sleuthkit-postgresql-4.6.2.jar ext/tika-core-1.17.jar diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 9c04508c1f..9494b3288a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -114,7 +114,6 @@ LocalFilesDSProcessor.toString.text=Logical Files LocalFilesPanel.contentType.text=LOCAL LocalFilesPanel.moduleErr=Module Error LocalFilesPanel.moduleErr.msg=A module caused an error listening to LocalFilesPanel updates. See log to determine which module. Some data could be incomplete. -MissingImageDialog.allDesc.text=All Supported Types MissingImageDialog.display.title=Search for Missing Image MissingImageDialog.confDlg.noFileSel.msg=No image file has been selected. Are you sure you\nwould like to exit without finding the image? MissingImageDialog.confDlg.noFileSel.title=Missing Image diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties index 8e405adec4..90849f4639 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties @@ -101,7 +101,6 @@ LocalFilesDSProcessor.toString.text=\u30ed\u30b8\u30ab\u30eb\u30d5\u30a1\u30a4\u LocalFilesPanel.contentType.text=\u30ed\u30fc\u30ab\u30eb LocalFilesPanel.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc LocalFilesPanel.moduleErr.msg=LocalFilesPanel\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 -MissingImageDialog.allDesc.text=\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u308b\u5168\u3066\u306e\u30bf\u30a4\u30d7 MissingImageDialog.display.title=\u6b20\u843d\u30a4\u30e1\u30fc\u30b8\u3092\u691c\u7d22 MissingImageDialog.confDlg.noFileSel.msg=\u30a4\u30e1\u30fc\u30b8\u30d5\u30a1\u30a4\u30eb\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u30a4\u30e1\u30fc\u30b8\u3092\u898b\u3064\u3051\u308b\n\u524d\u306b\u672c\u5f53\u306b\u7d42\u4e86\u3057\u307e\u3059\u304b\uff1f MissingImageDialog.confDlg.noFileSel.title=\u6b20\u843d\u30a4\u30e1\u30fc\u30b8 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index 1e091db81c..0fb98ea8b8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -89,6 +89,15 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour public ImageDSProcessor() { configPanel = ImageFilePanel.createInstance(ImageDSProcessor.class.getName(), filtersList); } + + /** + * Get the list of file filters supported by this DSP. + * + * @return A list of all supported file filters. + */ + static List getFileFiltersList() { + return filtersList; + } /** * Gets a string that describes the type of data sources this processor is diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java index 5645e1d5d6..894603fe02 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java @@ -28,6 +28,7 @@ import java.io.File; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; +import javax.swing.filechooser.FileFilter; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.coreutils.DriveUtils; @@ -44,17 +45,8 @@ class MissingImageDialog extends javax.swing.JDialog { private static final Logger logger = Logger.getLogger(MissingImageDialog.class.getName()); long obj_id; SleuthkitCase db; - static final GeneralFilter rawFilter = new GeneralFilter(GeneralFilter.RAW_IMAGE_EXTS, GeneralFilter.RAW_IMAGE_DESC); - static final GeneralFilter encaseFilter = new GeneralFilter(GeneralFilter.ENCASE_IMAGE_EXTS, GeneralFilter.ENCASE_IMAGE_DESC); - static final List allExt = new ArrayList(); - static { - allExt.addAll(GeneralFilter.RAW_IMAGE_EXTS); - allExt.addAll(GeneralFilter.ENCASE_IMAGE_EXTS); - } - static final String allDesc = NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.allDesc.text"); - static final GeneralFilter allFilter = new GeneralFilter(allExt, allDesc); - private final JFileChooser fc = new JFileChooser(); + private final JFileChooser fileChooser = new JFileChooser(); /** * Instantiate a MissingImageDialog. @@ -68,13 +60,15 @@ class MissingImageDialog extends javax.swing.JDialog { this.db = db; initComponents(); - fc.setDragEnabled(false); - fc.setFileSelectionMode(JFileChooser.FILES_ONLY); - fc.setMultiSelectionEnabled(false); + fileChooser.setDragEnabled(false); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.setMultiSelectionEnabled(false); - fc.addChoosableFileFilter(rawFilter); - fc.addChoosableFileFilter(encaseFilter); - fc.setFileFilter(allFilter); + List fileFiltersList = ImageDSProcessor.getFileFiltersList(); + for (FileFilter fileFilter : fileFiltersList) { + fileChooser.addChoosableFileFilter(fileFilter); + } + fileChooser.setFileFilter(fileFiltersList.get(0)); selectButton.setEnabled(false); } @@ -286,12 +280,12 @@ class MissingImageDialog extends javax.swing.JDialog { // set the current directory of the FileChooser if the ImagePath Field is valid File currentDir = new File(oldText); if (currentDir.exists()) { - fc.setCurrentDirectory(currentDir); + fileChooser.setCurrentDirectory(currentDir); } - int retval = fc.showOpenDialog(this); + int retval = fileChooser.showOpenDialog(this); if (retval == JFileChooser.APPROVE_OPTION) { - String path = fc.getSelectedFile().getPath(); + String path = fileChooser.getSelectedFile().getPath(); pathNameTextField.setText(path); } //pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString(), false, true); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java b/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java index 654ee7161e..df98197428 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java @@ -21,51 +21,48 @@ package org.sleuthkit.autopsy.centralrepository; import java.awt.event.ActionEvent; import java.util.logging.Level; import javax.swing.AbstractAction; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute; import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.TskCoreException; /** * An AbstractAction to manage adding and modifying a Central Repository file * instance comment. */ +@Messages({"AddEditCentralRepoCommentAction.menuItemText.addEditCentralRepoComment=Add/Edit Central Repository Comment"}) public final class AddEditCentralRepoCommentAction extends AbstractAction { private static final Logger logger = Logger.getLogger(AddEditCentralRepoCommentAction.class.getName()); private boolean addToDatabase; private CorrelationAttribute correlationAttribute; - String title; + private String comment; /** - * Private constructor to create an instance given a CorrelationAttribute. + * Constructor to create an instance given a CorrelationAttribute. * * @param correlationAttribute The correlation attribute to modify. - * @param title The text for the menu item. */ - private AddEditCentralRepoCommentAction(CorrelationAttribute correlationAttribute, String title) { - super(title); - this.title = title; + public AddEditCentralRepoCommentAction(CorrelationAttribute correlationAttribute) { + super(Bundle.AddEditCentralRepoCommentAction_menuItemText_addEditCentralRepoComment()); this.correlationAttribute = correlationAttribute; } /** - * Private constructor to create an instance given an AbstractFile. + * Constructor to create an instance given an AbstractFile. * - * @param file The file from which a correlation attribute to modify is - * derived. - * @param title The text for the menu item. + * @param file The file from which a correlation attribute to modify is + * derived. */ - private AddEditCentralRepoCommentAction(AbstractFile file, String title) { - - super(title); - this.title = title; + public AddEditCentralRepoCommentAction(AbstractFile file) { + super(Bundle.AddEditCentralRepoCommentAction_menuItemText_addEditCentralRepoComment()); correlationAttribute = EamArtifactUtil.getCorrelationAttributeFromContent(file); if (correlationAttribute == null) { addToDatabase = true; @@ -73,26 +70,24 @@ public final class AddEditCentralRepoCommentAction extends AbstractAction { } } - @Override - public void actionPerformed(ActionEvent event) { - addEditCentralRepoComment(); - } - /** * Create a Add/Edit dialog for the correlation attribute file instance * comment. The comment will be updated in the database if the file instance * exists there, or a new file instance will be added to the database with * the comment attached otherwise. - * - * The current comment for this instance is returned in case it is needed to - * update the display. * - * @return the current comment for this instance + * The current comment for this instance is saved in case it is needed to + * update the display. If the comment was not changed either due to the + * action being canceled or the occurrence of an error, the comment will be + * null. */ - public String addEditCentralRepoComment() { - CentralRepoCommentDialog centralRepoCommentDialog = new CentralRepoCommentDialog(correlationAttribute, title); + @Override + public void actionPerformed(ActionEvent event) { + CentralRepoCommentDialog centralRepoCommentDialog = new CentralRepoCommentDialog(correlationAttribute); centralRepoCommentDialog.display(); + comment = null; + if (centralRepoCommentDialog.isCommentUpdated()) { EamDb dbManager; @@ -104,45 +99,35 @@ public final class AddEditCentralRepoCommentAction extends AbstractAction { } else { dbManager.updateAttributeInstanceComment(correlationAttribute); } + + comment = centralRepoCommentDialog.getComment(); } catch (EamDbException ex) { logger.log(Level.SEVERE, "Error adding comment", ex); + NotifyDescriptor notifyDescriptor = new NotifyDescriptor.Message( + "An error occurred while trying to save the comment to the central repository.", + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDescriptor); } } - return centralRepoCommentDialog.getComment(); } /** - * Create an instance labeled "Add/Edit Central Repository Comment" given an - * AbstractFile. This is intended for the result view. + * Retrieve the comment that was last saved. If a comment update was + * canceled or an error occurred while attempting to save the comment, the + * comment will be null. * - * @param file The file from which a correlation attribute to modify is - * derived. - * - * @return The instance. - * - * @throws EamDbException - * @throws NoCurrentCaseException - * @throws TskCoreException + * @return The comment. */ - @Messages({"AddEditCentralRepoCommentAction.menuItemText.addEditCentralRepoComment=Add/Edit Central Repository Comment"}) - public static AddEditCentralRepoCommentAction createAddEditCentralRepoCommentAction(AbstractFile file) { - - return new AddEditCentralRepoCommentAction(file, - Bundle.AddEditCentralRepoCommentAction_menuItemText_addEditCentralRepoComment()); + public String getComment() { + return comment; } - + /** - * Create an instance labeled "Add/Edit Comment" given a - * CorrelationAttribute. This is intended for the content view. - * - * @param correlationAttribute The correlation attribute to modify. - * - * @return The instance. + * Retrieve the associated correlation attribute. + * + * @return The correlation attribute. */ - @Messages({"AddEditCentralRepoCommentAction.menuItemText.addEditComment=Add/Edit Comment"}) - public static AddEditCentralRepoCommentAction createAddEditCommentAction(CorrelationAttribute correlationAttribute) { - - return new AddEditCentralRepoCommentAction(correlationAttribute, - Bundle.AddEditCentralRepoCommentAction_menuItemText_addEditComment()); + public CorrelationAttribute getCorrelationAttribute() { + return correlationAttribute; } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java index c95b0bfde7..529ffb8529 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.centralrepository; +import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; @@ -26,6 +27,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeIns * Dialog to allow Central Repository file instance comments to be added and * modified. */ +@Messages({"CentralRepoCommentDialog.title.addEditCentralRepoComment=Add/Edit Central Repository Comment"}) @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives final class CentralRepoCommentDialog extends javax.swing.JDialog { @@ -37,10 +39,9 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog { * Create an instance. * * @param correlationAttribute The correlation attribute to be modified. - * @param title The title to assign the dialog. */ - CentralRepoCommentDialog(CorrelationAttribute correlationAttribute, String title) { - super(WindowManager.getDefault().getMainWindow(), title); + CentralRepoCommentDialog(CorrelationAttribute correlationAttribute) { + super(WindowManager.getDefault().getMainWindow(), Bundle.CentralRepoCommentDialog_title_addEditCentralRepoComment()); initComponents(); @@ -82,6 +83,7 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog { * Get the current comment. * If the user hit OK, this will be the new comment. * If the user canceled, this will be the original comment. + * * @return the comment */ String getComment() { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoContextMenuActionsProvider.java b/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoContextMenuActionsProvider.java index 5a6e8fa652..65a980558c 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoContextMenuActionsProvider.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoContextMenuActionsProvider.java @@ -38,19 +38,23 @@ public class CentralRepoContextMenuActionsProvider implements ContextMenuActions @Override public List getActions() { - ArrayList actions = new ArrayList<>(); + ArrayList actionsList = new ArrayList<>(); Collection selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class); if (selectedFiles.size() != 1) { - return actions; + return actionsList; } for (AbstractFile file : selectedFiles) { if (EamDbUtil.useCentralRepo() && EamArtifactUtil.isSupportedAbstractFileType(file) && file.isFile()) { - actions.add(AddEditCentralRepoCommentAction.createAddEditCentralRepoCommentAction(file)); + AddEditCentralRepoCommentAction action = new AddEditCentralRepoCommentAction(file); + if (action.getCorrelationAttribute() == null) { + action.setEnabled(false); + } + actionsList.add(action); } } - return actions; + return actionsList; } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties index b3375cda0d..acb3fa42d1 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties @@ -3,7 +3,7 @@ DataContentViewerOtherCases.showCaseDetailsMenuItem.text=Show Case Details DataContentViewerOtherCases.table.toolTip.text=Click column name to sort. Right-click on the table for more options. DataContentViewerOtherCases.exportToCSVMenuItem.text=Export Selected Rows to CSV DataContentViewerOtherCases.showCommonalityMenuItem.text=Show Frequency -DataContentViewerOtherCases.addCommentMenuItem.text=Add/Edit Comment +DataContentViewerOtherCases.addCommentMenuItem.text=Add/Edit Central Repository Comment DataContentViewerOtherCases.earliestCaseDate.text=Earliest Case Date DataContentViewerOtherCases.earliestCaseLabel.toolTipText= DataContentViewerOtherCases.earliestCaseLabel.text=Central Repository Starting Date: diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index 8ead475d95..26ceed5500 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -38,7 +38,6 @@ import java.util.Map; import java.util.Objects; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; -import java.util.stream.Collectors; import javax.swing.JFileChooser; import javax.swing.JMenuItem; import javax.swing.JOptionPane; @@ -127,12 +126,15 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi } else if (jmi.equals(addCommentMenuItem)) { try { OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(otherCasesTable.getSelectedRow()); - AddEditCentralRepoCommentAction action = AddEditCentralRepoCommentAction.createAddEditCommentAction(selectedNode.createCorrelationAttribute()); - String currentComment = action.addEditCentralRepoComment(); - selectedNode.updateComment(currentComment); - otherCasesTable.repaint(); + AddEditCentralRepoCommentAction action = new AddEditCentralRepoCommentAction(selectedNode.createCorrelationAttribute()); + action.actionPerformed(null); + String currentComment = action.getComment(); + if (currentComment != null) { + selectedNode.updateComment(action.getComment()); + otherCasesTable.repaint(); + } } catch (EamDbException ex) { - logger.log(Level.SEVERE, "Error performing Add/Edit Comment action", ex); + logger.log(Level.SEVERE, "Error performing Add/Edit Central Repository Comment action", ex); } } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java index 6aad75d38e..808b314af0 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java @@ -235,21 +235,37 @@ public class EamArtifactUtil { return null; } - CorrelationAttribute correlationAttribute = null; - + CorrelationAttribute correlationAttribute; + CorrelationAttribute.Type type; + CorrelationCase correlationCase; + CorrelationDataSource correlationDataSource; + String value; + String filePath; + try { - CorrelationAttribute.Type type = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); - CorrelationCase correlationCase = EamDb.getInstance().getCase(Case.getCurrentCaseThrows()); + type = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); + correlationCase = EamDb.getInstance().getCase(Case.getCurrentCaseThrows()); if (null == correlationCase) { correlationCase = EamDb.getInstance().newCase(Case.getCurrentCaseThrows()); } - CorrelationDataSource correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, file.getDataSource()); - String value = file.getMd5Hash(); - String filePath = (file.getParentPath() + file.getName()).toLowerCase(); - - correlationAttribute = EamDb.getInstance().getCorrelationAttribute(type, correlationCase, correlationDataSource, value, filePath); - } catch (TskCoreException | EamDbException | NoCurrentCaseException ex) { + correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, file.getDataSource()); + value = file.getMd5Hash(); + filePath = (file.getParentPath() + file.getName()).toLowerCase(); + } catch (TskCoreException | EamDbException ex) { logger.log(Level.SEVERE, "Error retrieving correlation attribute.", ex); + return null; + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Case is closed.", ex); + return null; + } + + try { + correlationAttribute = EamDb.getInstance().getCorrelationAttribute(type, correlationCase, correlationDataSource, value, filePath); + } catch (EamDbException ex) { + logger.log(Level.WARNING, String.format( + "Correlation attribute could not be retrieved for '%s' (id=%d): %s", + content.getName(), content.getId(), ex.getMessage())); + return null; } return correlationAttribute; @@ -300,9 +316,12 @@ public class EamArtifactUtil { af.getParentPath() + af.getName()); eamArtifact.addInstance(cei); return eamArtifact; - } catch (TskCoreException | EamDbException | NoCurrentCaseException ex) { + } catch (TskCoreException | EamDbException ex) { logger.log(Level.SEVERE, "Error making correlation attribute.", ex); return null; + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Case is closed.", ex); + return null; } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/FileInstanceNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/FileInstanceNode.java index 07c87035e1..899aa5abbc 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/FileInstanceNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/FileInstanceNode.java @@ -77,7 +77,7 @@ public class FileInstanceNode extends FileNode { sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), NO_DESCR, this.getContent().getName())); sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), NO_DESCR, this.getContent().getParentPath())); - sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), NO_DESCR, getHashSetHitsForFile(this.getContent()))); + sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), NO_DESCR, getHashSetHitsCsvList(this.getContent()))); sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), NO_DESCR, this.getDataSource())); sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), NO_DESCR, StringUtils.defaultString(this.getContent().getMIMEType()))); diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java index ced154edf7..9d0a83c2ad 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -26,7 +26,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import javax.swing.JTabbedPane; -import javax.swing.SwingWorker; +import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.openide.explorer.ExplorerManager; @@ -579,29 +579,6 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C } } - /** - * Worker for RootNodeListener childrenAdded. - */ - class SetupTabsChildrenWorker extends SwingWorker { - - private final Node childNode; - - SetupTabsChildrenWorker(Node aChildNode) { - childNode = aChildNode; - } - - @Override - protected Void doInBackground() throws Exception { - setupTabs(childNode); - return null; - } - - @Override - protected void done() { - setupTabs(childNode); - } - } - /** * Responds to changes in the root node due to asynchronous child node * creation. @@ -628,8 +605,13 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C */ if (waitingForData && containsReal(delta)) { waitingForData = false; - Node childNode = nme.getNode(); - new SetupTabsChildrenWorker(childNode).execute(); + if (SwingUtilities.isEventDispatchThread()) { + setupTabs(nme.getNode()); + } else { + SwingUtilities.invokeLater(() -> { + setupTabs(nme.getNode()); + }); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 6ccf1a3c46..80d42614c1 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -141,7 +141,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * Configure the child OutlineView (explorer view) component. */ outlineView.setAllowedDragActions(DnDConstants.ACTION_NONE); - + outline = outlineView.getOutline(); outline.setRowSelectionAllowed(true); outline.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); @@ -208,6 +208,11 @@ public class DataResultViewerTable extends AbstractDataResultViewer { @Override @ThreadConfined(type = ThreadConfined.ThreadType.AWT) public void setNode(Node rootNode) { + if (! SwingUtilities.isEventDispatchThread()) { + LOGGER.log(Level.SEVERE, "Attempting to run setNode() from non-EDT thread"); + return; + } + /* * The quick filter must be reset because when determining column width, * ETable.getRowCount is called, and the documentation states that quick @@ -281,7 +286,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * let the table resize itself. */ outline.setAutoResizeMode((props.isEmpty()) ? JTable.AUTO_RESIZE_ALL_COLUMNS : JTable.AUTO_RESIZE_OFF); - + assignColumns(props); // assign columns to match the properties if (firstProp != null) { ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(firstProp.getDisplayName()); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 28329f17c5..1a52a61bb2 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -251,7 +251,7 @@ public abstract class AbstractAbstractFileNode extends A map.put(TYPE_DIR.toString(), content.getDirType().getLabel()); map.put(TYPE_META.toString(), content.getMetaType().toString()); map.put(KNOWN.toString(), content.getKnown().getName()); - map.put(HASHSETS.toString(), getHashSetHitsForFile(content)); + map.put(HASHSETS.toString(), getHashSetHitsCsvList(content)); map.put(MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash())); map.put(ObjectID.toString(), content.getId()); map.put(MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType())); @@ -263,7 +263,7 @@ public abstract class AbstractAbstractFileNode extends A * to their sheets. * * @param sheetSet the modifiable Sheet.Set returned by - * Sheet.get(Sheet.PROPERTIES) + * Sheet.get(Sheet.PROPERTIES) */ @NbBundle.Messages("AbstractAbstractFileNode.tagsProperty.displayName=Tags") protected void addTagProperty(Sheet.Set sheetSet) { @@ -301,7 +301,15 @@ public abstract class AbstractAbstractFileNode extends A } } - public static String getHashSetHitsForFile(AbstractFile file) { + /** + * Gets a comma-separated values list of the names of the hash sets + * currently identified as including a given file. + * + * @param file The file. + * + * @return The CSV list of hash set names. + */ + protected static String getHashSetHitsCsvList(AbstractFile file) { try { return StringUtils.join(file.getHashSetNames(), ", "); } catch (TskCoreException tskCoreException) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildrenFactory.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildrenFactory.java rename to Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java index 9573347eb9..70f0ca3ce6 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildrenFactory.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java @@ -41,9 +41,9 @@ import org.sleuthkit.datamodel.TskCoreException; * Child factory to create the top level children of the autopsy tree * */ -public class AutopsyTreeChildrenFactory extends ChildFactory.Detachable { +public final class AutopsyTreeChildFactory extends ChildFactory.Detachable { - private static final Logger logger = Logger.getLogger(AutopsyTreeChildrenFactory.class.getName()); + private static final Logger logger = Logger.getLogger(AutopsyTreeChildFactory.class.getName()); /** * Listener for handling DATA_SOURCE_ADDED events. diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 95ba2f110c..fb9ded33e2 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -80,7 +80,7 @@ import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType; import org.sleuthkit.autopsy.datamodel.InterestingHits; import org.sleuthkit.autopsy.datamodel.KeywordHits; import org.sleuthkit.autopsy.datamodel.ResultsNode; -import org.sleuthkit.autopsy.datamodel.AutopsyTreeChildrenFactory; +import org.sleuthkit.autopsy.datamodel.AutopsyTreeChildFactory; import org.sleuthkit.autopsy.datamodel.ViewsNode; import org.sleuthkit.autopsy.datamodel.accounts.Accounts; import org.sleuthkit.autopsy.datamodel.accounts.BINRange; @@ -108,7 +108,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat private final LinkedList forwardList; private static final String PREFERRED_ID = "DirectoryTreeTopComponent"; //NON-NLS private static final Logger LOGGER = Logger.getLogger(DirectoryTreeTopComponent.class.getName()); - private AutopsyTreeChildrenFactory autopsyTreeChildrenFactory; + private AutopsyTreeChildFactory autopsyTreeChildFactory; private Children autopsyTreeChildren; private static final long DEFAULT_DATASOURCE_GROUPING_THRESHOLD = 5; // Threshold for prompting the user about grouping by data source private static final String GROUPING_THRESHOLD_NAME = "GroupDataSourceThreshold"; @@ -476,8 +476,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat } // if there's at least one image, load the image and open the top componen - autopsyTreeChildrenFactory = new AutopsyTreeChildrenFactory(); - autopsyTreeChildren = Children.create(autopsyTreeChildrenFactory, true); + autopsyTreeChildFactory = new AutopsyTreeChildFactory(); + autopsyTreeChildren = Children.create(autopsyTreeChildFactory, true); Node root = new AbstractNode(autopsyTreeChildren) { //JIRA-2807: What is the point of these overrides? /** @@ -735,9 +735,11 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat * responsible for opening core windows. Consider moving * this elsewhere. */ - if (!this.isOpened()) { - SwingUtilities.invokeLater(CoreComponentControl::openCoreWindows); - } + SwingUtilities.invokeLater(() -> { + if (! DirectoryTreeTopComponent.this.isOpened()) { + CoreComponentControl.openCoreWindows(); + } + }); } catch (NoCurrentCaseException notUsed) { /** * Case is closed, do nothing. @@ -907,7 +909,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat } // refresh all children of the root. - autopsyTreeChildrenFactory.refreshChildren(); + autopsyTreeChildFactory.refreshChildren(); // Select the first node and reset the selection history // This should happen on the EDT once the tree has been rebuilt. diff --git a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java index 71404c76e7..4200620749 100644 --- a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java +++ b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java @@ -134,7 +134,7 @@ class ImageWriter implements PropertyChangeListener{ @Messages({ "# {0} - data source name", - "ImageWriter.progressBar.message=Finishing acquisition of {0}" + "ImageWriter.progressBar.message=Finishing acquisition of {0} (unplug device to cancel)" }) private void startFinishImage(String dataSourceName){ diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.form b/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.form index e1f23ebffc..a67060d6f3 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.form +++ b/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.form @@ -97,6 +97,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.java b/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.java index 82de40aac9..03f3bda809 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.java @@ -109,7 +109,7 @@ final class ReportVisualPanel2 extends JPanel { } for (TagName tagName : tagNamesInUse) { - String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; tagStates.put(tagName.getDisplayName() + notableString, Boolean.FALSE); } tags.addAll(tagStates.keySet()); @@ -124,7 +124,9 @@ final class ReportVisualPanel2 extends JPanel { tagsList.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent evt) { - + if (!taggedResultsRadioButton.isSelected()) { + return; + } int index = tagsList.locationToIndex(evt.getPoint()); if (index < tagsModel.getSize() && index >= 0) { String value = tagsModel.getElementAt(index); @@ -184,16 +186,26 @@ final class ReportVisualPanel2 extends JPanel { return tagStates; } + /** + * Are any tags selected? + * + * @return True if any tags are selected; otherwise false. + */ private boolean areTagsSelected() { boolean result = false; for (Entry entry : tagStates.entrySet()) { if (entry.getValue()) { result = true; + break; } } return result; } + /** + * Set the Finish button as either enabled or disabled depending on the UI + * component selections. + */ private void updateFinishButton() { if (taggedResultsRadioButton.isSelected()) { wizPanel.setFinish(areTagsSelected()); @@ -209,6 +221,19 @@ final class ReportVisualPanel2 extends JPanel { return taggedResultsRadioButton.isSelected(); } + /** + * Set all tagged results as either selected or unselected. + * + * @param selected Should all tagged results be selected? + */ + void setAllTaggedResultsSelected(boolean selected) { + for (String tag : tags) { + tagStates.put(tag, (selected ? Boolean.TRUE : Boolean.FALSE)); + } + tagsList.repaint(); + wizPanel.setFinish(selected); + } + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -234,6 +259,11 @@ final class ReportVisualPanel2 extends JPanel { optionsButtonGroup.add(allResultsRadioButton); org.openide.awt.Mnemonics.setLocalizedText(allResultsRadioButton, org.openide.util.NbBundle.getMessage(ReportVisualPanel2.class, "ReportVisualPanel2.allResultsRadioButton.text")); // NOI18N + allResultsRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + allResultsRadioButtonActionPerformed(evt); + } + }); org.openide.awt.Mnemonics.setLocalizedText(dataLabel, org.openide.util.NbBundle.getMessage(ReportVisualPanel2.class, "ReportVisualPanel2.dataLabel.text")); // NOI18N @@ -312,25 +342,21 @@ final class ReportVisualPanel2 extends JPanel { }// //GEN-END:initComponents private void selectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectAllButtonActionPerformed - for (String tag : tags) { - tagStates.put(tag, Boolean.TRUE); - } - tagsList.repaint(); - wizPanel.setFinish(true); + setAllTaggedResultsSelected(true); }//GEN-LAST:event_selectAllButtonActionPerformed private void deselectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectAllButtonActionPerformed - for (String tag : tags) { - tagStates.put(tag, Boolean.FALSE); - } - tagsList.repaint(); - wizPanel.setFinish(false); + setAllTaggedResultsSelected(false); }//GEN-LAST:event_deselectAllButtonActionPerformed private void advancedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_advancedButtonActionPerformed artifactStates = dialog.display(); }//GEN-LAST:event_advancedButtonActionPerformed + private void allResultsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allResultsRadioButtonActionPerformed + setAllTaggedResultsSelected(false); + }//GEN-LAST:event_allResultsRadioButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton advancedButton; private javax.swing.JRadioButton allResultsRadioButton; diff --git a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java index f87851fe87..64f1f509af 100644 --- a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java @@ -582,7 +582,7 @@ class TableReportGenerator { adHocCountQuery += " AND (art.artifact_id = tag.artifact_id) AND (tag.tag_name_id IN (" + tagIDList + ")) "; //NON-NLS } adHocCountQuery += "EXCEPT " + // NON-NLS - "SELECT art.artifact_id FROM blackboard_artifacts AS art, blackboard_attributes AS att1 WHERE (att1.artifact_id = art.artifact_id) AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") AND (att1.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + ")) "; //NON-NLS + "SELECT art.artifact_id FROM blackboard_artifacts AS art, blackboard_attributes AS att1 WHERE (att1.artifact_id = art.artifact_id) AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") AND (att1.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + ")) AS adHocHits"; //NON-NLS int adHocCount = 0; try (SleuthkitCase.CaseDbQuery dbQuery = openCase.getSleuthkitCase().executeQuery(adHocCountQuery)) { @@ -600,7 +600,7 @@ class TableReportGenerator { // Create the query to get the keyword list names if (openCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) { - orderByClause = "ORDER BY convert_to(att.value_text, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS + orderByClause = "ORDER BY convert_to(list, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS } else { orderByClause = "ORDER BY list ASC"; //NON-NLS } @@ -621,8 +621,9 @@ class TableReportGenerator { "AND (tag.tag_name_id IN (" + tagIDList + ")) "; //NON-NLS } if (adHocCount > 0) { - keywordListQuery += " UNION SELECT \"\" AS list "; + keywordListQuery += " UNION SELECT \'\' AS list "; } + keywordListQuery = "SELECT * FROM ( " + keywordListQuery + " ) kwListNames "; keywordListQuery += "GROUP BY list " + orderByClause; //NON-NLS // Make the table of contents links for each list type @@ -645,17 +646,17 @@ class TableReportGenerator { BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName())); } catch (TskCoreException | SQLException ex) { errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedQueryKWLists")); - logger.log(Level.SEVERE, "Failed to query keyword lists: ", ex); //NON-NLS + logger.log(Level.SEVERE, "Failed to query keyword lists with query " + keywordListQuery, ex); //NON-NLS return; } // Query for keywords, grouped by list if (openCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) { - orderByClause = "ORDER BY convert_to(att3.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS - + "convert_to(att1.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS - + "convert_to(f.parent_path, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS - + "convert_to(f.name, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS - + "convert_to(att2.value_text, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS + orderByClause = "ORDER BY convert_to(list, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS + + "convert_to(keyword, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS + + "convert_to(parent_path, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS + + "convert_to(name, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS + + "convert_to(preview, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS } else { orderByClause = "ORDER BY list ASC, keyword ASC, parent_path ASC, name ASC, preview ASC"; //NON-NLS } @@ -684,7 +685,7 @@ class TableReportGenerator { // Query for keywords that are not part of a list String keywordAdHocQuery = - "SELECT art.artifact_id AS artifact_id, art.obj_id AS obj_id, att1.value_text AS keyword, att2.value_text AS preview, \"\" AS list, f.name AS name, f.parent_path AS parent_path " + // NON-NLS + "SELECT art.artifact_id AS artifact_id, art.obj_id AS obj_id, att1.value_text AS keyword, att2.value_text AS preview, \'\' AS list, f.name AS name, f.parent_path AS parent_path " + // NON-NLS "FROM blackboard_artifacts AS art, blackboard_attributes AS att1, blackboard_attributes AS att2, tsk_files AS f " + // NON-NLS "WHERE " + // NON-NLS " (art.artifact_id IN (SELECT art.artifact_id FROM blackboard_artifacts AS art, blackboard_attributes AS att1 WHERE (att1.artifact_id = art.artifact_id) AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") " + // NON-NLS @@ -697,7 +698,7 @@ class TableReportGenerator { "AND (att2.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID() + ") " + // NON-NLS "AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") "; // NON-NLS - String keywordsQuery = keywordListsQuery + " UNION " + keywordAdHocQuery + orderByClause; + String keywordsQuery = "SELECT * FROM ( " + keywordListsQuery + " UNION " + keywordAdHocQuery + " ) kwHits " + orderByClause; try (SleuthkitCase.CaseDbQuery dbQuery = openCase.getSleuthkitCase().executeQuery(keywordsQuery)) { ResultSet resultSet = dbQuery.getResultSet(); @@ -770,7 +771,7 @@ class TableReportGenerator { tableModule.endDataType(); } catch (TskCoreException | SQLException ex) { errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedQueryKWs")); - logger.log(Level.SEVERE, "Failed to query keywords: ", ex); //NON-NLS + logger.log(Level.SEVERE, "Failed to query keywords with query " + keywordsQuery, ex); //NON-NLS } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java index 7515891356..6bc26f8d7a 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java @@ -567,8 +567,11 @@ class ListTimeline extends BorderPane { super.updateItem(item, empty); if (empty || item == null) { setText(null); + setTooltip(null); } else { - setText(textSupplier.apply(getEvent())); + String text = textSupplier.apply(getEvent()); + setText(text); + setTooltip(new Tooltip(text)); } } } diff --git a/CoreLibs/manifest.mf b/CoreLibs/manifest.mf index e2386f67ce..24af339d11 100644 --- a/CoreLibs/manifest.mf +++ b/CoreLibs/manifest.mf @@ -1,8 +1,8 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.corelibs/3 -OpenIDE-Module-Implementation-Version: 4 +OpenIDE-Module-Implementation-Version: 5 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corelibs/Bundle.properties -OpenIDE-Module-Specification-Version: 1.1 +OpenIDE-Module-Specification-Version: 1.2 AutoUpdate-Show-In-Client: true AutoUpdate-Essential-Module: true diff --git a/Experimental/nbproject/project.xml b/Experimental/nbproject/project.xml index 6d3d3f6730..c0a18a9922 100644 --- a/Experimental/nbproject/project.xml +++ b/Experimental/nbproject/project.xml @@ -135,7 +135,7 @@ 10 - 10.11 + 10.12 @@ -144,7 +144,7 @@ 3 - 1.1 + 1.2 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/objectdetection/ObjectDetectectionFileIngestModule.java b/Experimental/src/org/sleuthkit/autopsy/experimental/objectdetection/ObjectDetectectionFileIngestModule.java index d6bef92ab8..003a35a46d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/objectdetection/ObjectDetectectionFileIngestModule.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/objectdetection/ObjectDetectectionFileIngestModule.java @@ -19,14 +19,11 @@ package org.sleuthkit.autopsy.experimental.objectdetection; import java.io.File; -import java.io.IOException; -import java.io.InputStream; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; import org.opencv.core.CvException; import org.opencv.core.Mat; import org.opencv.core.MatOfByte; @@ -52,7 +49,6 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; /** @@ -61,6 +57,7 @@ import org.sleuthkit.datamodel.TskCoreException; public class ObjectDetectectionFileIngestModule extends FileIngestModuleAdapter { private final static Logger logger = Logger.getLogger(ObjectDetectectionFileIngestModule.class.getName()); + private final static int MAX_FILE_SIZE = 100000000; //Max size of pictures to perform object detection on private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); private long jobId; private Map classifiers; @@ -100,15 +97,24 @@ public class ObjectDetectectionFileIngestModule extends FileIngestModuleAdapter @Override public ProcessResult process(AbstractFile file) { if (!classifiers.isEmpty() && ImageUtils.isImageThumbnailSupported(file)) { - //Any image we can create a thumbnail for is one we should apply the classifiers to - InputStream inputStream = new ReadContentInputStream(file); - byte[] imageInMemory; + //Any image we can create a thumbnail for is one we should apply the classifiers to + + if (file.getSize() > MAX_FILE_SIZE) { + //prevent it from allocating gigabytes of memory for extremely large files + logger.log(Level.INFO, "Encountered file " + file.getParentPath() + file.getName() + " with object id of " + + file.getId() + " which exceeds max file size of " + MAX_FILE_SIZE + " bytes, with a size of " + file.getSize()); + return IngestModule.ProcessResult.OK; + } + + byte[] imageInMemory = new byte[(int) file.getSize()]; + try { - imageInMemory = IOUtils.toByteArray(inputStream); - } catch (IOException ex) { + file.read(imageInMemory, 0, file.getSize()); + } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to read image to byte array for performing object detection on " + file.getParentPath() + file.getName() + " with object id of " + file.getId(), ex); return IngestModule.ProcessResult.ERROR; } + Mat originalImage; try { originalImage = Highgui.imdecode(new MatOfByte(imageInMemory), Highgui.IMREAD_GRAYSCALE); @@ -121,7 +127,6 @@ public class ObjectDetectectionFileIngestModule extends FileIngestModuleAdapter logger.log(Level.SEVERE, "Unexpected Exception encountered attempting to use OpenCV to decode picture: " + file.getParentPath() + file.getName() + " with object id of " + file.getId(), unexpectedException); return IngestModule.ProcessResult.ERROR; } - MatOfRect detectionRectangles = new MatOfRect(); //the rectangles which reprent the coordinates on the image for where objects were detected for (String classifierKey : classifiers.keySet()) { //apply each classifier to the file @@ -130,9 +135,9 @@ public class ObjectDetectectionFileIngestModule extends FileIngestModuleAdapter } catch (CvException ignored) { //The image was likely an image which we are unable to generate a thumbnail for, and the classifier was likely one where that is not acceptable continue; - } catch (Exception unexpectedException) { + } catch (Exception unexpectedException) { //hopefully an unnecessary generic exception catch but currently present to catch any exceptions OpenCv throws which may not be documented - logger.log(Level.SEVERE, "Unexpected Exception encountered for image " + file.getParentPath() + file.getName() + " with object id of " + file.getId() +" while trying to apply classifier " + classifierKey, unexpectedException); + logger.log(Level.SEVERE, "Unexpected Exception encountered for image " + file.getParentPath() + file.getName() + " with object id of " + file.getId() + " while trying to apply classifier " + classifierKey, unexpectedException); continue; } @@ -163,10 +168,14 @@ public class ObjectDetectectionFileIngestModule extends FileIngestModuleAdapter } catch (TskCoreException ex) { logger.log(Level.SEVERE, String.format("Failed to create blackboard artifact for '%s'.", file.getParentPath() + file.getName()), ex); //NON-NLS + detectionRectangles.release(); + originalImage.release(); return IngestModule.ProcessResult.ERROR; } } } + detectionRectangles.release(); + originalImage.release(); } return IngestModule.ProcessResult.OK; diff --git a/ImageGallery/nbproject/project.xml b/ImageGallery/nbproject/project.xml index 0fdad950f2..dcaa641e75 100644 --- a/ImageGallery/nbproject/project.xml +++ b/ImageGallery/nbproject/project.xml @@ -127,7 +127,7 @@ 10 - 10.11 + 10.12 @@ -136,7 +136,7 @@ 3 - 1.1 + 1.2 diff --git a/KeywordSearch/manifest.mf b/KeywordSearch/manifest.mf index 9f3126687e..5b53ffe61d 100644 --- a/KeywordSearch/manifest.mf +++ b/KeywordSearch/manifest.mf @@ -1,7 +1,7 @@ Manifest-Version: 1.0 AutoUpdate-Show-In-Client: true OpenIDE-Module: org.sleuthkit.autopsy.keywordsearch/6 -OpenIDE-Module-Implementation-Version: 19 +OpenIDE-Module-Implementation-Version: 20 OpenIDE-Module-Install: org/sleuthkit/autopsy/keywordsearch/Installer.class OpenIDE-Module-Layer: org/sleuthkit/autopsy/keywordsearch/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/keywordsearch/Bundle.properties diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index 25142d8119..343dc691e7 100644 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -119,7 +119,7 @@ 10 - 10.11 + 10.12 @@ -128,7 +128,7 @@ 3 - 1.1 + 1.2 diff --git a/RecentActivity/manifest.mf b/RecentActivity/manifest.mf index 3121c6b8ca..c115996776 100644 --- a/RecentActivity/manifest.mf +++ b/RecentActivity/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.recentactivity/6 -OpenIDE-Module-Implementation-Version: 15 +OpenIDE-Module-Implementation-Version: 16 OpenIDE-Module-Layer: org/sleuthkit/autopsy/recentactivity/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties OpenIDE-Module-Requires: diff --git a/RecentActivity/nbproject/project.xml b/RecentActivity/nbproject/project.xml index fd72fa7dfe..4d85f94e9b 100644 --- a/RecentActivity/nbproject/project.xml +++ b/RecentActivity/nbproject/project.xml @@ -60,7 +60,7 @@ 10 - 10.11 + 10.12 diff --git a/TSKVersion.xml b/TSKVersion.xml index 57096d8d35..7350f25b66 100644 --- a/TSKVersion.xml +++ b/TSKVersion.xml @@ -1,3 +1,3 @@ - + diff --git a/nbproject/project.properties b/nbproject/project.properties index 1ce749b501..55a5b67cfd 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -6,8 +6,8 @@ app.name=${branding.token} ### if left unset, version will default to today's date app.version=4.8.0 ### build.type must be one of: DEVELOPMENT, RELEASE -build.type=RELEASE -#build.type=DEVELOPMENT +#build.type=RELEASE +build.type=DEVELOPMENT project.org.netbeans.progress=org-netbeans-api-progress project.org.sleuthkit.autopsy.experimental=Experimental diff --git a/thunderbirdparser/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml index 110c3b8ede..d4c0a0b53d 100644 --- a/thunderbirdparser/nbproject/project.xml +++ b/thunderbirdparser/nbproject/project.xml @@ -36,7 +36,7 @@ 10 - 10.11 + 10.12 diff --git a/unix_setup.sh b/unix_setup.sh index 970c35a5c2..1cf9b65888 100755 --- a/unix_setup.sh +++ b/unix_setup.sh @@ -2,7 +2,7 @@ # Verifies programs are installed and copies native code into the Autopsy folder structure -TSK_VERSION=4.6.1 +TSK_VERSION=4.6.2 # Verify PhotoRec was installed photorec_filepath=/usr/bin/photorec