From f9bcfc14a660ade2133831fee820ea6c50364a38 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 30 Mar 2021 20:34:05 -0400 Subject: [PATCH 01/12] initial draft of heap dump options --- .../corecomponents/AutopsyOptionsPanel.form | 67 ++- .../corecomponents/AutopsyOptionsPanel.java | 384 +++++++++++++----- .../autopsy/corecomponents/Bundle.properties | 4 + 3 files changed, 349 insertions(+), 106 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index 4c42c44668..d47982f2a7 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -244,7 +244,7 @@ - + @@ -255,7 +255,24 @@ - + + + + + + + + + + + + + + + + + + @@ -293,7 +310,15 @@ - + + + + + + + + + @@ -414,6 +439,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -462,7 +521,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 193b1836e9..4ee0cde43b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -31,6 +31,10 @@ import java.util.List; import java.util.Optional; import java.util.StringJoiner; import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFileChooser; @@ -38,7 +42,10 @@ import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.tools.ant.types.Commandline; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; @@ -88,6 +95,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private String initialMemValue = Long.toString(Runtime.getRuntime().maxMemory() / ONE_BILLION); private final ReportBranding reportBranding; + private final JFileChooser heapFileChooser; /** * Instantiate the Autopsy options panel. @@ -103,6 +111,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { tempDirChooser = new JFileChooser(); tempDirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); tempDirChooser.setMultiSelectionEnabled(false); + + heapFileChooser = new JFileChooser(); + heapFileChooser.setMultiSelectionEnabled(false); if (!PlatformUtil.is64BitJVM() || Version.getBuildType() == Version.Type.DEVELOPMENT) { //32 bit JVM has a max heap size of 1.4 gb to 4 gb depending on OS @@ -118,9 +129,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 textFieldListener = new TextFieldListener(); - agencyLogoPathField.getDocument().addDocumentListener(textFieldListener); - tempCustomField.getDocument().addDocumentListener(new TempCustomTextListener()); + agencyLogoPathField.getDocument().addDocumentListener(new TextFieldListener(null)); + heapDumpFileField.getDocument().addDocumentListener(new TextFieldListener(this::isHeapPathValid)); + tempCustomField.getDocument().addDocumentListener(new TextFieldListener(this::evaluateTempDirState)); logFileCount.setText(String.valueOf(UserPreferences.getLogFileCount())); reportBranding = new ReportBranding(); @@ -140,18 +151,23 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { /** * Gets the currently saved max java heap space in gigabytes. + * @param The conf file memory value (i.e. 4G). * - * @return @throws IOException when unable to get a valid setting + * @return The value in gigabytes. + * @throws IOException when unable to get a valid setting */ - private long getCurrentJvmMaxMemoryInGB() throws IOException { - String currentXmx = getCurrentXmxValue(); + private long getCurrentJvmMaxMemoryInGB(String confFileMemValue) throws IOException { char units = '-'; Long value = 0L; - if (currentXmx.length() > 1) { - units = currentXmx.charAt(currentXmx.length() - 1); - value = Long.parseLong(currentXmx.substring(0, currentXmx.length() - 1)); + if (confFileMemValue.length() > 1) { + units = confFileMemValue.charAt(confFileMemValue.length() - 1); + try { + value = Long.parseLong(confFileMemValue.substring(0, confFileMemValue.length() - 1)); + } catch (NumberFormatException ex) { + throw new IOException("Unable to properly parse memory number.", ex); + } } else { - throw new IOException("No memory setting found in String: " + currentXmx); + throw new IOException("No memory setting found in String: " + confFileMemValue); } //some older .conf files might have the units as megabytes instead of gigabytes switch (units) { @@ -166,33 +182,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } } - /* - * The value currently saved in the conf file as the max java heap space - * available to this application. Form will be an integer followed by a - * character indicating units. Helper method for - * getCurrentJvmMaxMemoryInGB() - * - * @return the saved value for the max java heap space - * - * @throws IOException if the conf file does not exist in either the user - * directory or the install directory - */ - private String getCurrentXmxValue() throws IOException { - String[] settings; - String currentSetting = ""; - File userConfFile = getUserFolderConfFile(); - if (!userConfFile.exists()) { - settings = getDefaultsFromFileContents(readConfFile(getInstallFolderConfFile())); - } else { - settings = getDefaultsFromFileContents(readConfFile(userConfFile)); - } - for (String option : settings) { - if (option.startsWith("-J-Xmx")) { - currentSetting = option.replace("-J-Xmx", "").trim(); - } - } - return currentSetting; - } /** * Get the conf file from the install directory which stores the default @@ -229,7 +218,49 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } return new File(userEtcFolder, confFileName); } - + + private static final String JVM_SETTINGS_REGEX_PARAM = "options"; + private static final Pattern JVM_SETTINGS_REGEX = Pattern.compile("^\\s*default_options\\s*=\\s*\"?(?<" + JVM_SETTINGS_REGEX_PARAM + ">.+?)\"?\\s*$"); + private static final String XMX_REGEX_PARAM = "mem"; + private static final String XMX_REGEX_STR = "^\\s*\\-J\\-Xmx(?<" + XMX_REGEX_PARAM + ">.+?)\\s*$"; + private static final Pattern XMX_REGEX = Pattern.compile(XMX_REGEX_STR); + private static final String HEAP_DUMP_REGEX_PARAM = "path"; + private static final String HEAP_DUMP_REGEX_STR = "^\\s*\\-J\\-XX:HeapDumpPath=\\s*(\\\")?(?<" + HEAP_DUMP_REGEX_PARAM + ">.+?)(\\\")?\\s*$"; + private static final Pattern HEAP_DUMP_REGEX = Pattern.compile(HEAP_DUMP_REGEX_STR); + + /** + * Parse the autopsy conf file line. If the line is the default_options line, + * then replaces with current memory and heap path value. Otherwise, returns + * the line provided as parameter. + * + * @param line The line. + * @param memText The text to add as an argument to be used as memory with -J-Xmx. + * @param heapText The text to add as an argument to be used as the heap dump path with + * -J-XX:HeapDumpPath. + * @return The line modified to contain memory and heap arguments. + */ + private static String updateConfLine(String line, String memText, String heapText) { + Matcher match = JVM_SETTINGS_REGEX.matcher(line); + if (match != null) { + // split on command line arguments + String unescaped = StringEscapeUtils.unescapeJava(match.group(JVM_SETTINGS_REGEX_PARAM)); + String[] parsedArgs = Commandline.translateCommandline(unescaped); + + String newArgs = Stream.concat(Stream.of(parsedArgs) + // remove saved version of memory and heap dump path + .filter(s -> !s.matches(XMX_REGEX_STR) && !s.matches(HEAP_DUMP_REGEX_STR)), + Stream.of( + "-J-Xmx" + memText.replaceAll("[^\\d]", "") + "g", + String.format("-J-XX:HeapDumpPath=\"%s\"", heapText == null ? "" : StringEscapeUtils.escapeJava(heapText)))) + .collect(Collectors.joining(" ")); + + return String.format("default_options=\"%s\"", StringEscapeUtils.escapeJava(newArgs)); + }; + + return line; + } + + /** * Take the conf file in the install directory and save a copy of it to the * user directory. The copy will be modified to include the current memory @@ -239,25 +270,118 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { * install folders conf file */ private void writeEtcConfFile() throws IOException { - StringBuilder content = new StringBuilder(); - List confFile = readConfFile(getInstallFolderConfFile()); - for (String line : confFile) { - if (line.contains("-J-Xmx")) { - String[] splitLine = line.split(" "); - StringJoiner modifiedLine = new StringJoiner(" "); - for (String piece : splitLine) { - if (piece.contains("-J-Xmx")) { - piece = "-J-Xmx" + memField.getText() + "g"; - } - modifiedLine.add(piece); - } - content.append(modifiedLine.toString()); - } else { - content.append(line); - } - content.append("\n"); + String fileText = readConfFile(getInstallFolderConfFile()).stream() + .map((line) -> updateConfLine(line, memField.getText(), heapDumpFileField.getText())) + .collect(Collectors.joining("\n")); + + FileUtils.writeStringToFile(getUserFolderConfFile(), fileText, "UTF-8"); + } + + + /** + * Values for configuration located in the /etc/*.conf file. + */ + private static class ConfValues { + private final String XmxVal; + private final String heapDumpPath; + + /** + * Main constructor. + * @param XmxVal The heap memory size. + * @param heapDumpPath The heap dump path. + */ + ConfValues(String XmxVal, String heapDumpPath) { + this.XmxVal = XmxVal; + this.heapDumpPath = heapDumpPath; } - Files.write(getUserFolderConfFile().toPath(), content.toString().getBytes()); + + /** + * Returns the heap memory value specified in the conf file. + * @return The heap memory value specified in the conf file. + */ + String getXmxVal() { + return XmxVal; + } + + /** + * Returns path to the heap dump specified in the conf file. + * @return Path to the heap dump specified in the conf file. + */ + String getHeapDumpPath() { + return heapDumpPath; + } + } + + /** + * Retrieve the /etc/*.conf file values pertinent to settings. + * @return The conf file values. + * @throws IOException + */ + private ConfValues getEtcConfValues() throws IOException { + File userConfFile = getUserFolderConfFile(); + String[] confLines = userConfFile.exists() ? + getDefaultsFromFileContents(readConfFile(userConfFile)) : + getDefaultsFromFileContents(readConfFile(getInstallFolderConfFile())); + + String heapFile = ""; + String memSize = ""; + + for (String confLine: confLines) { + Matcher match = JVM_SETTINGS_REGEX.matcher(confLine); + if (match != null) { + String unescaped = StringEscapeUtils.unescapeJava(match.group(1)); + String[] args = Commandline.translateCommandline(unescaped); + + for (String arg : args) { + Matcher memMatch = XMX_REGEX.matcher(arg); + if (memMatch != null) { + memSize = memMatch.group(XMX_REGEX_PARAM); + continue; + } + + Matcher heapFileMatch = HEAP_DUMP_REGEX.matcher(arg); + if (heapFileMatch != null) { + heapFile = StringEscapeUtils.unescapeJava(heapFileMatch.group(HEAP_DUMP_REGEX_PARAM)); + continue; + } + } + break; + } + } + + return new ConfValues(memSize, heapFile); + } + + + + /** + * Checks current heap path value to see if it is valid, and displays an error message if invalid. + * @return True if the heap path is valid. + */ + @Messages({ + "AutopsyOptionsPanel_validateHeapField_fileAlreadyExists=A file already exists at this location.", + "AutopsyOptionsPanel_validateHeapField_directoryDoesNotExist=Selected directory does not exist." + }) + private boolean isHeapPathValid() { + File curHeapFile = new File(heapDumpFileField.getText()); + boolean isDirectory = curHeapFile.isDirectory(); + boolean exists = curHeapFile.exists(); + if (exists && !isDirectory) { + heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_validateHeapField_fileAlreadyExists()); + return false; + } + + + if (!exists) { + File parentDir = curHeapFile.getParentFile(); + if (parentDir == null || !parentDir.exists()) { + heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_validateHeapField_directoryDoesNotExist()); + return false; + } + } + + heapFieldValidationLabel.setText(""); + return true; } /** @@ -349,7 +473,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } if (memField.isEnabled()) { try { - initialMemValue = Long.toString(getCurrentJvmMaxMemoryInGB()); + ConfValues confValues = getEtcConfValues(); + heapDumpFileField.setText(confValues.getHeapDumpPath()); + initialMemValue = Long.toString(getCurrentJvmMaxMemoryInGB(confValues.getXmxVal())); } catch (IOException ex) { logger.log(Level.SEVERE, "Can't read current Jvm max memory setting from file", ex); memField.setEnabled(false); @@ -474,18 +600,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { * @return True if valid; false otherwise. */ boolean valid() { - boolean valid = true; - if (!isAgencyLogoPathValid()) { - valid = false; - } - if (!isMemFieldValid()) { - valid = false; - } - if (!isLogNumFieldValid()) { - valid = false; - } - - return valid; + return isAgencyLogoPathValid() && + isMemFieldValid() && + isLogNumFieldValid() && + isHeapPathValid(); } /** @@ -589,47 +707,41 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { /** * Listens for registered text fields that have changed and fires a - * PropertyChangeEvent accordingly. + * PropertyChangeEvent accordingly as well as firing an optional additional listener. */ private class TextFieldListener implements DocumentListener { + private final Runnable onChange; - @Override - public void insertUpdate(DocumentEvent e) { + + /** + * Main constructor. + * @param onChange Additional listener for change events. + */ + TextFieldListener(Runnable onChange) { + this.onChange = onChange; + } + + private void baseOnChange() { + if (onChange != null) { + onChange.run(); + } + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } + + @Override + public void changedUpdate(DocumentEvent e) { + baseOnChange(); + } @Override public void removeUpdate(DocumentEvent e) { - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - } - - @Override - public void changedUpdate(DocumentEvent e) { - 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); + baseOnChange(); } @Override public void insertUpdate(DocumentEvent e) { - evaluateTempDirState(); - super.changedUpdate(e); + baseOnChange(); } @@ -673,6 +785,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { maxMemoryUnitsLabel2 = new javax.swing.JLabel(); solrMaxHeapSpinner = new javax.swing.JSpinner(); solrJVMHeapWarning = new javax.swing.JLabel(); + heapFileLabel = new javax.swing.JLabel(); + heapDumpFileField = new javax.swing.JTextField(); + heapDumpBrowseButton = new javax.swing.JButton(); + heapFieldValidationLabel = new javax.swing.JLabel(); tempDirectoryPanel = new javax.swing.JPanel(); tempCustomField = new javax.swing.JTextField(); tempDirectoryBrowseButton = new javax.swing.JButton(); @@ -823,6 +939,20 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(solrJVMHeapWarning, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.solrJVMHeapWarning.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(heapFileLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.heapFileLabel.text")); // NOI18N + + heapDumpFileField.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.heapDumpFileField.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(heapDumpBrowseButton, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.heapDumpBrowseButton.text")); // NOI18N + heapDumpBrowseButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + heapDumpBrowseButtonActionPerformed(evt); + } + }); + + heapFieldValidationLabel.setForeground(new java.awt.Color(255, 0, 0)); + org.openide.awt.Mnemonics.setLocalizedText(heapFieldValidationLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.heapFieldValidationLabel.text")); // NOI18N + javax.swing.GroupLayout runtimePanelLayout = new javax.swing.GroupLayout(runtimePanel); runtimePanel.setLayout(runtimePanelLayout); runtimePanelLayout.setHorizontalGroup( @@ -851,14 +981,26 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(runtimePanelLayout.createSequentialGroup() .addGap(23, 23, 23) .addComponent(memFieldValidationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 478, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(12, Short.MAX_VALUE)) .addGroup(runtimePanelLayout.createSequentialGroup() .addGap(18, 18, 18) .addComponent(solrJVMHeapWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 331, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(44, 44, 44) .addComponent(logNumAlert) .addContainerGap()))) - .addComponent(restartNecessaryWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 615, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(runtimePanelLayout.createSequentialGroup() + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(restartNecessaryWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 615, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(runtimePanelLayout.createSequentialGroup() + .addComponent(heapFileLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(heapFieldValidationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 478, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(runtimePanelLayout.createSequentialGroup() + .addComponent(heapDumpFileField, javax.swing.GroupLayout.PREFERRED_SIZE, 415, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(heapDumpBrowseButton))))) + .addGap(0, 0, Short.MAX_VALUE)))) ); runtimePanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {maxLogFileCount, maxMemoryLabel, totalMemoryLabel}); @@ -892,7 +1034,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(maxLogFileCount) .addComponent(logFileCount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(heapFileLabel) + .addComponent(heapDumpFileField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(heapDumpBrowseButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(heapFieldValidationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(restartNecessaryWarning) .addContainerGap()) ); @@ -965,7 +1114,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .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)) + .addContainerGap(164, Short.MAX_VALUE)) ); tempDirectoryPanelLayout.setVerticalGroup( tempDirectoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -1162,6 +1311,33 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { evaluateTempDirState(); }//GEN-LAST:event_tempCustomRadioActionPerformed + @Messages({ + "AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsTitle=File Already Exists", + "AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsMessage=File already exists. Please select a new location." + }) + private void heapDumpBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_heapDumpBrowseButtonActionPerformed + String oldHeapPath = heapDumpFileField.getText(); + if (!StringUtils.isBlank(oldHeapPath)) { + heapFileChooser.setCurrentDirectory(new File(oldHeapPath)); + } + + int returnState = heapFileChooser.showSaveDialog(this); + if (returnState == JFileChooser.APPROVE_OPTION) { + File selectedFile = heapFileChooser.getSelectedFile(); + // heap dump path can be file or directory: https://www.oracle.com/java/technologies/javase/vmoptions-jsp.html + if (selectedFile.exists() && !selectedFile.isDirectory()) { + JOptionPane.showMessageDialog(this, + Bundle.AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsMessage(), + Bundle.AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsTitle(), + JOptionPane.ERROR_MESSAGE); + + } else { + heapDumpFileField.setText(selectedFile.getAbsolutePath()); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } + } + }//GEN-LAST:event_heapDumpBrowseButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JTextField agencyLogoPathField; private javax.swing.JLabel agencyLogoPathFieldValidationLabel; @@ -1170,6 +1346,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private javax.swing.JRadioButton defaultLogoRB; private javax.swing.ButtonGroup displayTimesButtonGroup; private javax.swing.ButtonGroup fileSelectionButtonGroup; + private javax.swing.JButton heapDumpBrowseButton; + private javax.swing.JTextField heapDumpFileField; + private javax.swing.JLabel heapFieldValidationLabel; + private javax.swing.JLabel heapFileLabel; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JTextField logFileCount; private javax.swing.JTextField logNumAlert; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index bad8f8ff83..278f4828e8 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -251,3 +251,7 @@ 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. +AutopsyOptionsPanel.heapDumpFileField.text= +AutopsyOptionsPanel.heapDumpBrowseButton.text=Browse +AutopsyOptionsPanel.heapFileLabel.text=Heap Dump Location: +AutopsyOptionsPanel.heapFieldValidationLabel.text= From 8df2674a19d6cf2fee878b6e64834f5e2d9069b3 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 1 Apr 2021 14:12:21 -0400 Subject: [PATCH 02/12] small fixes --- .../corecomponents/AutopsyOptionsPanel.java | 54 ++++++++++++++----- .../corecomponents/Bundle.properties-MERGED | 10 ++++ 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 4ee0cde43b..f8cb96ae5b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -29,7 +29,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.StringJoiner; import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -83,6 +82,7 @@ import org.sleuthkit.autopsy.report.ReportBranding; final class AutopsyOptionsPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; + private static final String DEFAULT_HEAP_DUMP_FILE_FIELD = ""; private final JFileChooser logoFileChooser; private final JFileChooser tempDirChooser; private static final String ETC_FOLDER_NAME = "etc"; @@ -115,12 +115,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { heapFileChooser = new JFileChooser(); heapFileChooser.setMultiSelectionEnabled(false); - if (!PlatformUtil.is64BitJVM() || Version.getBuildType() == Version.Type.DEVELOPMENT) { + if (!isJVMHeapSettingsCapable()) { //32 bit JVM has a max heap size of 1.4 gb to 4 gb depending on OS //So disabling the setting of heap size when the JVM is not 64 bit //Is the safest course of action //And the file won't exist in the install folder when running through netbeans memField.setEnabled(false); + heapDumpFileField.setEnabled(false); + heapDumpBrowseButton.setEnabled(false); solrMaxHeapSpinner.setEnabled(false); } systemMemoryTotal.setText(Long.toString(getSystemMemoryInGB())); @@ -136,6 +138,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { reportBranding = new ReportBranding(); } + + /** + * Returns whether or not the jvm runtime heap settings can effectively be changed. + * @return Whether or not the jvm runtime heap settings can effectively be changed. + */ + private static boolean isJVMHeapSettingsCapable() { + return PlatformUtil.is64BitJVM() && Version.getBuildType() != Version.Type.DEVELOPMENT; + } /** * Get the total system memory in gigabytes which exists on the machine @@ -329,7 +339,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { for (String confLine: confLines) { Matcher match = JVM_SETTINGS_REGEX.matcher(confLine); if (match != null) { - String unescaped = StringEscapeUtils.unescapeJava(match.group(1)); + String unescaped = StringEscapeUtils.unescapeJava(match.group(JVM_SETTINGS_REGEX_PARAM)); String[] args = Commandline.translateCommandline(unescaped); for (String arg : args) { @@ -359,15 +369,27 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { * @return True if the heap path is valid. */ @Messages({ - "AutopsyOptionsPanel_validateHeapField_fileAlreadyExists=A file already exists at this location.", - "AutopsyOptionsPanel_validateHeapField_directoryDoesNotExist=Selected directory does not exist." + "AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists=A file already exists at this location.", + "AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist=Selected directory does not exist.", + "AutopsyOptionsPanel_isHeapPathValid_developerMode=Cannot change heap dump path while in developer mode.", + "AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=Changing heap dump path settings only enabled for 64 bit version." }) private boolean isHeapPathValid() { + if (Version.getBuildType() == Version.Type.DEVELOPMENT) { + heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_developerMode()); + return true; + } + + if (!PlatformUtil.is64BitJVM()) { + heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_not64BitMachine()); + return true; + } + File curHeapFile = new File(heapDumpFileField.getText()); boolean isDirectory = curHeapFile.isDirectory(); boolean exists = curHeapFile.exists(); if (exists && !isDirectory) { - heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_validateHeapField_fileAlreadyExists()); + heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists()); return false; } @@ -375,7 +397,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { if (!exists) { File parentDir = curHeapFile.getParentFile(); if (parentDir == null || !parentDir.exists()) { - heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_validateHeapField_directoryDoesNotExist()); + heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist()); return false; } } @@ -471,7 +493,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } catch (IOException ex) { logger.log(Level.WARNING, "Error loading image from previously saved agency logo path", ex); } - if (memField.isEnabled()) { + if (isJVMHeapSettingsCapable()) { try { ConfValues confValues = getEtcConfValues(); heapDumpFileField.setText(confValues.getHeapDumpPath()); @@ -479,8 +501,12 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } catch (IOException ex) { logger.log(Level.SEVERE, "Can't read current Jvm max memory setting from file", ex); memField.setEnabled(false); + heapDumpFileField.setText(DEFAULT_HEAP_DUMP_FILE_FIELD); + heapDumpBrowseButton.setEnabled(false); + heapDumpFileField.setEnabled(false); } memField.setText(initialMemValue); + heapDumpFileField.setText(DEFAULT_HEAP_DUMP_FILE_FIELD); } setTempDirEnabled(); valid(); //ensure the error messages are up to date @@ -585,7 +611,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { reportBranding.setAgencyLogoPath(""); } UserPreferences.setMaxSolrVMSize((int) solrMaxHeapSpinner.getValue()); - if (memField.isEnabled()) { //if the field could of been changed we need to try and save it + if (isJVMHeapSettingsCapable()) { //if the field could of been changed we need to try and save it try { writeEtcConfFile(); } catch (IOException ex) { @@ -600,10 +626,12 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { * @return True if valid; false otherwise. */ boolean valid() { - return isAgencyLogoPathValid() && - isMemFieldValid() && - isLogNumFieldValid() && - isHeapPathValid(); + boolean agencyValid = isAgencyLogoPathValid(); + boolean memFieldValid = isMemFieldValid(); + boolean logNumValid = isLogNumFieldValid(); + boolean heapPathValid = isHeapPathValid(); + + return agencyValid && memFieldValid && logNumValid && heapPathValid; } /** diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED index bcf95a19a9..ad0aee80d1 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED @@ -12,6 +12,12 @@ 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_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsMessage=File already exists. Please select a new location. +AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsTitle=File Already Exists +AutopsyOptionsPanel_isHeapPathValid_developerMode=Cannot change heap dump path while in developer mode. +AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist=Selected directory does not exist. +AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists=A file already exists at this location. +AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=Changing heap dump path settings only enabled for 64 bit version. AutopsyOptionsPanel_storeTempDir_onChoiceError_description=There was an error updating temporary directory choice selection. AutopsyOptionsPanel_storeTempDir_onChoiceError_title=Error Saving Temporary Directory Choice # {0} - path @@ -311,3 +317,7 @@ 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. +AutopsyOptionsPanel.heapDumpFileField.text= +AutopsyOptionsPanel.heapDumpBrowseButton.text=Browse +AutopsyOptionsPanel.heapFileLabel.text=Heap Dump Location: +AutopsyOptionsPanel.heapFieldValidationLabel.text= From ca953ca9d94a0f309c3c1d458504cdc0979de5a4 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 1 Apr 2021 21:15:16 -0400 Subject: [PATCH 03/12] bug fixes --- .../corecomponents/AutopsyOptionsPanel.java | 121 ++++++++++-------- 1 file changed, 68 insertions(+), 53 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index f8cb96ae5b..d7a3284cb3 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -42,7 +42,6 @@ import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.tools.ant.types.Commandline; import org.netbeans.spi.options.OptionsPanelController; @@ -221,7 +220,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { */ private static File getUserFolderConfFile() { String confFileName = UserPreferences.getAppName() + CONFIG_FILE_EXTENSION; - File userFolder = PlatformUtil.getUserDirectory(); + File userFolder = new File("C:\\Users\\gregd\\AppData\\Roaming\\autopsy"); // PlatformUtil.getUserDirectory(); File userEtcFolder = new File(userFolder, ETC_FOLDER_NAME); if (!userEtcFolder.exists()) { userEtcFolder.mkdir(); @@ -230,12 +229,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } private static final String JVM_SETTINGS_REGEX_PARAM = "options"; - private static final Pattern JVM_SETTINGS_REGEX = Pattern.compile("^\\s*default_options\\s*=\\s*\"?(?<" + JVM_SETTINGS_REGEX_PARAM + ">.+?)\"?\\s*$"); + private static final String JVM_SETTINGS_REGEX_STR = "^\\s*default_options\\s*=\\s*\"?(?<" + JVM_SETTINGS_REGEX_PARAM + ">.+?)\"?\\s*$"; + private static final Pattern JVM_SETTINGS_REGEX = Pattern.compile(JVM_SETTINGS_REGEX_STR); private static final String XMX_REGEX_PARAM = "mem"; private static final String XMX_REGEX_STR = "^\\s*\\-J\\-Xmx(?<" + XMX_REGEX_PARAM + ">.+?)\\s*$"; private static final Pattern XMX_REGEX = Pattern.compile(XMX_REGEX_STR); private static final String HEAP_DUMP_REGEX_PARAM = "path"; - private static final String HEAP_DUMP_REGEX_STR = "^\\s*\\-J\\-XX:HeapDumpPath=\\s*(\\\")?(?<" + HEAP_DUMP_REGEX_PARAM + ">.+?)(\\\")?\\s*$"; + private static final String HEAP_DUMP_REGEX_STR = "^\\s*\\-J\\-XX:HeapDumpPath=\\s*'?(?<" + HEAP_DUMP_REGEX_PARAM + ">.+?)'?\\s*$"; private static final Pattern HEAP_DUMP_REGEX = Pattern.compile(HEAP_DUMP_REGEX_STR); /** @@ -251,20 +251,26 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { */ private static String updateConfLine(String line, String memText, String heapText) { Matcher match = JVM_SETTINGS_REGEX.matcher(line); - if (match != null) { + if (match.find()) { // split on command line arguments - String unescaped = StringEscapeUtils.unescapeJava(match.group(JVM_SETTINGS_REGEX_PARAM)); - String[] parsedArgs = Commandline.translateCommandline(unescaped); + String[] parsedArgs = Commandline.translateCommandline(match.group(JVM_SETTINGS_REGEX_PARAM)); - String newArgs = Stream.concat(Stream.of(parsedArgs) + String memString = "-J-Xmx" + memText.replaceAll("[^\\d]", "") + "g"; + + // only add in heap path argument if a heap path is specified + String heapString = StringUtils.isNotBlank(heapText) ? + String.format("-J-XX:HeapDumpPath='%s'", heapText) : + null; + + Stream argsNoMemHeap = Stream.of(parsedArgs) // remove saved version of memory and heap dump path - .filter(s -> !s.matches(XMX_REGEX_STR) && !s.matches(HEAP_DUMP_REGEX_STR)), - Stream.of( - "-J-Xmx" + memText.replaceAll("[^\\d]", "") + "g", - String.format("-J-XX:HeapDumpPath=\"%s\"", heapText == null ? "" : StringEscapeUtils.escapeJava(heapText)))) + .filter(s -> !s.matches(XMX_REGEX_STR) && !s.matches(HEAP_DUMP_REGEX_STR)); + + String newArgs = Stream.concat(argsNoMemHeap, Stream.of(memString, heapString)) + .filter(s -> s != null) .collect(Collectors.joining(" ")); - return String.format("default_options=\"%s\"", StringEscapeUtils.escapeJava(newArgs)); + return String.format("default_options=\"%s\"", newArgs); }; return line; @@ -329,33 +335,24 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { */ private ConfValues getEtcConfValues() throws IOException { File userConfFile = getUserFolderConfFile(); - String[] confLines = userConfFile.exists() ? + String[] args = userConfFile.exists() ? getDefaultsFromFileContents(readConfFile(userConfFile)) : getDefaultsFromFileContents(readConfFile(getInstallFolderConfFile())); String heapFile = ""; String memSize = ""; - - for (String confLine: confLines) { - Matcher match = JVM_SETTINGS_REGEX.matcher(confLine); - if (match != null) { - String unescaped = StringEscapeUtils.unescapeJava(match.group(JVM_SETTINGS_REGEX_PARAM)); - String[] args = Commandline.translateCommandline(unescaped); - - for (String arg : args) { - Matcher memMatch = XMX_REGEX.matcher(arg); - if (memMatch != null) { - memSize = memMatch.group(XMX_REGEX_PARAM); - continue; - } - - Matcher heapFileMatch = HEAP_DUMP_REGEX.matcher(arg); - if (heapFileMatch != null) { - heapFile = StringEscapeUtils.unescapeJava(heapFileMatch.group(HEAP_DUMP_REGEX_PARAM)); - continue; - } - } - break; + + for (String arg : args) { + Matcher memMatch = XMX_REGEX.matcher(arg); + if (memMatch.find()) { + memSize = memMatch.group(XMX_REGEX_PARAM); + continue; + } + + Matcher heapFileMatch = HEAP_DUMP_REGEX.matcher(arg); + if (heapFileMatch.find()) { + heapFile = heapFileMatch.group(HEAP_DUMP_REGEX_PARAM); + continue; } } @@ -376,32 +373,40 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { }) private boolean isHeapPathValid() { if (Version.getBuildType() == Version.Type.DEVELOPMENT) { + heapFieldValidationLabel.setVisible(true); heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_developerMode()); return true; } if (!PlatformUtil.is64BitJVM()) { + heapFieldValidationLabel.setVisible(true); heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_not64BitMachine()); return true; } - File curHeapFile = new File(heapDumpFileField.getText()); - boolean isDirectory = curHeapFile.isDirectory(); - boolean exists = curHeapFile.exists(); - if (exists && !isDirectory) { - heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists()); - return false; - } - - - if (!exists) { - File parentDir = curHeapFile.getParentFile(); - if (parentDir == null || !parentDir.exists()) { - heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist()); + //allow blank field as the default will be used + if (StringUtils.isNotBlank(heapDumpFileField.getText())) { + File curHeapFile = new File(heapDumpFileField.getText()); + boolean isDirectory = curHeapFile.isDirectory(); + boolean exists = curHeapFile.exists(); + if (exists && !isDirectory) { + heapFieldValidationLabel.setVisible(true); + heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists()); return false; + } + + + if (!exists) { + File parentDir = curHeapFile.getParentFile(); + if (parentDir == null || !parentDir.exists()) { + heapFieldValidationLabel.setVisible(true); + heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist()); + return false; + } } } + heapFieldValidationLabel.setVisible(false); heapFieldValidationLabel.setText(""); return true; } @@ -441,11 +446,17 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { * options is not present. */ private static String[] getDefaultsFromFileContents(List list) { - Optional defaultSettings = list.stream().filter(line -> line.startsWith("default_options=")).findFirst(); + Optional defaultSettings = list.stream() + .filter(line -> line.matches(JVM_SETTINGS_REGEX_STR)) + .findFirst(); if (defaultSettings.isPresent()) { - return defaultSettings.get().replace("default_options=", "").replaceAll("\"", "").split(" "); + Matcher match = JVM_SETTINGS_REGEX.matcher(defaultSettings.get()); + if (match.find()) { + return Commandline.translateCommandline(match.group(JVM_SETTINGS_REGEX_PARAM)); + } } + return new String[]{}; } @@ -493,21 +504,25 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } catch (IOException ex) { logger.log(Level.WARNING, "Error loading image from previously saved agency logo path", ex); } + + boolean confLoaded = false; if (isJVMHeapSettingsCapable()) { try { ConfValues confValues = getEtcConfValues(); heapDumpFileField.setText(confValues.getHeapDumpPath()); initialMemValue = Long.toString(getCurrentJvmMaxMemoryInGB(confValues.getXmxVal())); + confLoaded = true; } catch (IOException ex) { logger.log(Level.SEVERE, "Can't read current Jvm max memory setting from file", ex); memField.setEnabled(false); heapDumpFileField.setText(DEFAULT_HEAP_DUMP_FILE_FIELD); - heapDumpBrowseButton.setEnabled(false); - heapDumpFileField.setEnabled(false); } memField.setText(initialMemValue); - heapDumpFileField.setText(DEFAULT_HEAP_DUMP_FILE_FIELD); } + + heapDumpBrowseButton.setEnabled(confLoaded); + heapDumpFileField.setEnabled(confLoaded); + setTempDirEnabled(); valid(); //ensure the error messages are up to date } From b4c961b536cc7f2a9ff5b217133e146be555c6f7 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 1 Apr 2021 22:13:53 -0400 Subject: [PATCH 04/12] fix for missed field --- .../sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index d7a3284cb3..43807eb505 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -220,7 +220,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { */ private static File getUserFolderConfFile() { String confFileName = UserPreferences.getAppName() + CONFIG_FILE_EXTENSION; - File userFolder = new File("C:\\Users\\gregd\\AppData\\Roaming\\autopsy"); // PlatformUtil.getUserDirectory(); + File userFolder = PlatformUtil.getUserDirectory(); File userEtcFolder = new File(userFolder, ETC_FOLDER_NAME); if (!userEtcFolder.exists()) { userEtcFolder.mkdir(); From 313ee1dd531931d012dc96acbfd7394ceecafb89 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 2 Apr 2021 09:00:37 -0400 Subject: [PATCH 05/12] fixes --- .../corecomponents/AutopsyOptionsPanel.java | 18 +++++++++++++----- .../autopsy/corecomponents/Bundle.properties | 2 +- .../corecomponents/Bundle.properties-MERGED | 3 ++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 43807eb505..ed2c6ea724 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -235,7 +235,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private static final String XMX_REGEX_STR = "^\\s*\\-J\\-Xmx(?<" + XMX_REGEX_PARAM + ">.+?)\\s*$"; private static final Pattern XMX_REGEX = Pattern.compile(XMX_REGEX_STR); private static final String HEAP_DUMP_REGEX_PARAM = "path"; - private static final String HEAP_DUMP_REGEX_STR = "^\\s*\\-J\\-XX:HeapDumpPath=\\s*'?(?<" + HEAP_DUMP_REGEX_PARAM + ">.+?)'?\\s*$"; + private static final String HEAP_DUMP_REGEX_STR = "^\\s*\\-J\\-XX:HeapDumpPath=\\s*(?<" + HEAP_DUMP_REGEX_PARAM + ">.+?)\\s*$"; private static final Pattern HEAP_DUMP_REGEX = Pattern.compile(HEAP_DUMP_REGEX_STR); /** @@ -259,7 +259,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { // only add in heap path argument if a heap path is specified String heapString = StringUtils.isNotBlank(heapText) ? - String.format("-J-XX:HeapDumpPath='%s'", heapText) : + String.format("-J-XX:HeapDumpPath=%s", heapText) : null; Stream argsNoMemHeap = Stream.of(parsedArgs) @@ -369,7 +369,8 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { "AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists=A file already exists at this location.", "AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist=Selected directory does not exist.", "AutopsyOptionsPanel_isHeapPathValid_developerMode=Cannot change heap dump path while in developer mode.", - "AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=Changing heap dump path settings only enabled for 64 bit version." + "AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=Changing heap dump path settings only enabled for 64 bit version.", + "AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no spaces or quotes." }) private boolean isHeapPathValid() { if (Version.getBuildType() == Version.Type.DEVELOPMENT) { @@ -385,8 +386,15 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } //allow blank field as the default will be used - if (StringUtils.isNotBlank(heapDumpFileField.getText())) { - File curHeapFile = new File(heapDumpFileField.getText()); + if (StringUtils.isNotBlank(heapDumpFileField.getText())) { + String heapText = heapDumpFileField.getText().trim(); + if (heapText.contains(" ") || heapText.contains("\"") || heapText.contains("'")) { + heapFieldValidationLabel.setVisible(true); + heapFieldValidationLabel.setText(Bundle.AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters()); + return false; + } + + File curHeapFile = new File(heapText); boolean isDirectory = curHeapFile.isDirectory(); boolean exists = curHeapFile.exists(); if (exists && !isDirectory) { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 278f4828e8..2deaab0d3b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -253,5 +253,5 @@ AutopsyOptionsPanel.tempCustomField.text= AutopsyOptionsPanel.tempOnCustomNoPath.text=Please select a path for the custom root temp directory. AutopsyOptionsPanel.heapDumpFileField.text= AutopsyOptionsPanel.heapDumpBrowseButton.text=Browse -AutopsyOptionsPanel.heapFileLabel.text=Heap Dump Location: +AutopsyOptionsPanel.heapFileLabel.text=Custom Heap Dump Location: AutopsyOptionsPanel.heapFieldValidationLabel.text= diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED index ad0aee80d1..67222493e7 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED @@ -17,6 +17,7 @@ AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsTitle=F AutopsyOptionsPanel_isHeapPathValid_developerMode=Cannot change heap dump path while in developer mode. AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist=Selected directory does not exist. AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists=A file already exists at this location. +AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no spaces or quotes. AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=Changing heap dump path settings only enabled for 64 bit version. AutopsyOptionsPanel_storeTempDir_onChoiceError_description=There was an error updating temporary directory choice selection. AutopsyOptionsPanel_storeTempDir_onChoiceError_title=Error Saving Temporary Directory Choice @@ -319,5 +320,5 @@ AutopsyOptionsPanel.tempCustomField.text= AutopsyOptionsPanel.tempOnCustomNoPath.text=Please select a path for the custom root temp directory. AutopsyOptionsPanel.heapDumpFileField.text= AutopsyOptionsPanel.heapDumpBrowseButton.text=Browse -AutopsyOptionsPanel.heapFileLabel.text=Heap Dump Location: +AutopsyOptionsPanel.heapFileLabel.text=Custom Heap Dump Location: AutopsyOptionsPanel.heapFieldValidationLabel.text= From d7a617ed22853c226147a9aa29b3711bf7674faf Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 7 Apr 2021 11:53:39 -0400 Subject: [PATCH 06/12] fixes --- .../corecomponents/AutopsyOptionsPanel.java | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index ed2c6ea724..9a3f56dffa 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -112,6 +112,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { tempDirChooser.setMultiSelectionEnabled(false); heapFileChooser = new JFileChooser(); + heapFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); heapFileChooser.setMultiSelectionEnabled(false); if (!isJVMHeapSettingsCapable()) { @@ -235,7 +236,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private static final String XMX_REGEX_STR = "^\\s*\\-J\\-Xmx(?<" + XMX_REGEX_PARAM + ">.+?)\\s*$"; private static final Pattern XMX_REGEX = Pattern.compile(XMX_REGEX_STR); private static final String HEAP_DUMP_REGEX_PARAM = "path"; - private static final String HEAP_DUMP_REGEX_STR = "^\\s*\\-J\\-XX:HeapDumpPath=\\s*(?<" + HEAP_DUMP_REGEX_PARAM + ">.+?)\\s*$"; + private static final String HEAP_DUMP_REGEX_STR = "^\\s*\\-J\\-XX:HeapDumpPath=(\\\")?\\s*(?<" + HEAP_DUMP_REGEX_PARAM + ">.+?)\\s*(\\\")?$"; private static final Pattern HEAP_DUMP_REGEX = Pattern.compile(HEAP_DUMP_REGEX_STR); /** @@ -258,9 +259,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { String memString = "-J-Xmx" + memText.replaceAll("[^\\d]", "") + "g"; // only add in heap path argument if a heap path is specified - String heapString = StringUtils.isNotBlank(heapText) ? - String.format("-J-XX:HeapDumpPath=%s", heapText) : - null; + String heapString = null; + if (StringUtils.isNotBlank(heapText)) { + while (heapText.endsWith("\\") && heapText.length() > 0) { + heapText = heapText.substring(0, heapText.length() - 1); + } + + heapString = String.format("-J-XX:HeapDumpPath=\"%s\"", heapText); + } Stream argsNoMemHeap = Stream.of(parsedArgs) // remove saved version of memory and heap dump path @@ -370,7 +376,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { "AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist=Selected directory does not exist.", "AutopsyOptionsPanel_isHeapPathValid_developerMode=Cannot change heap dump path while in developer mode.", "AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=Changing heap dump path settings only enabled for 64 bit version.", - "AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no spaces or quotes." + "AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no quotes." }) private boolean isHeapPathValid() { if (Version.getBuildType() == Version.Type.DEVELOPMENT) { @@ -388,7 +394,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { //allow blank field as the default will be used if (StringUtils.isNotBlank(heapDumpFileField.getText())) { String heapText = heapDumpFileField.getText().trim(); - if (heapText.contains(" ") || heapText.contains("\"") || heapText.contains("'")) { + if (heapText.contains("\"") || heapText.contains("'")) { heapFieldValidationLabel.setVisible(true); heapFieldValidationLabel.setText(Bundle.AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters()); return false; @@ -1372,20 +1378,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { heapFileChooser.setCurrentDirectory(new File(oldHeapPath)); } - int returnState = heapFileChooser.showSaveDialog(this); + int returnState = heapFileChooser.showOpenDialog(this); if (returnState == JFileChooser.APPROVE_OPTION) { - File selectedFile = heapFileChooser.getSelectedFile(); - // heap dump path can be file or directory: https://www.oracle.com/java/technologies/javase/vmoptions-jsp.html - if (selectedFile.exists() && !selectedFile.isDirectory()) { - JOptionPane.showMessageDialog(this, - Bundle.AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsMessage(), - Bundle.AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsTitle(), - JOptionPane.ERROR_MESSAGE); - - } else { - heapDumpFileField.setText(selectedFile.getAbsolutePath()); - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - } + File selectedDirectory = heapFileChooser.getSelectedFile(); + heapDumpFileField.setText(selectedDirectory.getAbsolutePath()); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } }//GEN-LAST:event_heapDumpBrowseButtonActionPerformed From ddbd6452ac0ec0fc9726bc5f42c1ba1a947ce0a2 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 7 Apr 2021 19:23:36 -0400 Subject: [PATCH 07/12] enforce hprof extension --- .../autopsy/corecomponents/AutopsyOptionsPanel.java | 9 ++++++++- .../autopsy/corecomponents/Bundle.properties-MERGED | 4 +++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 9a3f56dffa..36ffa1a971 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -86,6 +86,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private final JFileChooser tempDirChooser; private static final String ETC_FOLDER_NAME = "etc"; private static final String CONFIG_FILE_EXTENSION = ".conf"; + private static final String HEAP_DUMP_FILE_EXTENSION = "hprof"; private static final long ONE_BILLION = 1000000000L; //used to roughly convert system memory from bytes to gigabytes private static final int MEGA_IN_GIGA = 1024; //used to convert memory settings saved as megabytes to gigabytes private static final int JVM_MEMORY_STEP_SIZE_MB = 512; @@ -376,7 +377,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { "AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist=Selected directory does not exist.", "AutopsyOptionsPanel_isHeapPathValid_developerMode=Cannot change heap dump path while in developer mode.", "AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=Changing heap dump path settings only enabled for 64 bit version.", - "AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no quotes." + "AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no quotes.", + "# {0} - heapDumpExtension", + "AutopsyOptionsPanel_isHeapPathValid_invalidExtension=Please make sure your file ends with a {0} extension." }) private boolean isHeapPathValid() { if (Version.getBuildType() == Version.Type.DEVELOPMENT) { @@ -416,6 +419,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { heapFieldValidationLabel.setVisible(true); heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist()); return false; + } else if (!curHeapFile.getAbsolutePath().trim().toLowerCase().endsWith("." + HEAP_DUMP_FILE_EXTENSION)) { + heapFieldValidationLabel.setVisible(true); + heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_invalidExtension(HEAP_DUMP_FILE_EXTENSION)); + return false; } } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED index 67222493e7..12bebd1a95 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED @@ -17,7 +17,9 @@ AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsTitle=F AutopsyOptionsPanel_isHeapPathValid_developerMode=Cannot change heap dump path while in developer mode. AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist=Selected directory does not exist. AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists=A file already exists at this location. -AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no spaces or quotes. +AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no quotes. +# {0} - heapDumpExtension +AutopsyOptionsPanel_isHeapPathValid_invalidExtension=Please make sure your file ends with a {0} extension. AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=Changing heap dump path settings only enabled for 64 bit version. AutopsyOptionsPanel_storeTempDir_onChoiceError_description=There was an error updating temporary directory choice selection. AutopsyOptionsPanel_storeTempDir_onChoiceError_title=Error Saving Temporary Directory Choice From 9ad5cf30d360e27f14f4151751b06b67bd723969 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 8 Apr 2021 08:30:44 -0400 Subject: [PATCH 08/12] just custom heap dump directory --- .../corecomponents/AutopsyOptionsPanel.java | 28 +++---------------- .../corecomponents/Bundle.properties-MERGED | 5 +--- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 36ffa1a971..edbef370b2 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -86,7 +86,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private final JFileChooser tempDirChooser; private static final String ETC_FOLDER_NAME = "etc"; private static final String CONFIG_FILE_EXTENSION = ".conf"; - private static final String HEAP_DUMP_FILE_EXTENSION = "hprof"; private static final long ONE_BILLION = 1000000000L; //used to roughly convert system memory from bytes to gigabytes private static final int MEGA_IN_GIGA = 1024; //used to convert memory settings saved as megabytes to gigabytes private static final int JVM_MEMORY_STEP_SIZE_MB = 512; @@ -373,13 +372,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { * @return True if the heap path is valid. */ @Messages({ - "AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists=A file already exists at this location.", - "AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist=Selected directory does not exist.", + "AutopsyOptionsPanel_isHeapPathValid_selectValidDirectory=Please select an existing directory.", "AutopsyOptionsPanel_isHeapPathValid_developerMode=Cannot change heap dump path while in developer mode.", "AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=Changing heap dump path settings only enabled for 64 bit version.", - "AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no quotes.", - "# {0} - heapDumpExtension", - "AutopsyOptionsPanel_isHeapPathValid_invalidExtension=Please make sure your file ends with a {0} extension." + "AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no quotes." }) private boolean isHeapPathValid() { if (Version.getBuildType() == Version.Type.DEVELOPMENT) { @@ -404,26 +400,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } File curHeapFile = new File(heapText); - boolean isDirectory = curHeapFile.isDirectory(); - boolean exists = curHeapFile.exists(); - if (exists && !isDirectory) { + if (!curHeapFile.exists() || !curHeapFile.isDirectory()) { heapFieldValidationLabel.setVisible(true); - heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists()); + heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_selectValidDirectory()); return false; - } - - - if (!exists) { - File parentDir = curHeapFile.getParentFile(); - if (parentDir == null || !parentDir.exists()) { - heapFieldValidationLabel.setVisible(true); - heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist()); - return false; - } else if (!curHeapFile.getAbsolutePath().trim().toLowerCase().endsWith("." + HEAP_DUMP_FILE_EXTENSION)) { - heapFieldValidationLabel.setVisible(true); - heapFieldValidationLabel.setText(Bundle.AutopsyOptionsPanel_isHeapPathValid_invalidExtension(HEAP_DUMP_FILE_EXTENSION)); - return false; - } } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED index 12bebd1a95..16fa8d0e5f 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED @@ -15,12 +15,9 @@ AutopsyOptionsPanel.memFieldValidationLabel.underMinMemory.text=Value must be at AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsMessage=File already exists. Please select a new location. AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsTitle=File Already Exists AutopsyOptionsPanel_isHeapPathValid_developerMode=Cannot change heap dump path while in developer mode. -AutopsyOptionsPanel_isHeapPathValid_directoryDoesNotExist=Selected directory does not exist. -AutopsyOptionsPanel_isHeapPathValid_fileAlreadyExists=A file already exists at this location. AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=Please select a path with no quotes. -# {0} - heapDumpExtension -AutopsyOptionsPanel_isHeapPathValid_invalidExtension=Please make sure your file ends with a {0} extension. AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=Changing heap dump path settings only enabled for 64 bit version. +AutopsyOptionsPanel_isHeapPathValid_selectValidDirectory=Please select an existing directory. AutopsyOptionsPanel_storeTempDir_onChoiceError_description=There was an error updating temporary directory choice selection. AutopsyOptionsPanel_storeTempDir_onChoiceError_title=Error Saving Temporary Directory Choice # {0} - path From b17390ffac01c7531c3a20d47107645b1eeff5dd Mon Sep 17 00:00:00 2001 From: apriestman Date: Thu, 8 Apr 2021 09:46:32 -0400 Subject: [PATCH 09/12] Try handling host deleted event --- Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java index 433a98972c..e53e392f49 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java @@ -78,13 +78,14 @@ public class HostNode extends DisplayableItemNode { } /** - * Listener for handling DATA_SOURCE_ADDED events. + * Listener for handling DATA_SOURCE_ADDED / HOST_DELETED events. */ private final PropertyChangeListener dataSourceAddedPcl = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { + if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString()) + || eventType.equals(Case.Events.HOSTS_DELETED.toString())) { refresh(true); } } @@ -92,12 +93,12 @@ public class HostNode extends DisplayableItemNode { @Override protected void addNotify() { - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), dataSourceAddedPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), dataSourceAddedPcl); } @Override protected void removeNotify() { - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), dataSourceAddedPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), dataSourceAddedPcl); } @Override From 0d223f37da0ab684626497f12ade44baec9ccf65 Mon Sep 17 00:00:00 2001 From: apriestman Date: Thu, 8 Apr 2021 10:16:05 -0400 Subject: [PATCH 10/12] Improve comment --- Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java index e53e392f49..a98bdb61dd 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java @@ -79,6 +79,8 @@ public class HostNode extends DisplayableItemNode { /** * Listener for handling DATA_SOURCE_ADDED / HOST_DELETED events. + * A host may have been deleted as part of a merge, which means its data sources could + * have moved to a different host requiring a refresh. */ private final PropertyChangeListener dataSourceAddedPcl = new PropertyChangeListener() { @Override From e7ef17d1b46e5dd2211442ab8ea353348a34f976 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 8 Apr 2021 13:22:19 -0400 Subject: [PATCH 11/12] changes for case directory temp path --- .../UserMachinePreferences.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/machinesettings/UserMachinePreferences.java b/Core/src/org/sleuthkit/autopsy/machinesettings/UserMachinePreferences.java index ef7b138ef0..f0aa9b06d5 100644 --- a/Core/src/org/sleuthkit/autopsy/machinesettings/UserMachinePreferences.java +++ b/Core/src/org/sleuthkit/autopsy/machinesettings/UserMachinePreferences.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.machinesettings; import java.io.File; import java.nio.file.Paths; import java.util.Optional; +import java.util.logging.Level; import java.util.prefs.Preferences; import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; @@ -30,12 +31,15 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.FileUtil; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.NetworkUtils; /** * Provides case-specific settings like the user-specified temp folder. */ public final class UserMachinePreferences { + private static final Logger logger = Logger.getLogger(UserMachinePreferences.class.getName()); private static final Preferences preferences = NbPreferences.forModule(UserMachinePreferences.class); /** @@ -81,6 +85,17 @@ public final class UserMachinePreferences { private static final TempDirChoice DEFAULT_CHOICE = TempDirChoice.SYSTEM; + /** + * Returns the name of this computer's host name to be used as a directory + * in some instances. + * + * @return The name of this computer's host name to be used as a directory + * in some instances. + */ + private static String getHostName() { + return NetworkUtils.getLocalHostName(); + } + /** * @return A subdirectory of java.io.tmpdir. */ @@ -94,8 +109,16 @@ public final class UserMachinePreferences { */ private static File getCaseTempDirFile() { try { - String caseDirStr = Case.getCurrentCaseThrows().getCaseDirectory(); - return Paths.get(caseDirStr, CASE_SUBDIR).toFile(); + Case autCase = Case.getCurrentCaseThrows(); + String caseDirStr = autCase.getCaseDirectory(); + switch (autCase.getCaseType()) { + case MULTI_USER_CASE: return Paths.get(caseDirStr, getHostName(), CASE_SUBDIR).toFile(); + case SINGLE_USER_CASE: return Paths.get(caseDirStr, CASE_SUBDIR).toFile(); + default: + logger.log(Level.SEVERE, "Unknown case type: " + autCase.getCaseType()); + return getSystemTempDirFile(); + } + } catch (NoCurrentCaseException ex) { return getSystemTempDirFile(); } @@ -111,7 +134,7 @@ public final class UserMachinePreferences { private static File getCustomTempDirFile() { String customDirectory = getCustomTempDirectory(); return (StringUtils.isBlank(customDirectory)) - ? getSystemTempDirFile() : Paths.get(customDirectory, AUTOPSY_SUBDIR).toFile(); + ? getSystemTempDirFile() : Paths.get(customDirectory, AUTOPSY_SUBDIR, getHostName()).toFile(); } /** @@ -214,8 +237,9 @@ public final class UserMachinePreferences { /** * Sets the temp directory choice (i.e. system, case, custom). + * * @param tempDirChoice The choice (must be non-null). - * @throws UserMachinePreferencesException + * @throws UserMachinePreferencesException */ public static void setTempDirChoice(TempDirChoice tempDirChoice) throws UserMachinePreferencesException { if (tempDirChoice == null) { From 393c22439f0266ce0d8db3f843a820062d1ad789 Mon Sep 17 00:00:00 2001 From: apriestman Date: Fri, 9 Apr 2021 07:56:11 -0400 Subject: [PATCH 12/12] More CR test fixes --- .../datamodel/CentralRepoAccountsTest.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccountsTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccountsTest.java index 2e3080617e..537835bc01 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccountsTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccountsTest.java @@ -120,23 +120,21 @@ public class CentralRepoAccountsTest extends TestCase { public void testRejectionOfDeviceAccountType() { try { Account.Type deviceAccount = Account.Type.DEVICE; - CentralRepository.getInstance() + Optional optType = CentralRepository.getInstance() .getAccountTypeByName(deviceAccount.getTypeName()); - Assert.fail("Expected an exception from getAccountTypeByName() when" - + " querying the device account type"); + Assert.assertFalse(optType.isPresent()); } catch (CentralRepoException ex) { - // Pass + Assert.fail("Didn't expect an exception here. Exception: " + ex); } } public void testNonExistentAccountType() { try { - CentralRepository.getInstance() + Optional optType = CentralRepository.getInstance() .getAccountTypeByName("NotARealAccountType"); - Assert.fail("Expected an exception from getAccountTypeByName()" - + " when querying a non-existent account type"); + Assert.assertFalse(optType.isPresent()); } catch (CentralRepoException ex) { - // Pass + Assert.fail("Didn't expect an exception here. Exception: " + ex); } }