diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 54dd21e3c9..cae89e41ce 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -190,7 +190,6 @@ ImageFilePanel.sectorSizeLabel.text=Sector size: LocalDiskPanel.sectorSizeLabel.text=Sector Size: LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default LocalFilesPanel.errorLabel.text=Error Label -LocalFilesPanel.selectedPaths.toolTipText= LocalFilesPanel.clearButton.toolTipText=Clears currently selected local file paths LocalFilesPanel.clearButton.text=Clear LocalFilesPanel.selectButton.actionCommand=Add @@ -263,8 +262,11 @@ AddImageWizardSelectHostVisual.specifyNewHostTextField.text= AddImageWizardSelectHostVisual.specifyNewHostRadio.text=Specify new host name AddImageWizardSelectHostVisual.generateNewRadio.text=Generate new host name based on data source name AddImageWizardSelectHostVisual.validationMessage.text=\ +LocalFilesPanel.deleteButon.text=Delete LocalFilesPanel.createTimeCheckBox.text=Creation Time - Often changed when a file is copied LocalFilesPanel.modifiedTimeCheckBox.text=\ Modified Time - Often not changed when a file is copied LocalFilesPanel.jLabel2.text=NOTE: Time stamps may have changed when the files were copied to the current location. LocalFilesPanel.timestampToIncludeLabel.text=Timestamps To Include: LocalFilesPanel.accessTimeCheckBox.text=Access Time - Can be changed when the file is opened +LocalFilesPanel.timeStampToIncludeLabel.text=Timestamps To Include: +LocalFilesPanel.timeStampNoteLabel.text=NOTE: Time stamps may have changed when the files were copied to the current location. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED index e5dc718df7..b671940118 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED @@ -417,7 +417,6 @@ ImageFilePanel.sectorSizeLabel.text=Sector size: LocalDiskPanel.sectorSizeLabel.text=Sector Size: LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default LocalFilesPanel.errorLabel.text=Error Label -LocalFilesPanel.selectedPaths.toolTipText= LocalFilesPanel.clearButton.toolTipText=Clears currently selected local file paths LocalFilesPanel.clearButton.text=Clear LocalFilesPanel.selectButton.actionCommand=Add @@ -490,8 +489,11 @@ AddImageWizardSelectHostVisual.specifyNewHostTextField.text= AddImageWizardSelectHostVisual.specifyNewHostRadio.text=Specify new host name AddImageWizardSelectHostVisual.generateNewRadio.text=Generate new host name based on data source name AddImageWizardSelectHostVisual.validationMessage.text=\ +LocalFilesPanel.deleteButon.text=Delete LocalFilesPanel.createTimeCheckBox.text=Creation Time - Often changed when a file is copied LocalFilesPanel.modifiedTimeCheckBox.text=\ Modified Time - Often not changed when a file is copied LocalFilesPanel.jLabel2.text=NOTE: Time stamps may have changed when the files were copied to the current location. LocalFilesPanel.timestampToIncludeLabel.text=Timestamps To Include: LocalFilesPanel.accessTimeCheckBox.text=Access Time - Can be changed when the file is opened +LocalFilesPanel.timeStampToIncludeLabel.text=Timestamps To Include: +LocalFilesPanel.timeStampNoteLabel.text=NOTE: Time stamps may have changed when the files were copied to the current location. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form index 69014dd195..358f4e7fd5 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form @@ -27,185 +27,139 @@ + - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + @@ -215,6 +169,11 @@ + + + + + @@ -222,53 +181,114 @@ + + + + + - + - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -278,6 +298,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index 58dba0ccef..0bdb52b4fd 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -19,31 +19,33 @@ package org.sleuthkit.autopsy.casemodule; import java.io.File; -import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; -import java.util.Set; -import java.util.TreeSet; import javax.swing.JFileChooser; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.swing.AbstractListModel; import javax.swing.JOptionPane; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PathValidator; /** - * A panel which allows the user to select local files and/or directories. + * A panel which allows the user to select local files and/or directories. */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives final class LocalFilesPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; - private final Set currentFiles = new TreeSet<>(); //keep currents in a set to disallow duplicates per add private boolean enableNext = false; private static final Logger logger = Logger.getLogger(LocalFilesPanel.class.getName()); private String displayName = ""; + private final LocalFilesModel listModel = new LocalFilesModel(); /** * Creates new form LocalFilesPanel @@ -56,7 +58,8 @@ final class LocalFilesPanel extends javax.swing.JPanel { private void customInit() { localFileChooser.setMultiSelectionEnabled(true); errorLabel.setVisible(false); - selectedPaths.setText(""); + this.fileList.setModel(listModel); + listModel.clear(); this.displayNameLabel.setText(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.displayNameLabel.text")); } @@ -68,27 +71,33 @@ final class LocalFilesPanel extends javax.swing.JPanel { @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; localFileChooser = new javax.swing.JFileChooser(); - jPanel1 = new javax.swing.JPanel(); selectButton = new javax.swing.JButton(); + deleteButon = new javax.swing.JButton(); clearButton = new javax.swing.JButton(); - selectedPathsScrollPane = new javax.swing.JScrollPane(); - selectedPaths = new javax.swing.JTextArea(); + javax.swing.JScrollPane fileListScrollpane = new javax.swing.JScrollPane(); + fileList = new javax.swing.JList<>(); + javax.swing.JPanel displayNamePanel = new javax.swing.JPanel(); changeNameButton = new javax.swing.JButton(); displayNameLabel = new javax.swing.JLabel(); - timestampToIncludeLabel = new javax.swing.JLabel(); + javax.swing.JPanel padding = new javax.swing.JPanel(); + javax.swing.JLabel timeStampToIncludeLabel = new javax.swing.JLabel(); + modifiedTimeCheckBox = new javax.swing.JCheckBox(); createTimeCheckBox = new javax.swing.JCheckBox(); accessTimeCheckBox = new javax.swing.JCheckBox(); - modifiedTimeCheckBox = new javax.swing.JCheckBox(); - jLabel2 = new javax.swing.JLabel(); + javax.swing.JLabel timeStampNoteLabel = new javax.swing.JLabel(); errorLabel = new javax.swing.JLabel(); + javax.swing.JPanel paddingBottom = new javax.swing.JPanel(); localFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonText")); // NOI18N localFileChooser.setApproveButtonToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonToolTipText")); // NOI18N localFileChooser.setDialogTitle(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.dialogTitle")); // NOI18N localFileChooser.setFileSelectionMode(javax.swing.JFileChooser.FILES_AND_DIRECTORIES); + setLayout(new java.awt.GridBagLayout()); + org.openide.awt.Mnemonics.setLocalizedText(selectButton, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.selectButton.text")); // NOI18N selectButton.setToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.selectButton.toolTipText")); // NOI18N selectButton.setActionCommand(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.selectButton.actionCommand")); // NOI18N @@ -100,6 +109,29 @@ final class LocalFilesPanel extends javax.swing.JPanel { selectButtonActionPerformed(evt); } }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + add(selectButton, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(deleteButon, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.deleteButon.text")); // NOI18N + deleteButon.setMaximumSize(new java.awt.Dimension(70, 23)); + deleteButon.setMinimumSize(new java.awt.Dimension(70, 23)); + deleteButon.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + deleteButonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + add(deleteButon, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(clearButton, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.clearButton.text")); // NOI18N clearButton.setToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.clearButton.toolTipText")); // NOI18N @@ -111,14 +143,30 @@ final class LocalFilesPanel extends javax.swing.JPanel { clearButtonActionPerformed(evt); } }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + add(clearButton, gridBagConstraints); - selectedPathsScrollPane.setPreferredSize(new java.awt.Dimension(379, 96)); + fileListScrollpane.setMaximumSize(new java.awt.Dimension(32767, 100)); + fileListScrollpane.setMinimumSize(new java.awt.Dimension(100, 100)); + fileListScrollpane.setPreferredSize(new java.awt.Dimension(258, 100)); - selectedPaths.setEditable(false); - selectedPaths.setColumns(20); - selectedPaths.setRows(5); - selectedPaths.setToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.selectedPaths.toolTipText")); // NOI18N - selectedPathsScrollPane.setViewportView(selectedPaths); + fileListScrollpane.setViewportView(fileList); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridheight = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 0); + add(fileListScrollpane, gridBagConstraints); + + displayNamePanel.setLayout(new java.awt.GridBagLayout()); org.openide.awt.Mnemonics.setLocalizedText(changeNameButton, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.changeNameButton.text")); // NOI18N changeNameButton.addActionListener(new java.awt.event.ActionListener() { @@ -126,121 +174,127 @@ final class LocalFilesPanel extends javax.swing.JPanel { changeNameButtonActionPerformed(evt); } }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0); + displayNamePanel.add(changeNameButton, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(displayNameLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.displayNameLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + displayNamePanel.add(displayNameLabel, gridBagConstraints); - org.openide.awt.Mnemonics.setLocalizedText(timestampToIncludeLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.timestampToIncludeLabel.text")); // NOI18N + padding.setMinimumSize(new java.awt.Dimension(0, 0)); + padding.setPreferredSize(new java.awt.Dimension(0, 0)); - org.openide.awt.Mnemonics.setLocalizedText(createTimeCheckBox, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.createTimeCheckBox.text")); // NOI18N - createTimeCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - createTimeCheckBoxActionPerformed(evt); - } - }); + javax.swing.GroupLayout paddingLayout = new javax.swing.GroupLayout(padding); + padding.setLayout(paddingLayout); + paddingLayout.setHorizontalGroup( + paddingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) + ); + paddingLayout.setVerticalGroup( + paddingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) + ); - org.openide.awt.Mnemonics.setLocalizedText(accessTimeCheckBox, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.accessTimeCheckBox.text")); // NOI18N - accessTimeCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - accessTimeCheckBoxActionPerformed(evt); - } - }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 0; + gridBagConstraints.weightx = 1.0; + displayNamePanel.add(padding, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + add(displayNamePanel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(timeStampToIncludeLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.timeStampToIncludeLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + add(timeStampToIncludeLabel, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(modifiedTimeCheckBox, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.modifiedTimeCheckBox.text")); // NOI18N - modifiedTimeCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - modifiedTimeCheckBoxActionPerformed(evt); - } - }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 5; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 15, 5, 5); + add(modifiedTimeCheckBox, gridBagConstraints); - org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.jLabel2.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(createTimeCheckBox, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.createTimeCheckBox.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 6; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 15, 5, 5); + add(createTimeCheckBox, gridBagConstraints); - javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); - jPanel1.setLayout(jPanel1Layout); - jPanel1Layout.setHorizontalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() - .addComponent(selectedPathsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(selectButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(2, 2, 2)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(timestampToIncludeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addContainerGap()) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(displayNameLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(changeNameButton) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(23, 23, 23) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(modifiedTimeCheckBox) - .addComponent(accessTimeCheckBox) - .addComponent(createTimeCheckBox))) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel2))) - .addGap(0, 0, Short.MAX_VALUE)) - ); + org.openide.awt.Mnemonics.setLocalizedText(accessTimeCheckBox, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.accessTimeCheckBox.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 7; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 15, 5, 5); + add(accessTimeCheckBox, gridBagConstraints); - jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {clearButton, selectButton}); - - jPanel1Layout.setVerticalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(0, 0, 0) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(36, 36, 36) - .addComponent(clearButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(selectedPathsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(changeNameButton) - .addComponent(displayNameLabel)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(timestampToIncludeLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(modifiedTimeCheckBox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(createTimeCheckBox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(accessTimeCheckBox) - .addGap(18, 18, 18) - .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(17, Short.MAX_VALUE)) - ); + org.openide.awt.Mnemonics.setLocalizedText(timeStampNoteLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.timeStampNoteLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 8; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(10, 5, 5, 5); + add(timeStampNoteLabel, gridBagConstraints); errorLabel.setForeground(new java.awt.Color(255, 0, 0)); org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.errorLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 9; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + add(errorLabel, gridBagConstraints); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addContainerGap()) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(errorLabel) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + paddingBottom.setMinimumSize(new java.awt.Dimension(0, 0)); + + javax.swing.GroupLayout paddingBottomLayout = new javax.swing.GroupLayout(paddingBottom); + paddingBottom.setLayout(paddingBottomLayout); + paddingBottomLayout.setHorizontalGroup( + paddingBottomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(errorLabel)) + paddingBottomLayout.setVerticalGroup( + paddingBottomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) ); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 10; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; + gridBagConstraints.weighty = 1.0; + add(paddingBottom, gridBagConstraints); }// //GEN-END:initComponents private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectButtonActionPerformed @@ -248,20 +302,10 @@ final class LocalFilesPanel extends javax.swing.JPanel { if (returnVal == JFileChooser.APPROVE_OPTION) { File[] files = localFileChooser.getSelectedFiles(); - StringBuilder allPaths = new StringBuilder(); - for (File f : files) { - currentFiles.add(f); - } - for (File f : currentFiles) { - //loop over set of all files to ensure list is accurate - //update label - allPaths.append(f.getAbsolutePath()).append("\n"); - } - this.selectedPaths.setText(allPaths.toString()); - this.selectedPaths.setToolTipText(allPaths.toString()); + this.listModel.add(files); } - enableNext = !currentFiles.isEmpty(); + enableNext = !this.listModel.getFiles().isEmpty(); try { firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); @@ -285,24 +329,32 @@ final class LocalFilesPanel extends javax.swing.JPanel { } }//GEN-LAST:event_changeNameButtonActionPerformed - private void createTimeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createTimeCheckBoxActionPerformed - - }//GEN-LAST:event_createTimeCheckBoxActionPerformed + private void deleteButonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteButonActionPerformed + int minIdx = this.fileList.getMinSelectionIndex(); + int maxIdx = this.fileList.getMaxSelectionIndex(); - private void accessTimeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_accessTimeCheckBoxActionPerformed + if (minIdx >= 0 && maxIdx >= minIdx) { + this.listModel.remove(minIdx, maxIdx); + } + this.fileList.clearSelection(); - }//GEN-LAST:event_accessTimeCheckBoxActionPerformed + enableNext = !this.listModel.getFiles().isEmpty(); - private void modifiedTimeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_modifiedTimeCheckBoxActionPerformed - - }//GEN-LAST:event_modifiedTimeCheckBoxActionPerformed + try { + firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); + } catch (Exception e) { + logger.log(Level.SEVERE, "LocalFilesPanel listener threw exception", e); //NON-NLS + MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.moduleErr"), + NbBundle.getMessage(this.getClass(), "LocalFilesPanel.moduleErr.msg"), + MessageNotifyUtil.MessageType.ERROR); + } + }//GEN-LAST:event_deleteButonActionPerformed /** * Clear the fields and undo any selection of files. */ void reset() { - currentFiles.clear(); - selectedPaths.setText(""); + this.listModel.clear(); enableNext = false; errorLabel.setVisible(false); displayName = ""; @@ -316,20 +368,17 @@ final class LocalFilesPanel extends javax.swing.JPanel { MessageNotifyUtil.MessageType.ERROR); } } + /** * Get the path(s) which have been selected on this panel * - * @return a List of Strings representing the path(s) for the selected files or directories + * @return a List of Strings representing the path(s) for the selected files + * or directories */ List getContentPaths() { - List pathsList = new ArrayList<>(); - if (currentFiles == null) { - return pathsList; - } - for (File f : currentFiles) { - pathsList.add(f.getAbsolutePath()); - } - return pathsList; + return this.listModel.getFiles().stream() + .map(File::getAbsolutePath) + .collect(Collectors.toList()); } /** @@ -409,20 +458,104 @@ final class LocalFilesPanel extends javax.swing.JPanel { return this.displayName; } + /** + * A record of a file for the specific purposes of displaying in a JList + * (with toString). + */ + private static class FileRecord { + + private final File file; + + FileRecord(File file) { + this.file = file; + } + + @Override + public String toString() { + return file == null ? "" : file.getAbsolutePath(); + } + + /** + * @return The underlying file. + */ + File getFile() { + return file; + } + } + + /** + * JListModel for displaying files. + */ + private static class LocalFilesModel extends AbstractListModel { + + private List items = Collections.emptyList(); + + @Override + public int getSize() { + return items.size(); + } + + @Override + public FileRecord getElementAt(int index) { + File f = items.get(index); + return new FileRecord(f); + } + + /** + * Adds a series of files to the list model. + * + * @param files The files. + */ + void add(File... files) { + items = Stream.concat(items.stream(), Stream.of(files)) + .sorted(Comparator.comparing(f -> f.getAbsolutePath().toLowerCase())) + .distinct() + .collect(Collectors.toList()); + + this.fireContentsChanged(this, 0, items.size() - 1); + } + + /** + * Removes files in the list starting at minIdx going to maxIdx. + * + * @param minIdx The minimum index of items to be removed. + * @param maxIdx The maximum index to be removed. + */ + void remove(int minIdx, int maxIdx) { + for (int i = maxIdx; i >= minIdx; i--) { + items.remove(i); + } + this.fireContentsChanged(this, 0, items.size() - 1); + } + + /** + * @return The files to be added to the local files data source. + */ + List getFiles() { + return items; + } + + /** + * Clears currently tracked local files. + */ + void clear() { + items.clear(); + this.fireContentsChanged(this, 0, 0); + } + + } + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JCheckBox accessTimeCheckBox; private javax.swing.JButton changeNameButton; private javax.swing.JButton clearButton; private javax.swing.JCheckBox createTimeCheckBox; + private javax.swing.JButton deleteButon; private javax.swing.JLabel displayNameLabel; private javax.swing.JLabel errorLabel; - private javax.swing.JLabel jLabel2; - private javax.swing.JPanel jPanel1; + private javax.swing.JList fileList; private javax.swing.JFileChooser localFileChooser; private javax.swing.JCheckBox modifiedTimeCheckBox; private javax.swing.JButton selectButton; - private javax.swing.JTextArea selectedPaths; - private javax.swing.JScrollPane selectedPathsScrollPane; - private javax.swing.JLabel timestampToIncludeLabel; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 36ca201649..56a0f2ceb3 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -506,7 +506,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { 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); } memField.setText(initialMemValue); diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ALeappAnalyzerIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ALeappAnalyzerIngestModule.java index 3cfe4b954c..d9f673ac36 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ALeappAnalyzerIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ALeappAnalyzerIngestModule.java @@ -71,7 +71,7 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { private static final String ALEAPP_EXECUTABLE = "aleapp.exe";//NON-NLS private static final String ALEAPP_PATHS_FILE = "aLeapp_paths.txt"; //NON-NLS - private static final String XMLFILE = "aleap-artifact-attribute-reference.xml"; //NON-NLS + private static final String XMLFILE = "aleapp-artifact-attribute-reference.xml"; //NON-NLS private File aLeappExecutable; @@ -86,7 +86,7 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { @NbBundle.Messages({ "ALeappAnalyzerIngestModule.executable.not.found=aLeapp Executable Not Found.", "ALeappAnalyzerIngestModule.requires.windows=aLeapp module requires windows.", - "ALeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize aLeappProcessFile"}) + "ALeappAnalyzerIngestModule.error.aleapp.file.processor.init=Failure to initialize aLeappProcessFile"}) @Override public void startUp(IngestJobContext context) throws IngestModuleException { this.context = context; @@ -100,9 +100,9 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { } try { - aLeappFileProcessor = new LeappFileProcessor(XMLFILE, ALeappAnalyzerModuleFactory.getModuleName(), context); + aLeappFileProcessor = new LeappFileProcessor(XMLFILE, ALeappAnalyzerModuleFactory.getModuleName(), ALEAPP, context); } catch (IOException | IngestModuleException | NoCurrentCaseException ex) { - throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_error_ileapp_file_processor_init(), ex); + throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_error_aleapp_file_processor_init(), ex); } try { @@ -148,7 +148,7 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { writeErrorMsgToIngestInbox(); return ProcessResult.ERROR; } - aLeappPathsToProcess = loadIleappPathFile(tempOutputPath); + aLeappPathsToProcess = loadAleappPathFile(tempOutputPath); if (aLeappPathsToProcess.isEmpty()) { logger.log(Level.SEVERE, String.format("Error getting file paths to search, list is empty")); writeErrorMsgToIngestInbox(); @@ -178,7 +178,7 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { } statusHelper.switchToIndeterminate(); - statusHelper.progress(Bundle.ILeappAnalyzerIngestModule_processing_iLeapp_results()); + statusHelper.progress(Bundle.ALeappAnalyzerIngestModule_processing_aLeapp_results()); extractFilesFromDataSource(dataSource, aLeappPathsToProcess, tempOutputPath); processALeappFs(dataSource, currentCase, statusHelper, tempOutputPath.toString()); @@ -219,7 +219,7 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { return; } - addILeappReportToReports(moduleOutputPath, currentCase); + addALeappReportToReports(moduleOutputPath, currentCase); } catch (IOException ex) { logger.log(Level.SEVERE, String.format("Error when trying to execute aLeapp program against file %s", aLeappFile.getLocalAbsPath()), ex); @@ -227,7 +227,7 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { } if (context.dataSourceIngestIsCancelled()) { - logger.log(Level.INFO, "ILeapp Analyser ingest module run was canceled"); //NON-NLS + logger.log(Level.INFO, "aLeapp Analyser ingest module run was canceled"); //NON-NLS return; } @@ -262,7 +262,7 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { return; } - addILeappReportToReports(moduleOutputPath, currentCase); + addALeappReportToReports(moduleOutputPath, currentCase); } catch (IOException ex) { logger.log(Level.SEVERE, String.format("Error when trying to execute aLeapp program against file system"), ex); @@ -270,7 +270,7 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { } if (context.dataSourceIngestIsCancelled()) { - logger.log(Level.INFO, "ILeapp Analyser ingest module run was canceled"); //NON-NLS + logger.log(Level.INFO, "aLeapp Analyser ingest module run was canceled"); //NON-NLS return; } @@ -335,7 +335,7 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { * Find the index.html file in the aLeapp output directory so it can be * added to reports */ - private void addILeappReportToReports(Path aLeappOutputDir, Case currentCase) { + private void addALeappReportToReports(Path aLeappOutputDir, Case currentCase) { List allIndexFiles = new ArrayList<>(); try (Stream walk = Files.walk(aLeappOutputDir)) { @@ -363,7 +363,7 @@ public class ALeappAnalyzerIngestModule implements DataSourceIngestModule { * Reads the aLeapp paths file to get the paths that we want to extract * */ - private List loadIleappPathFile(Path moduleOutputPath) throws FileNotFoundException, IOException { + private List loadAleappPathFile(Path moduleOutputPath) throws FileNotFoundException, IOException { List aLeappPathsToProcess = new ArrayList<>(); Path filePath = Paths.get(moduleOutputPath.toString(), ALEAPP_PATHS_FILE); diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle.properties-MERGED index d861b2fc29..9c7572c8b6 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle.properties-MERGED @@ -1,7 +1,7 @@ ALeappAnalyzerIngestModule.aLeapp.cancelled=aLeapp run was canceled ALeappAnalyzerIngestModule.completed=aLeapp Processing Completed +ALeappAnalyzerIngestModule.error.aleapp.file.processor.init=Failure to initialize aLeappProcessFile ALeappAnalyzerIngestModule.error.creating.output.dir=Error creating aLeapp module output directory. -ALeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize aLeappProcessFile ALeappAnalyzerIngestModule.error.running.aLeapp=Error running aLeapp, see log file. ALeappAnalyzerIngestModule.executable.not.found=aLeapp Executable Not Found. ALeappAnalyzerIngestModule.has.run=aLeapp diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ILeappAnalyzerIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ILeappAnalyzerIngestModule.java index b46982dfa6..4d8328ce3d 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ILeappAnalyzerIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ILeappAnalyzerIngestModule.java @@ -71,7 +71,7 @@ public class ILeappAnalyzerIngestModule implements DataSourceIngestModule { private static final String ILEAPP_EXECUTABLE = "ileapp.exe";//NON-NLS private static final String ILEAPP_PATHS_FILE = "iLeapp_paths.txt"; //NON-NLS - private static final String XMLFILE = "ileap-artifact-attribute-reference.xml"; //NON-NLS + private static final String XMLFILE = "ileapp-artifact-attribute-reference.xml"; //NON-NLS private File iLeappExecutable; @@ -100,7 +100,7 @@ public class ILeappAnalyzerIngestModule implements DataSourceIngestModule { } try { - iLeappFileProcessor = new LeappFileProcessor(XMLFILE, ILeappAnalyzerModuleFactory.getModuleName(), context); + iLeappFileProcessor = new LeappFileProcessor(XMLFILE, ILeappAnalyzerModuleFactory.getModuleName(), ILEAPP, context); } catch (IOException | IngestModuleException | NoCurrentCaseException ex) { throw new IngestModuleException(Bundle.ILeappAnalyzerIngestModule_error_ileapp_file_processor_init(), ex); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/LeappFileProcessor.java b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/LeappFileProcessor.java index 1e4e30a944..3fab3e483c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/LeappFileProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/LeappFileProcessor.java @@ -145,7 +145,11 @@ public final class LeappFileProcessor { } private static final Logger logger = Logger.getLogger(LeappFileProcessor.class.getName()); + private final String CUSTOM_ARTIFACTS_ATTRIBUTES_FILE = "custom-artifact-attribute-list.csv"; + private final String ARTIFACT_ATTRIBUTE_REFERENCE_USER = "artifact-attribute-reference-user.xml"; + private final String xmlFile; //NON-NLS + private final String leapModule; private final String moduleName; private final IngestJobContext context; @@ -198,7 +202,7 @@ public final class LeappFileProcessor { private final Blackboard blkBoard; - public LeappFileProcessor(String xmlFile, String moduleName, IngestJobContext context) throws IOException, IngestModuleException, NoCurrentCaseException { + public LeappFileProcessor(String xmlFile, String moduleName, String leapModule, IngestJobContext context) throws IOException, IngestModuleException, NoCurrentCaseException { this.tsvFiles = new HashMap<>(); this.tsvFileArtifacts = new HashMap<>(); this.tsvFileArtifactComments = new HashMap<>(); @@ -206,14 +210,27 @@ public final class LeappFileProcessor { this.xmlFile = xmlFile; this.moduleName = moduleName; this.context = context; + this.leapModule = leapModule; blkBoard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard(); + loadCustomArtifactsAttributes(blkBoard, leapModule); createCustomArtifacts(blkBoard); configExtractor(); loadConfigFile(); } + + /** + * Generates a key trimmed and case-insensitive that can be used for a + * case-insensitive lookup in a map. + * + * @param origKey The original key. + * @return The normalized key. + */ + private static String normalizeKey(String origKey) { + return StringUtils.defaultString(origKey).trim().toLowerCase(); + } @NbBundle.Messages({ "LeappFileProcessor.error.running.Leapp=Error running Leapp, see log file.", @@ -274,7 +291,7 @@ public final class LeappFileProcessor { .filter(f -> f.toLowerCase().endsWith(".tsv")).collect(Collectors.toList()); for (String tsvFile : allTsvFiles) { - if (tsvFiles.containsKey(FilenameUtils.getName(tsvFile.toLowerCase()))) { + if (tsvFiles.containsKey(normalizeKey(FilenameUtils.getName(tsvFile)))) { foundTsvFiles.add(tsvFile); } } @@ -323,9 +340,10 @@ public final class LeappFileProcessor { progress.progress(Bundle.LeappFileProcessor_tsvProcessed(fileName), i); File LeappFile = new File(LeappFileName); - if (tsvFileAttributes.containsKey(fileName)) { - List attrList = tsvFileAttributes.get(fileName); - BlackboardArtifact.Type artifactType = tsvFileArtifacts.get(fileName); + String fileKey = fileName.toLowerCase().trim(); + if (tsvFileAttributes.containsKey(normalizeKey(fileKey))) { + List attrList = tsvFileAttributes.get(normalizeKey(fileKey)); + BlackboardArtifact.Type artifactType = tsvFileArtifacts.get(normalizeKey(fileKey)); try { processFile(LeappFile, attrList, fileName, artifactType, dataSource); @@ -895,18 +913,15 @@ public final class LeappFileProcessor { private Collection processReadLine(List lineValues, Map columnIndexes, List attrList, String fileName, int lineNum) throws IngestModuleException { + // if no attributes, return an empty row if (MapUtils.isEmpty(columnIndexes) || CollectionUtils.isEmpty(lineValues) || (lineValues.size() == 1 && StringUtils.isEmpty(lineValues.get(0)))) { return Collections.emptyList(); - } else if (lineValues.size() != columnIndexes.size()) { - logger.log(Level.WARNING, String.format( - "Row at line number %d in file %s has %d columns when %d were expected based on the header row.", - lineNum, fileName, lineValues.size(), columnIndexes.size())); - return Collections.emptyList(); } List attrsToRet = new ArrayList<>(); for (TsvColumn colAttr : attrList) { + // if no matching attribute type, keep going if (colAttr.getAttributeType() == null) { // this handles columns that are currently ignored. continue; @@ -920,22 +935,30 @@ public final class LeappFileProcessor { String value = (columnIdx >= lineValues.size() || columnIdx < 0) ? null : lineValues.get(columnIdx); if (value == null) { - logger.log(Level.WARNING, String.format("No value found for column %s at line %d in file %s. Omitting row.", colAttr.getColumnName(), lineNum, fileName)); - return Collections.emptyList(); + // if column is required, return empty for this row if no value + if (colAttr.isRequired()) { + logger.log(Level.WARNING, String.format("No value found for required column %s at line %d in file %s. Omitting row.", colAttr.getColumnName(), lineNum, fileName)); + return Collections.emptyList(); + } else { + // otherwise, continue to next column + logger.log(Level.WARNING, String.format("No value found for column %s at line %d in file %s. Omitting column.", colAttr.getColumnName(), lineNum, fileName)); + continue; + } } String formattedValue = formatValueBasedOnAttrType(colAttr, value); BlackboardAttribute attr = getAttribute(colAttr.getAttributeType(), formattedValue, fileName); - if (attr == null) { + if (attr != null) { + attrsToRet.add(attr); + } else if (colAttr.isRequired()) { logger.log(Level.WARNING, String.format("Blackboard attribute could not be parsed column %s at line %d in file %s. Omitting row.", colAttr.getColumnName(), lineNum, fileName)); return Collections.emptyList(); } - attrsToRet.add(attr); } - if (tsvFileArtifactComments.containsKey(fileName)) { - attrsToRet.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, moduleName, tsvFileArtifactComments.get(fileName))); + if (tsvFileArtifactComments.containsKey(normalizeKey(fileName))) { + attrsToRet.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, moduleName, tsvFileArtifactComments.get(normalizeKey(fileName)))); } return attrsToRet; @@ -1065,6 +1088,18 @@ public final class LeappFileProcessor { } } + /** + * Read the XML config file and load the mappings into maps + */ + private void loadConfigFile() throws IngestModuleException { + String path = PlatformUtil.getUserConfigDirectory() + File.separator + xmlFile; + loadIndividualConfigFile(path); + String userPath = PlatformUtil.getUserConfigDirectory() + File.separator + leapModule + "-" + ARTIFACT_ATTRIBUTE_REFERENCE_USER; + if (new File(userPath).exists()) { + loadIndividualConfigFile(userPath); + } + } + /** * Read the XML config file and load the mappings into maps */ @@ -1075,10 +1110,9 @@ public final class LeappFileProcessor { "LeappFileProcessor.postartifacts_error=Error posting Blackboard Artifact", "LeappFileProcessor.error.creating.new.artifacts=Error creating new artifacts." }) - private void loadConfigFile() throws IngestModuleException { + private void loadIndividualConfigFile(String path) throws IngestModuleException { Document xmlinput; try { - String path = PlatformUtil.getUserConfigDirectory() + File.separator + xmlFile; File f = new File(path); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); @@ -1104,7 +1138,7 @@ public final class LeappFileProcessor { for (int i = 0; i < nlist.getLength(); i++) { NamedNodeMap nnm = nlist.item(i).getAttributes(); - tsvFiles.put(nnm.getNamedItem("filename").getNodeValue().toLowerCase(), nnm.getNamedItem("description").getNodeValue()); + tsvFiles.put(normalizeKey(nnm.getNamedItem("filename").getNodeValue()), nnm.getNamedItem("description").getNodeValue()); } @@ -1130,11 +1164,11 @@ public final class LeappFileProcessor { logger.log(Level.SEVERE, String.format("No known artifact mapping found for [artifact: %s, %s]", artifactName, getXmlFileIdentifier(parentName))); } else { - tsvFileArtifacts.put(parentName, foundArtifactType); + tsvFileArtifacts.put(normalizeKey(parentName), foundArtifactType); } if (!comment.toLowerCase().matches("null")) { - tsvFileArtifactComments.put(parentName, comment); + tsvFileArtifactComments.put(normalizeKey(parentName), comment); } } @@ -1196,14 +1230,14 @@ public final class LeappFileProcessor { columnName.trim().toLowerCase(), "yes".compareToIgnoreCase(required) == 0); - if (tsvFileAttributes.containsKey(parentName)) { - List attrList = tsvFileAttributes.get(parentName); + if (tsvFileAttributes.containsKey(normalizeKey(parentName))) { + List attrList = tsvFileAttributes.get(normalizeKey(parentName)); attrList.add(thisCol); tsvFileAttributes.replace(parentName, attrList); } else { List attrList = new ArrayList<>(); attrList.add(thisCol); - tsvFileAttributes.put(parentName, attrList); + tsvFileAttributes.put(normalizeKey(parentName), attrList); } } @@ -1270,7 +1304,7 @@ public final class LeappFileProcessor { private static final Set ALLOWED_EXTENSIONS = new HashSet<>(Arrays.asList("zip", "tar", "tgz")); /** - * Find the files that will be processed by the iLeapp program + * Find the files that will be processed by the Leapp program * * @param dataSource * @@ -1303,6 +1337,111 @@ public final class LeappFileProcessor { return leappFilesToProcess; } + /** + * Create custom artifacts that are defined in the xLeapp xml file(s). + * + */ + private void loadCustomArtifactsAttributes(Blackboard blkBoard, String leapModule) { + + for (Map.Entry customArtifact : CUSTOM_ARTIFACT_MAP.entrySet()) { + String artifactName = customArtifact.getKey(); + String artifactDescription = customArtifact.getValue(); + createCustomAttributesArtifacts(blkBoard, "artifact", artifactName, artifactDescription, null); + } + + File customFilePath = new File(PlatformUtil.getUserConfigDirectory() + File.separator + leapModule + '-' + CUSTOM_ARTIFACTS_ATTRIBUTES_FILE); + if (customFilePath.exists()) { + try (MappingIterator> iterator = new CsvMapper() + .enable(CsvParser.Feature.WRAP_AS_ARRAY) + .readerFor(List.class) + .with(CsvSchema.emptySchema().withColumnSeparator(',')) + .readValues(customFilePath)) { + + if (iterator.hasNext()) { + // Header line we can skip + List headerItems = iterator.next(); + int lineNum = 2; + while (iterator.hasNext()) { + List columnItems = iterator.next(); + if (columnItems.size() > 3) { + createCustomAttributesArtifacts(blkBoard, columnItems.get(0), columnItems.get(1), columnItems.get(2), columnItems.get(3)); + } else { + createCustomAttributesArtifacts(blkBoard, columnItems.get(0), columnItems.get(1), columnItems.get(2), null); + } + } + } + } catch (IOException ex) { + logger.log(Level.WARNING, String.format("Failed to read/open file %s.", customFilePath), ex); + } + } + } + + /** + * Create custom attributes that are defined in the xLeapp xml file(s). + * + */ + private void createCustomAttributesArtifacts(Blackboard blkBoard, String atType, String atName, String atDescription, String attrType) { + + if (atType.toLowerCase().equals("artifact")) { + try { + BlackboardArtifact.Type customArtifactType = blkBoard.getOrAddArtifactType(atName.toUpperCase(), atDescription); + } catch (Blackboard.BlackboardException ex) { + logger.log(Level.WARNING, String.format("Failed to create custom artifact type %s.", atName), ex); + } + return; + } + + switch (attrType.toLowerCase()) { + case "json": + case "string": + try { + BlackboardAttribute.Type customAttrbiuteType = blkBoard.getOrAddAttributeType(atName.toUpperCase(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, atDescription); + } catch (Blackboard.BlackboardException ex) { + logger.log(Level.WARNING, String.format("Failed to create custom attribute type %s.", atName), ex); + } + return; + case "integer": + try { + BlackboardAttribute.Type customAttrbiuteType = blkBoard.getOrAddAttributeType(atName.toUpperCase(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, atDescription); + } catch (Blackboard.BlackboardException ex) { + logger.log(Level.WARNING, String.format("Failed to create custom attribute type %s.", atName), ex); + } + return; + case "long": + try { + BlackboardAttribute.Type customAttrbiuteType = blkBoard.getOrAddAttributeType(atName.toUpperCase(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, atDescription); + } catch (Blackboard.BlackboardException ex) { + logger.log(Level.WARNING, String.format("Failed to create custom attribute type %s.", atName), ex); + } + return; + case "double": + try { + BlackboardAttribute.Type customAttrbiuteType = blkBoard.getOrAddAttributeType(atName.toUpperCase(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, atDescription); + } catch (Blackboard.BlackboardException ex) { + logger.log(Level.WARNING, String.format("Failed to create custom attribute type %s.", atName), ex); + } + return; + case "byte": + try { + BlackboardAttribute.Type customAttrbiuteType = blkBoard.getOrAddAttributeType(atName.toUpperCase(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE, atDescription); + } catch (Blackboard.BlackboardException ex) { + logger.log(Level.WARNING, String.format("Failed to create custom attribute type %s.", atName), ex); + } + return; + case "datetime": + try { + BlackboardAttribute.Type customAttrbiuteType = blkBoard.getOrAddAttributeType(atName.toUpperCase(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME, atDescription); + } catch (Blackboard.BlackboardException ex) { + logger.log(Level.WARNING, String.format("Failed to create custom attribute type %s.", atName), ex); + } + return; + default: + logger.log(Level.WARNING, String.format("Attribute Type %s for file %s not defined.", attrType, atName)); //NON-NLS + return; + + } + } + /** * Create custom artifacts that are defined in the xLeapp xml file(s). * diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleap-artifact-attribute-reference.xml b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleapp-artifact-attribute-reference.xml similarity index 93% rename from Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleap-artifact-attribute-reference.xml rename to Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleapp-artifact-attribute-reference.xml index 3ef61b0025..88359a0b4c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleap-artifact-attribute-reference.xml +++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleapp-artifact-attribute-reference.xml @@ -36,6 +36,14 @@ + + + + + + + + @@ -54,7 +62,15 @@ - + + + + + + + + + @@ -64,7 +80,7 @@ - + @@ -76,7 +92,7 @@ - + @@ -86,7 +102,7 @@ - + @@ -94,7 +110,7 @@ - + @@ -104,7 +120,7 @@ - + @@ -116,7 +132,7 @@ - + @@ -126,7 +142,7 @@ - + @@ -151,7 +167,7 @@ - + @@ -161,7 +177,7 @@ - + @@ -173,7 +189,7 @@ - + @@ -183,17 +199,18 @@ - + - + - + + - + @@ -205,7 +222,7 @@ - + @@ -215,7 +232,7 @@ - + @@ -224,7 +241,7 @@ - + @@ -234,19 +251,19 @@ - + - + - - + + - + @@ -256,7 +273,7 @@ - + @@ -266,7 +283,7 @@ - + @@ -278,7 +295,7 @@ - + @@ -288,7 +305,7 @@ - + @@ -317,7 +334,7 @@ - + @@ -329,13 +346,21 @@ + + + + + + - + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileap-artifact-attribute-reference.xml b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileapp-artifact-attribute-reference.xml similarity index 91% rename from Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileap-artifact-attribute-reference.xml rename to Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileapp-artifact-attribute-reference.xml index 70725fd0c6..3580e29061 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileap-artifact-attribute-reference.xml +++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileapp-artifact-attribute-reference.xml @@ -66,14 +66,24 @@ + + + + + + + + + + + - - + @@ -92,16 +102,17 @@ - - - + + + + + - - + + - @@ -712,19 +723,24 @@ - - + + + + + + + + + - + + - - - - - - - + + + + @@ -744,22 +760,28 @@ - + - - - + + - - - - - - - - - + + + + + + + + + + + + + + + + @@ -779,4 +801,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties index 565804dea4..12e6ab211f 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties @@ -85,6 +85,8 @@ KeywordSearchFilterNode.getFileActions.searchSameMd5=Search for files with the s KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl=View in New Window KeywordSearchIngestModule.init.noKwInLstMsg=No keywords in keyword list. KeywordSearchIngestModule.init.onlyIdxKwSkipMsg=Only indexing will be done and keyword search will be skipped (you can still add keyword lists using the Keyword Lists - Add to Ingest). +KeywordSearchIngestModule.init.SolrIndexingDisabled=Solr indexing is disabled. +KeywordSearchIngestModule.init.indexingDisabled=Text indexing is disabled. See user manual section "Limitations of Ad Hoc Keyword Search" for details. KeywordSearchIngestModule.doInBackGround.displayName=Periodic Keyword Search KeywordSearchIngestModule.doInBackGround.finalizeMsg=Finalizing KeywordSearchIngestModule.doInBackGround.pendingMsg=(Pending) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index 2ff50a4048..0bf48a5370 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED @@ -137,6 +137,8 @@ KeywordSearchFilterNode.getFileActions.searchSameMd5=Search for files with the s KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl=View in New Window KeywordSearchIngestModule.init.noKwInLstMsg=No keywords in keyword list. KeywordSearchIngestModule.init.onlyIdxKwSkipMsg=Only indexing will be done and keyword search will be skipped (you can still add keyword lists using the Keyword Lists - Add to Ingest). +KeywordSearchIngestModule.init.SolrIndexingDisabled=Solr indexing is disabled. +KeywordSearchIngestModule.init.indexingDisabled=Text indexing is disabled. See user manual section "Limitations of Ad Hoc Keyword Search" for details. KeywordSearchIngestModule.doInBackGround.displayName=Periodic Keyword Search KeywordSearchIngestModule.doInBackGround.finalizeMsg=Finalizing KeywordSearchIngestModule.doInBackGround.pendingMsg=(Pending) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java index cd6f255def..b3a0a1b3b3 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java @@ -318,9 +318,15 @@ public final class KeywordSearchIngestModule implements FileIngestModule { break; } } - if (!hasKeywordsForSearch) { - services.postMessage(IngestMessage.createWarningMessage(KeywordSearchModuleFactory.getModuleName(), NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.noKwInLstMsg"), - NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.onlyIdxKwSkipMsg"))); + + if (!settings.isIndexToSolrEnabled()) { + services.postMessage(IngestMessage.createWarningMessage(KeywordSearchModuleFactory.getModuleName(), NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.SolrIndexingDisabled"), + NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.indexingDisabled"))); + } else { + if (!hasKeywordsForSearch) { + services.postMessage(IngestMessage.createWarningMessage(KeywordSearchModuleFactory.getModuleName(), NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.noKwInLstMsg"), + NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.onlyIdxKwSkipMsg"))); + } } } } diff --git a/build-windows-installer.xml b/build-windows-installer.xml index c56429a330..41c8fd2058 100644 --- a/build-windows-installer.xml +++ b/build-windows-installer.xml @@ -174,11 +174,11 @@ - + - - + + @@ -222,6 +222,19 @@ + + + + + + + + + diff --git a/build.xml b/build.xml index cb81444cf0..ec5c30369d 100644 --- a/build.xml +++ b/build.xml @@ -148,7 +148,7 @@ - + diff --git a/docs/doxygen-dev/Doxyfile b/docs/doxygen-dev/Doxyfile index 1bb93877f4..66497c563c 100755 --- a/docs/doxygen-dev/Doxyfile +++ b/docs/doxygen-dev/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy Developer Documentation" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.19.3 +PROJECT_NUMBER = 4.20.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -1025,7 +1025,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = 4.19.3 +HTML_OUTPUT = 4.20.0 # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). diff --git a/docs/doxygen-user/Doxyfile b/docs/doxygen-user/Doxyfile index f7740fa8f0..e836298f10 100644 --- a/docs/doxygen-user/Doxyfile +++ b/docs/doxygen-user/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.19.3 +PROJECT_NUMBER = 4.20.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -1025,7 +1025,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = 4.19.3 +HTML_OUTPUT = 4.20.0 # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). diff --git a/docs/doxygen-user/data_sources.dox b/docs/doxygen-user/data_sources.dox index 81336e74ab..0dd49b9868 100644 --- a/docs/doxygen-user/data_sources.dox +++ b/docs/doxygen-user/data_sources.dox @@ -103,7 +103,8 @@ To add a local drive: You can add files or folders that are on your local computer (or on a shared drive) without putting them into a disk image. This is useful if you have only a collection of files that you want to analyze. Some things to note when doing this: -- Autopsy ignores the time stamps on files that it adds this way because they could be the timestamps when they were copied onto your examination device. +- Autopsy by default ignores the time stamps on files that it adds this way because they could be the timestamps when they were copied onto your examination device. +- You do have the option to have time stamps added on files by checking the timestamps you want, these time stamps are taken from the examination device. Directories will not have time stamps. - If you have a USB-attached device that you are analyzing and you choose to add the device's contents using this method, then note that it will not look at unallocated space or deleted files. Autopsy will only be able to see the allocated files. You should add the device as a "Logical Drive" to analyze the unallocated space. - You can modify the name of the Logical File Set from the default LogicalFileSet# by clicking the "Change" button as shown in the screenshot below: @@ -114,6 +115,8 @@ To add logical files: -# Leave the top combo box on "Local files and folders" -# Press the "Add" button and navigate to a folder or file to add. Choosing a folder will cause all of its contents (including sub-folders) to be added. -# Continue to press "Add" until all files and folders have been selected. +-# If you want any of the files to be added with time stamps from the file system then check the box associated with the timestamp you would like associaed with the file. +-# If a file or directory was mistakenly added then highlight it and press the "Delete" button to remove the item from the list of files/folders All of the files that you added in the panel will be grouped together into a single data source, called "LogicalFileSet" in the main UI. diff --git a/docs/doxygen-user/images/change_logical_file_set_display_name.PNG b/docs/doxygen-user/images/change_logical_file_set_display_name.PNG index dfaa158c0f..d6b3871377 100644 Binary files a/docs/doxygen-user/images/change_logical_file_set_display_name.PNG and b/docs/doxygen-user/images/change_logical_file_set_display_name.PNG differ diff --git a/docs/doxygen-user_fr/Doxyfile b/docs/doxygen-user_fr/Doxyfile index 177c9cdb6e..4538fd297c 100644 --- a/docs/doxygen-user_fr/Doxyfile +++ b/docs/doxygen-user_fr/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Documentation utilisateur Autopsy" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.19.1 +PROJECT_NUMBER = 4.20.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -1025,7 +1025,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = 4.19.1 +HTML_OUTPUT = 4.20.0 # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 5eead8e4cf..4859eab17f 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.19.3 +PROJECT_NUMBER = 4.20.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears a the top of each page and should give viewer a @@ -1066,7 +1066,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = api-docs/4.19.3/ +HTML_OUTPUT = api-docs/4.20.0/ # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). diff --git a/installer_autopsy/etc/autopsy.conf b/installer_autopsy/etc/autopsy.conf new file mode 100755 index 0000000000..a92a08d04b --- /dev/null +++ b/installer_autopsy/etc/autopsy.conf @@ -0,0 +1,71 @@ +#Thu, 15 Jun 2023 09:17:11 -0400 +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# ${HOME} will be replaced by user home directory according to platform. +# +# Default locations of userdir and cachedir: +# (http://wiki.netbeans.org/FaqWhatIsUserdir) +# +# On Windows ${DEFAULT_USERDIR_ROOT} will be replaced by the launcher +# with \, where is the value of +# "AppData" key in Windows Registry under +# "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" +# and ${DEFAULT_CACHEDIR_ROOT} will be replaced by the launcher +# with the value of "\\Cache" where "LocalAppData" +# is a key in Windows Registry under +# "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders". +# is the the executable's filename without the extension. +# +# On Mac ${DEFAULT_USERDIR_ROOT} will be replaced by the launcher +# with "~/Library/Application Support/" and +# ${DEFAULT_CACHEDIR_ROOT} with "~/Library/Caches/" +# where is the launcher script's name. +# +# On other systems ${DEFAULT_USERDIR_ROOT} will be replaced by the launcher +# with "${HOME}/." and ${DEFAULT_CACHEDIR_ROOT} with +# "${HOME}/.cache/". +# +# You can also use ${HOME} variable which will be replaced with +# user.home JVM system property value. +# +# The above location variables are valid only in the default_userdir and +# default_cachedir properties. +# +# NOTE: If you specify a non-default userdir path on command line +# (--userdir option) and don't specify a cachedir path (--cachedir option), +# cachedir will be in "/var/cache". +# +# Cachedir must be different from userdir. The same cachedir and userdir +# would cause problems. +# + +default_userdir=${DEFAULT_USERDIR_ROOT} +default_cachedir="${DEFAULT_CACHEDIR_ROOT}/dev" + +# options used by the launcher by default, can be overridden by explicit +# command line switches +default_options="--branding autopsy -J-Xms24m -J-XX:+UseStringDeduplication -J-Dprism.order=sw -J--add-opens=java.base/java.lang=ALL-UNNAMED -J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-opens=javafx.controls/javafx.scene.control.skin=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED -J--add-exports=javafx.controls/com.sun.javafx.scene.control.inputmap=ALL-UNNAMED -J--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED" +# for development purposes you may wish to append: -J-Dnetbeans.logger.console=true -J-ea + +# default location of JDK/JRE, can be overridden by using --jdkhome switch +#jdkhome="/path/to/jdk" + +# clusters' paths separated by path.separator (semicolon on Windows, colon on Unices) +#extra_clusters= + +jdkhome="jre" diff --git a/nbproject/project.properties b/nbproject/project.properties index 86e5d275ca..e8d17eb3c8 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -19,7 +19,7 @@ update_versions=false #Note: can be higher on 64 bit systems, should be in sync with build.xml # for Japanese version add: -J-Duser.language=ja # NOTE: Modules need to be exported to other components for visibility (and use). See https://stackoverflow.com/questions/53695304/autocompletionbinding-cannot-access-class-com-sun-javafx-event-eventhandlermanag -run.args.extra=-J-Xms24m -J-Xmx4G -J-XX:+UseStringDeduplication -J-Dprism.order=sw -J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-opens=javafx.controls/javafx.scene.control.skin=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED -J--add-exports=javafx.controls/com.sun.javafx.scene.control.inputmap=ALL-UNNAMED -J--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED +run.args.extra=-J-Xms24m -J-Xmx4G -J-XX:+UseStringDeduplication -J-Dprism.order=sw -J--add-opens=java.base/java.lang=ALL-UNNAMED -J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-opens=javafx.controls/javafx.scene.control.skin=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED -J--add-exports=javafx.controls/com.sun.javafx.scene.control.inputmap=ALL-UNNAMED -J--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED auxiliary.org-netbeans-modules-apisupport-installer.license-type=apache.v2 auxiliary.org-netbeans-modules-apisupport-installer.os-linux=false auxiliary.org-netbeans-modules-apisupport-installer.os-macosx=false diff --git a/thirdparty/aLeapp/Version.txt b/thirdparty/aLeapp/Version.txt new file mode 100644 index 0000000000..7e3788794e --- /dev/null +++ b/thirdparty/aLeapp/Version.txt @@ -0,0 +1 @@ +ALEAPP v3.1.6: Android Logs, Events, and Protobuf Parser \ No newline at end of file diff --git a/thirdparty/aLeapp/aleapp.exe b/thirdparty/aLeapp/aleapp.exe index 3f47725616..91be0eacb5 100644 Binary files a/thirdparty/aLeapp/aleapp.exe and b/thirdparty/aLeapp/aleapp.exe differ diff --git a/thirdparty/iLeapp/Version.txt b/thirdparty/iLeapp/Version.txt new file mode 100644 index 0000000000..4be0e77ba2 --- /dev/null +++ b/thirdparty/iLeapp/Version.txt @@ -0,0 +1 @@ +iLEAPP v1.18.6: iLEAPP Logs, Events, and Properties Parser \ No newline at end of file diff --git a/thirdparty/iLeapp/ileapp.exe b/thirdparty/iLeapp/ileapp.exe index f1d395e930..956afd7f5b 100644 Binary files a/thirdparty/iLeapp/ileapp.exe and b/thirdparty/iLeapp/ileapp.exe differ