diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 3b15568c2b..e4402a1b86 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -124,6 +124,7 @@ import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceException; +import org.sleuthkit.autopsy.machinesettings.UserMachinePreferences; import org.sleuthkit.autopsy.progress.LoggingProgressIndicator; import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator; import org.sleuthkit.autopsy.progress.ProgressIndicator; @@ -1477,16 +1478,7 @@ public class Case { * @return The temp subdirectory path. */ public String getTempDirectory() { - // get temp folder scoped to the combination of case name and timestamp - // provided by getName() - Path path = Paths.get(UserPreferences.getAppTempDirectory(), CASE_TEMP_DIR, getName()); - File f = path.toFile(); - // verify that the folder exists - if (!f.exists()) { - f.mkdirs(); - } - - return path.toAbsolutePath().toString(); + return UserMachinePreferences.getTempDirectory(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 537c25c827..395b8cd830 100644 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -674,8 +674,7 @@ public final class UserPreferences { * @return The absolute path to the application temp directory. */ public static String getAppTempDirectory() { - return Paths.get(UserMachinePreferences.getBaseTempDirectory(), getAppName()) - .toAbsolutePath().toString(); + return UserMachinePreferences.getTempDirectory(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index 79746c704e..4c42c44668 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -8,6 +8,8 @@ + + @@ -24,12 +26,12 @@ - + - + @@ -418,7 +420,7 @@ - + @@ -444,37 +446,53 @@ - - - + + + + + - + + + + + + + + - + + + + + - + + - + + + - + - + - + @@ -498,6 +516,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 9a6af23efa..193b1836e9 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -38,6 +38,7 @@ import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; +import org.apache.commons.lang3.StringUtils; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; @@ -47,9 +48,9 @@ import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.machinesettings.UserMachinePreferences; import org.sleuthkit.autopsy.machinesettings.UserMachinePreferencesException; import org.sleuthkit.autopsy.core.UserPreferences; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.Version; +import org.sleuthkit.autopsy.machinesettings.UserMachinePreferences.TempDirChoice; import org.sleuthkit.autopsy.report.ReportBranding; /** @@ -77,7 +78,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; private final JFileChooser logoFileChooser; private final JFileChooser tempDirChooser; - private final TextFieldListener textFieldListener; private static final String ETC_FOLDER_NAME = "etc"; private static final String CONFIG_FILE_EXTENSION = ".conf"; private static final long ONE_BILLION = 1000000000L; //used to roughly convert system memory from bytes to gigabytes @@ -118,9 +118,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { solrMaxHeapSpinner.setModel(new javax.swing.SpinnerNumberModel(UserPreferences.getMaxSolrVMSize(), JVM_MEMORY_STEP_SIZE_MB, ((int) getSystemMemoryInGB()) * MEGA_IN_GIGA, JVM_MEMORY_STEP_SIZE_MB)); - textFieldListener = new TextFieldListener(); + TextFieldListener textFieldListener = new TextFieldListener(); agencyLogoPathField.getDocument().addDocumentListener(textFieldListener); - tempDirectoryField.getDocument().addDocumentListener(textFieldListener); + tempCustomField.getDocument().addDocumentListener(new TempCustomTextListener()); logFileCount.setText(String.valueOf(UserPreferences.getLogFileCount())); reportBranding = new ReportBranding(); @@ -302,6 +302,16 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } return new String[]{}; } + + private void evaluateTempDirState() { + boolean caseOpen = Case.isCaseOpen(); + boolean customSelected = tempCustomRadio.isSelected(); + + tempDirectoryBrowseButton.setEnabled(!caseOpen && customSelected); + tempCustomField.setEnabled(!caseOpen && customSelected); + + tempOnCustomNoPath.setVisible(customSelected && StringUtils.isBlank(tempCustomField.getText())); + } /** * Load the saved user preferences. @@ -313,10 +323,25 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { specifyLogoRB.setSelected(!useDefault); agencyLogoPathField.setEnabled(!useDefault); browseLogosButton.setEnabled(!useDefault); - tempDirectoryField.setText(UserMachinePreferences.getBaseTempDirectory()); + + tempCustomField.setText(UserMachinePreferences.getCustomTempDirectory()); + switch (UserMachinePreferences.getTempDirChoice()) { + case CASE: + tempCaseRadio.setSelected(true); + break; + case CUSTOM: + tempCustomRadio.setSelected(true); + break; + default: + case SYSTEM: + tempLocalRadio.setSelected(true); + break; + } + + evaluateTempDirState(); + logFileCount.setText(String.valueOf(UserPreferences.getLogFileCount())); solrMaxHeapSpinner.setValue(UserPreferences.getMaxSolrVMSize()); - tempDirectoryField.setText(UserMachinePreferences.getBaseTempDirectory()); try { updateAgencyLogo(path); } catch (IOException ex) { @@ -337,9 +362,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private void setTempDirEnabled() { boolean enabled = !Case.isCaseOpen(); - this.tempDirectoryBrowseButton.setEnabled(enabled); - this.tempDirectoryField.setEnabled(enabled); + + this.tempCaseRadio.setEnabled(enabled); + this.tempCustomRadio.setEnabled(enabled); + this.tempLocalRadio.setEnabled(enabled); + this.tempDirectoryWarningLabel.setVisible(!enabled); + evaluateTempDirState(); } /** @@ -371,12 +400,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { @Messages({ "AutopsyOptionsPanel_storeTempDir_onError_title=Error Saving Temporary Directory", "# {0} - path", - "AutopsyOptionsPanel_storeTempDir_onError_description=There was an error creating the temporary directory on the filesystem at: {0}.",}) + "AutopsyOptionsPanel_storeTempDir_onError_description=There was an error creating the temporary directory on the filesystem at: {0}.", + "AutopsyOptionsPanel_storeTempDir_onChoiceError_title=Error Saving Temporary Directory Choice", + "AutopsyOptionsPanel_storeTempDir_onChoiceError_description=There was an error updating temporary directory choice selection.",}) private void storeTempDir() { - String tempDirectoryPath = tempDirectoryField.getText(); - if (!UserMachinePreferences.getBaseTempDirectory().equals(tempDirectoryPath)) { + String tempDirectoryPath = tempCustomField.getText(); + if (!UserMachinePreferences.getCustomTempDirectory().equals(tempDirectoryPath)) { try { - UserMachinePreferences.setBaseTempDirectory(tempDirectoryPath); + UserMachinePreferences.setCustomTempDirectory(tempDirectoryPath); } catch (UserMachinePreferencesException ex) { logger.log(Level.WARNING, "There was an error creating the temporary directory defined by the user: " + tempDirectoryPath, ex); SwingUtilities.invokeLater(() -> { @@ -387,6 +418,29 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { }); } } + + TempDirChoice choice; + if (tempCaseRadio.isSelected()) { + choice = TempDirChoice.CASE; + } else if (tempCustomRadio.isSelected()) { + choice = TempDirChoice.CUSTOM; + } else { + choice = TempDirChoice.SYSTEM; + } + + if (!choice.equals(UserMachinePreferences.getTempDirChoice())) { + try { + UserMachinePreferences.setTempDirChoice(choice); + } catch (UserMachinePreferencesException ex) { + logger.log(Level.WARNING, "There was an error updating choice to: " + choice.name(), ex); + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(this, + String.format("%s", Bundle.AutopsyOptionsPanel_storeTempDir_onChoiceError_description()), + Bundle.AutopsyOptionsPanel_storeTempDir_onChoiceError_title(), + JOptionPane.ERROR_MESSAGE); + }); + } + } } /** @@ -554,6 +608,32 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } } + + /** + * Listens for changes in the temp directory custom directory text field. + */ + private class TempCustomTextListener extends TextFieldListener { + + @Override + public void changedUpdate(DocumentEvent e) { + evaluateTempDirState(); + super.changedUpdate(e); + } + + @Override + public void removeUpdate(DocumentEvent e) { + evaluateTempDirState(); + super.changedUpdate(e); + } + + @Override + public void insertUpdate(DocumentEvent e) { + evaluateTempDirState(); + super.changedUpdate(e); + } + + + } /** * This method is called from within the constructor to initialize the form. @@ -567,6 +647,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { fileSelectionButtonGroup = new javax.swing.ButtonGroup(); displayTimesButtonGroup = new javax.swing.ButtonGroup(); logoSourceButtonGroup = new javax.swing.ButtonGroup(); + tempDirChoiceGroup = new javax.swing.ButtonGroup(); jScrollPane1 = new javax.swing.JScrollPane(); javax.swing.JPanel mainPanel = new javax.swing.JPanel(); logoPanel = new javax.swing.JPanel(); @@ -593,9 +674,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { solrMaxHeapSpinner = new javax.swing.JSpinner(); solrJVMHeapWarning = new javax.swing.JLabel(); tempDirectoryPanel = new javax.swing.JPanel(); - tempDirectoryField = new javax.swing.JTextField(); + tempCustomField = new javax.swing.JTextField(); tempDirectoryBrowseButton = new javax.swing.JButton(); tempDirectoryWarningLabel = new javax.swing.JLabel(); + tempLocalRadio = new javax.swing.JRadioButton(); + tempCaseRadio = new javax.swing.JRadioButton(); + tempCustomRadio = new javax.swing.JRadioButton(); + tempOnCustomNoPath = new javax.swing.JLabel(); rdpPanel = new javax.swing.JPanel(); javax.swing.JScrollPane sizingScrollPane = new javax.swing.JScrollPane(); javax.swing.JTextPane sizingTextPane = new javax.swing.JTextPane(); @@ -822,7 +907,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { tempDirectoryPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryPanel.border.title"))); // NOI18N tempDirectoryPanel.setName(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryPanel.name")); // NOI18N - tempDirectoryField.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryField.text")); // NOI18N + tempCustomField.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempCustomField.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(tempDirectoryBrowseButton, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryBrowseButton.text")); // NOI18N tempDirectoryBrowseButton.addActionListener(new java.awt.event.ActionListener() { @@ -834,6 +919,33 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { tempDirectoryWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/warning16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(tempDirectoryWarningLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryWarningLabel.text")); // NOI18N + tempDirChoiceGroup.add(tempLocalRadio); + org.openide.awt.Mnemonics.setLocalizedText(tempLocalRadio, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempLocalRadio.text")); // NOI18N + tempLocalRadio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + tempLocalRadioActionPerformed(evt); + } + }); + + tempDirChoiceGroup.add(tempCaseRadio); + org.openide.awt.Mnemonics.setLocalizedText(tempCaseRadio, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempCaseRadio.text")); // NOI18N + tempCaseRadio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + tempCaseRadioActionPerformed(evt); + } + }); + + tempDirChoiceGroup.add(tempCustomRadio); + org.openide.awt.Mnemonics.setLocalizedText(tempCustomRadio, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempCustomRadio.text")); // NOI18N + tempCustomRadio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + tempCustomRadioActionPerformed(evt); + } + }); + + tempOnCustomNoPath.setForeground(java.awt.Color.RED); + org.openide.awt.Mnemonics.setLocalizedText(tempOnCustomNoPath, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempOnCustomNoPath.text")); // NOI18N + javax.swing.GroupLayout tempDirectoryPanelLayout = new javax.swing.GroupLayout(tempDirectoryPanel); tempDirectoryPanel.setLayout(tempDirectoryPanelLayout); tempDirectoryPanelLayout.setHorizontalGroup( @@ -841,23 +953,37 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(tempDirectoryPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(tempDirectoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tempLocalRadio) + .addComponent(tempCaseRadio) .addComponent(tempDirectoryWarningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 615, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(tempDirectoryPanelLayout.createSequentialGroup() - .addComponent(tempDirectoryField, javax.swing.GroupLayout.PREFERRED_SIZE, 367, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(tempCustomRadio) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(tempDirectoryBrowseButton))) - .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(tempDirectoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tempOnCustomNoPath) + .addGroup(tempDirectoryPanelLayout.createSequentialGroup() + .addComponent(tempCustomField, javax.swing.GroupLayout.PREFERRED_SIZE, 459, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tempDirectoryBrowseButton))))) + .addContainerGap(158, Short.MAX_VALUE)) ); tempDirectoryPanelLayout.setVerticalGroup( tempDirectoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(tempDirectoryPanelLayout.createSequentialGroup() .addContainerGap() + .addComponent(tempLocalRadio) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tempCaseRadio) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(tempDirectoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(tempDirectoryField) + .addComponent(tempCustomRadio) + .addComponent(tempCustomField) .addComponent(tempDirectoryBrowseButton)) - .addGap(18, 18, 18) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(tempOnCustomNoPath) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(tempDirectoryWarningLabel) - .addContainerGap()) + .addGap(14, 14, 14)) ); gridBagConstraints = new java.awt.GridBagConstraints(); @@ -910,11 +1036,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 648, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 860, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 620, Short.MAX_VALUE) ); }// //GEN-END:initComponents @@ -931,7 +1057,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { if (!f.exists() && !f.mkdirs()) { throw new InvalidPathException(specifiedPath, "Unable to create parent directories leading to " + specifiedPath); } - tempDirectoryField.setText(specifiedPath); + tempCustomField.setText(specifiedPath); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } catch (InvalidPathException ex) { logger.log(Level.WARNING, "Unable to create temporary directory in " + specifiedPath, ex); @@ -1021,6 +1147,21 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } }//GEN-LAST:event_browseLogosButtonActionPerformed + private void tempLocalRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tempLocalRadioActionPerformed + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + evaluateTempDirState(); + }//GEN-LAST:event_tempLocalRadioActionPerformed + + private void tempCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tempCaseRadioActionPerformed + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + evaluateTempDirState(); + }//GEN-LAST:event_tempCaseRadioActionPerformed + + private void tempCustomRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tempCustomRadioActionPerformed + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + evaluateTempDirState(); + }//GEN-LAST:event_tempCustomRadioActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JTextField agencyLogoPathField; private javax.swing.JLabel agencyLogoPathFieldValidationLabel; @@ -1049,10 +1190,15 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private javax.swing.JSpinner solrMaxHeapSpinner; private javax.swing.JRadioButton specifyLogoRB; private javax.swing.JLabel systemMemoryTotal; + private javax.swing.JRadioButton tempCaseRadio; + private javax.swing.JTextField tempCustomField; + private javax.swing.JRadioButton tempCustomRadio; + private javax.swing.ButtonGroup tempDirChoiceGroup; private javax.swing.JButton tempDirectoryBrowseButton; - private javax.swing.JTextField tempDirectoryField; private javax.swing.JPanel tempDirectoryPanel; private javax.swing.JLabel tempDirectoryWarningLabel; + private javax.swing.JRadioButton tempLocalRadio; + private javax.swing.JLabel tempOnCustomNoPath; private javax.swing.JLabel totalMemoryLabel; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index b880747533..bad8f8ff83 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -188,12 +188,11 @@ MultiUserSettingsPanel.restartRequiredLabel.text=Application restart required to MultiUserSettingsPanel.MustRestart=Autopsy must be restarted for new configuration to take effect MultiUserSettingsPanel.lbSolrNote1.text=Enter Solr 8 and/or Solr 4 server settings. MultiUserSettingsPanel.lbSolrNote2.text=New text indexing can only be done with Solr 8. -AutopsyOptionsPanel.tempDirectoryField.text= AutopsyOptionsPanel.tempDirectoryBrowseButton.text=Browse AutopsyOptionsPanel.a.AccessibleContext.accessibleName=Temp Directory AutopsyOptionsPanel.tempDirectoryPanel.AccessibleContext.accessibleName=Temp Directory AutopsyOptionsPanel.tempDirectoryPanel.name=Temp Directory -AutopsyOptionsPanel.tempDirectoryPanel.border.title=Temp Directory +AutopsyOptionsPanel.tempDirectoryPanel.border.title=Root Temp Directory AutopsyOptionsPanel.tempDirectoryWarningLabel.text=Close the current case to change the temporary directory. AutopsyOptionsPanel.solrJVMHeapWarning.text=NOTE: Setting this too large may impact overall performance. AutopsyOptionsPanel.maxMemoryUnitsLabel2.text=MB @@ -247,3 +246,8 @@ AutopsyOptionsPanel.agencyLogoPathField.text= AutopsyOptionsPanel.logoPanel.border.title=Logo ViewPreferencesPanel.radioGroupByPersonHost.text=Group by Person/Host ViewPreferencesPanel.radioGroupByDataType.text=Group by Data Type +AutopsyOptionsPanel.tempLocalRadio.text=Local temp directory +AutopsyOptionsPanel.tempCaseRadio.text=Temp folder in case directory +AutopsyOptionsPanel.tempCustomRadio.text=Custom +AutopsyOptionsPanel.tempCustomField.text= +AutopsyOptionsPanel.tempOnCustomNoPath.text=Please select a path for the custom root temp directory. diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED index a1520ece04..bcf95a19a9 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED @@ -12,6 +12,8 @@ AutopsyOptionsPanel.memFieldValidationLabel.noValueEntered.text=No value entered AutopsyOptionsPanel.memFieldValidationLabel.overMaxMemory.text=Value must be less than the total system memory of {0}GB # {0} - minimumMemory AutopsyOptionsPanel.memFieldValidationLabel.underMinMemory.text=Value must be at least {0}GB +AutopsyOptionsPanel_storeTempDir_onChoiceError_description=There was an error updating temporary directory choice selection. +AutopsyOptionsPanel_storeTempDir_onChoiceError_title=Error Saving Temporary Directory Choice # {0} - path AutopsyOptionsPanel_storeTempDir_onError_description=There was an error creating the temporary directory on the filesystem at: {0}. AutopsyOptionsPanel_storeTempDir_onError_title=Error Saving Temporary Directory @@ -246,12 +248,11 @@ MultiUserSettingsPanel.restartRequiredLabel.text=Application restart required to MultiUserSettingsPanel.MustRestart=Autopsy must be restarted for new configuration to take effect MultiUserSettingsPanel.lbSolrNote1.text=Enter Solr 8 and/or Solr 4 server settings. MultiUserSettingsPanel.lbSolrNote2.text=New text indexing can only be done with Solr 8. -AutopsyOptionsPanel.tempDirectoryField.text= AutopsyOptionsPanel.tempDirectoryBrowseButton.text=Browse AutopsyOptionsPanel.a.AccessibleContext.accessibleName=Temp Directory AutopsyOptionsPanel.tempDirectoryPanel.AccessibleContext.accessibleName=Temp Directory AutopsyOptionsPanel.tempDirectoryPanel.name=Temp Directory -AutopsyOptionsPanel.tempDirectoryPanel.border.title=Temp Directory +AutopsyOptionsPanel.tempDirectoryPanel.border.title=Root Temp Directory AutopsyOptionsPanel.tempDirectoryWarningLabel.text=Close the current case to change the temporary directory. AutopsyOptionsPanel.solrJVMHeapWarning.text=NOTE: Setting this too large may impact overall performance. AutopsyOptionsPanel.maxMemoryUnitsLabel2.text=MB @@ -305,3 +306,8 @@ AutopsyOptionsPanel.agencyLogoPathField.text= AutopsyOptionsPanel.logoPanel.border.title=Logo ViewPreferencesPanel.radioGroupByPersonHost.text=Group by Person/Host ViewPreferencesPanel.radioGroupByDataType.text=Group by Data Type +AutopsyOptionsPanel.tempLocalRadio.text=Local temp directory +AutopsyOptionsPanel.tempCaseRadio.text=Temp folder in case directory +AutopsyOptionsPanel.tempCustomRadio.text=Custom +AutopsyOptionsPanel.tempCustomField.text= +AutopsyOptionsPanel.tempOnCustomNoPath.text=Please select a path for the custom root temp directory. diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java index 6c551da602..3bef43e0b2 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java @@ -95,9 +95,9 @@ final class DataSourceIngestPipeline extends IngestTaskPipeline { ingestManager.setIngestTaskProgress(task, getDisplayName()); ingestJobPipeline.setCurrentFileIngestModule(getDisplayName(), file.getName()); ProcessResult result = module.process(file); - if (result == ProcessResult.ERROR) { - throw new IngestModuleException(String.format("%s experienced an error analyzing %s (file objId = %d)", getDisplayName(), file.getName(), file.getId())); //NON-NLS - } +// if (result == ProcessResult.ERROR) { +// throw new IngestModuleException(String.format("%s experienced an error analyzing %s (file objId = %d)", getDisplayName(), file.getName(), file.getId())); //NON-NLS +// } } } diff --git a/Core/src/org/sleuthkit/autopsy/machinesettings/UserMachinePreferences.java b/Core/src/org/sleuthkit/autopsy/machinesettings/UserMachinePreferences.java index cc1538c9b7..ef7b138ef0 100644 --- a/Core/src/org/sleuthkit/autopsy/machinesettings/UserMachinePreferences.java +++ b/Core/src/org/sleuthkit/autopsy/machinesettings/UserMachinePreferences.java @@ -20,10 +20,15 @@ package org.sleuthkit.autopsy.machinesettings; import java.io.File; import java.nio.file.Paths; +import java.util.Optional; import java.util.prefs.Preferences; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.FileUtil; /** @@ -33,26 +38,122 @@ public final class UserMachinePreferences { private static final Preferences preferences = NbPreferences.forModule(UserMachinePreferences.class); - private static final String TEMP_DIR_KEY = "TempDirectory"; + /** + * The user specified choice for where the temp directory should be located. + */ + public enum TempDirChoice { + /** + * A custom location specified with an absolute path by the user. + */ + CUSTOM, + /** + * Equivalent to java.io.tmpdir. + */ + SYSTEM, + /** + * If a case is open, a sub directory of the case. + */ + CASE; + + /** + * Returns the temp directory choice that matches the string provided + * (whitespace and case insensitive). + * + * @param val The string value. + * @return The choice or empty if not found. + */ + static Optional getValue(String val) { + if (val == null) { + return Optional.empty(); + } + + return Stream.of(TempDirChoice.values()) + .filter(tempChoice -> tempChoice.name().equalsIgnoreCase(val.trim())) + .findFirst(); + } + } + + private static final String CUSTOM_TEMP_DIR_KEY = "TempDirectory"; + private static final String TEMP_DIR_CHOICE_KEY = "TempDirChoice"; + + private static final String AUTOPSY_SUBDIR = UserPreferences.getAppName(); + private static final String CASE_SUBDIR = "Temp"; + + private static final TempDirChoice DEFAULT_CHOICE = TempDirChoice.SYSTEM; /** - * Retrieves a default temporary directory that is a subdirectory of - * java.io.tmpdir. - * - * @return The absolute path to the temp directory. + * @return A subdirectory of java.io.tmpdir. */ - private static String getDefaultTempDirectory() { - return Paths.get(System.getProperty("java.io.tmpdir")).toAbsolutePath().toString(); + private static File getSystemTempDirFile() { + return Paths.get(System.getProperty("java.io.tmpdir"), AUTOPSY_SUBDIR).toFile(); } /** - * Retrieves the base user-specified temporary directory. + * @return A subdirectory of the open case or getSystemTempDirFile if no + * open case. + */ + private static File getCaseTempDirFile() { + try { + String caseDirStr = Case.getCurrentCaseThrows().getCaseDirectory(); + return Paths.get(caseDirStr, CASE_SUBDIR).toFile(); + } catch (NoCurrentCaseException ex) { + return getSystemTempDirFile(); + } + } + + /** + * Returns the custom directory subdirectory to be used for temp files + * (otherwise java.io.tmpdir subdir). + * + * @return A subdirectory of the custom user-specified path. If no path is + * specified, getSystemTempDirFile() is returned instead. + */ + private static File getCustomTempDirFile() { + String customDirectory = getCustomTempDirectory(); + return (StringUtils.isBlank(customDirectory)) + ? getSystemTempDirFile() : Paths.get(customDirectory, AUTOPSY_SUBDIR).toFile(); + } + + /** + * Returns the temp directory file to use based on user choice. + * + * @return The directory. + */ + private static File getTempDirFile() { + TempDirChoice choice = getTempDirChoice(); + switch (choice) { + case CASE: + return getCaseTempDirFile(); + case CUSTOM: + return getCustomTempDirFile(); + case SYSTEM: + default: + return getSystemTempDirFile(); + } + } + + /** + * Returns the temp directory to use based on settings. This method also + * ensures the temp directory has been created. * * @return The base user-specified temporary directory. */ - public static String getBaseTempDirectory() { - String tempDir = preferences.get(TEMP_DIR_KEY, null); - return StringUtils.isBlank(tempDir) ? getDefaultTempDirectory() : tempDir; + public static String getTempDirectory() { + File dir = getTempDirFile(); + dir = dir == null ? getSystemTempDirFile() : dir; + + if (!dir.exists()) { + dir.mkdirs(); + } + + return dir.getAbsolutePath(); + } + + /** + * @return The user-specified custom temp directory path or empty string. + */ + public static String getCustomTempDirectory() { + return preferences.get(CUSTOM_TEMP_DIR_KEY, ""); } /** @@ -64,8 +165,7 @@ public final class UserMachinePreferences { * @return True if this is a valid location for a temp directory. * * @throws UserMachinePreferencesException If path could not be validated - * due to mkdirs failure or the - * directory is not read/write. + * due to mkdirs failure or the directory is not read/write. */ @NbBundle.Messages({ "# {0} - path", @@ -96,11 +196,33 @@ public final class UserMachinePreferences { * @param path The path to the directory. * * @throws UserMachinePreferencesException If the directory cannot be - * accessed or created. + * accessed or created. */ - public static void setBaseTempDirectory(String path) throws UserMachinePreferencesException { + public static void setCustomTempDirectory(String path) throws UserMachinePreferencesException { validateTempDirectory(path); - preferences.put(TEMP_DIR_KEY, path); + preferences.put(CUSTOM_TEMP_DIR_KEY, path); + } + + /** + * @return The user selection for how the temp directory should be handled + * (temp directory in case folder, in java.io.tmpdir, custom path). + */ + public static TempDirChoice getTempDirChoice() { + return TempDirChoice.getValue(preferences.get(TEMP_DIR_CHOICE_KEY, null)) + .orElse(DEFAULT_CHOICE); + } + + /** + * Sets the temp directory choice (i.e. system, case, custom). + * @param tempDirChoice The choice (must be non-null). + * @throws UserMachinePreferencesException + */ + public static void setTempDirChoice(TempDirChoice tempDirChoice) throws UserMachinePreferencesException { + if (tempDirChoice == null) { + throw new UserMachinePreferencesException("Expected non-null temp dir choice"); + } + + preferences.put(TEMP_DIR_CHOICE_KEY, tempDirChoice.name()); } private UserMachinePreferences() { diff --git a/CoreLibs/ivy.xml b/CoreLibs/ivy.xml index 7457154839..303f0a04bb 100644 --- a/CoreLibs/ivy.xml +++ b/CoreLibs/ivy.xml @@ -14,7 +14,7 @@ - + diff --git a/CoreLibs/nbproject/project.properties b/CoreLibs/nbproject/project.properties index 3d8ebb951a..60d2362fd8 100644 --- a/CoreLibs/nbproject/project.properties +++ b/CoreLibs/nbproject/project.properties @@ -42,8 +42,8 @@ file.reference.javassist-3.12.1.GA.jar=release/modules/ext/javassist-3.12.1.GA.j file.reference.jfxtras-common-8.0-r4.jar=release/modules/ext/jfxtras-common-8.0-r4.jar file.reference.jfxtras-controls-8.0-r4.jar=release/modules/ext/jfxtras-controls-8.0-r4.jar file.reference.jfxtras-fxml-8.0-r4.jar=release/modules/ext/jfxtras-fxml-8.0-r4.jar -file.reference.jna-5.7.0.jar=release/modules/ext/jna-5.7.0.jar -file.reference.jna-platform-5.7.0.jar=release/modules/ext/jna-platform-5.7.0.jar +file.reference.jna-5.8.0.jar=release/modules/ext/jna-5.8.0.jar +file.reference.jna-platform-5.8.0.jar=release/modules/ext/jna-platform-5.8.0.jar file.reference.joda-time-2.4.jar=release/modules/ext/joda-time-2.4.jar file.reference.jsr305-1.3.9.jar=release/modules/ext/jsr305-1.3.9.jar file.reference.LGoodDatePicker-10.3.1.jar=release/modules/ext/LGoodDatePicker-10.3.1.jar diff --git a/CoreLibs/nbproject/project.xml b/CoreLibs/nbproject/project.xml index 24219c333d..0d3dac9aa3 100644 --- a/CoreLibs/nbproject/project.xml +++ b/CoreLibs/nbproject/project.xml @@ -923,8 +923,8 @@ release/modules/ext/commons-compress-1.18.jar - ext/jna-platform-5.7.0.jar - release\modules\ext\jna-platform-5.7.0.jar + ext/jna-platform-5.8.0.jar + release\modules\ext\jna-platform-5.8.0.jar ext/opencv-248.jar @@ -951,8 +951,8 @@ release/modules/ext/imageio-bmp-3.2.jar - ext/jna-5.7.0.jar - release\modules\ext\jna-5.7.0.jar + ext/jna-5.8.0.jar + release\modules\ext\jna-5.8.0.jar ext/commons-lang-2.6.jar diff --git a/NEWS.txt b/NEWS.txt index d437c75034..532aae69fa 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -33,6 +33,7 @@ Reporting: Misc: - Added support for Ext4 inline data and sparse blocks (via TSK fix). +- Fixed timeline controller deadlock issue - Updated PostgreSQL JDBC driver to support any recent version of PostgreSQL for multi-user cases and PostgreSQL Central Repository. - Added personas to the summary viewer in CVT. - Handling of bad characters in auto ingest manifest files. diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 8d215ccf6e..cdffe5e21a 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -876,9 +876,12 @@ class ExtractRegistry extends Extract { try{ createOrUpdateOsAccount(regFile, sid, username, homeDir); - } catch(TskCoreException | TskDataException ex) { - logger.log(Level.SEVERE, String.format("Failed to create OsAccount for file: %s, sid: %s", regFile.getId(), sid)); + } catch (OsAccountManager.NotUserSIDException ex) { + logger.log(Level.WARNING, String.format("Cannot create OsAccount for file: %s, sid: %s is not a user SID.", regFile.getId(), sid)); } + catch(TskCoreException | TskDataException ex ) { + logger.log(Level.SEVERE, String.format("Failed to create OsAccount for file: %s, sid: %s", regFile.getId(), sid)); + } BlackboardArtifact bbart = null; try { @@ -1216,7 +1219,10 @@ class ExtractRegistry extends Extract { logger.log(Level.WARNING, "Error parsing the the date from the registry file", ex); //NON-NLS } catch (TskDataException | TskCoreException ex) { logger.log(Level.WARNING, "Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex); //NON-NLS - } finally { + } catch (OsAccountManager.NotUserSIDException ex) { + logger.log(Level.WARNING, "Error creating OS Account, input SID is not a user SID.", ex); //NON-NLS + } + finally { if (!context.dataSourceIngestIsCancelled()) { postArtifacts(newArtifacts); } @@ -2206,8 +2212,9 @@ class ExtractRegistry extends Extract { * * @throws TskCoreException * @throws TskDataException + * @throws OsAccountManager.NotUserSIDException */ - private void createOrUpdateOsAccount(AbstractFile file, String sid, String userName, String homeDir) throws TskCoreException, TskDataException { + private void createOrUpdateOsAccount(AbstractFile file, String sid, String userName, String homeDir) throws TskCoreException, TskDataException, OsAccountManager.NotUserSIDException { OsAccountManager accountMgr = tskCase.getOsAccountManager(); HostManager hostMrg = tskCase.getHostManager(); Host host = hostMrg.getHost((DataSource)dataSource); diff --git a/nbproject/platform.properties b/nbproject/platform.properties index 7a61a6e1b6..32e681b3af 100644 --- a/nbproject/platform.properties +++ b/nbproject/platform.properties @@ -7,9 +7,9 @@ suite.dir=${basedir} nbplatform.active=download nbplatform.active.dir=${suite.dir}/netbeans-plat/${netbeans-plat-version} harness.dir=${nbplatform.active.dir}/harness -bootstrap.url=https://netbeans-vm.apache.org/uc/${netbeans-plat-version}/tasks.jar +bootstrap.url=https://netbeans-vm1.apache.org/uc/${netbeans-plat-version}/tasks.jar # Where we get the platform from. To see what versions are available, open URL in browser up to the .../updates part of the URL -autoupdate.catalog.url=https://netbeans-vm.apache.org/uc/${netbeans-plat-version}/updates.xml.gz +autoupdate.catalog.url=https://netbeans-vm1.apache.org/uc/${netbeans-plat-version}/updates.xml.gz cluster.path=\ ${nbplatform.active.dir}/harness:\ ${nbplatform.active.dir}/java:\