diff --git a/Core/release/InternalPythonModules/README.txt b/Core/release/InternalPythonModules/README.txt index e71281b732..7f03c2fa24 100755 --- a/Core/release/InternalPythonModules/README.txt +++ b/Core/release/InternalPythonModules/README.txt @@ -1,4 +1,6 @@ -Place Jython modules HERE in their respective folders. Eg. - +Do not place user modules here. Place them in the folder at C:\Users\JDoe\AppData\Roaming\Autopsy\python_modules where JDoe is your Windows username. You can also access this folder by launching Autopsy and clicking Tools -> Python Plugins through the menu. + +Place Jython modules HERE in their respective folders. Eg. - InternalPythonModules/ - testModule1/ - testModule1.py diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index d38eaa77ae..4373959707 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -45,10 +45,10 @@ public class ImageFilePanel extends JPanel implements DocumentListener { private final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; //NON-NLS private static final Logger logger = Logger.getLogger(ImageFilePanel.class.getName()); - private JFileChooser fc = new JFileChooser(); + private final JFileChooser fc = new JFileChooser(); // Externally supplied name is used to store settings - private String contextName; + private final String contextName; /** * Creates new form ImageFilePanel @@ -82,11 +82,11 @@ public class ImageFilePanel extends JPanel implements DocumentListener { /** * Creates and returns an instance of a ImageFilePanel. + * @return instance of the ImageFilePanel */ public static synchronized ImageFilePanel createInstance(String context, List fileChooserFilters) { ImageFilePanel instance = new ImageFilePanel(context, fileChooserFilters); - instance.postInit(); instance.createTimeZoneList(); @@ -234,6 +234,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { /** * Set the path of the image file. + * @param s path of the image file */ public void setContentPath(String s) { pathTextField.setText(s); @@ -242,7 +243,6 @@ public class ImageFilePanel extends JPanel implements DocumentListener { public String getTimeZone() { String tz = timeZoneComboBox.getSelectedItem().toString(); return tz.substring(tz.indexOf(")") + 2).trim(); - } public boolean getNoFatOrphans() { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java index 1aeda4a6da..56262394bf 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -66,7 +66,6 @@ final class LocalDiskPanel extends JPanel { customInit(); createTimeZoneList(); - } /** @@ -185,7 +184,6 @@ final class LocalDiskPanel extends JPanel { * * @return String selected disk path */ - //@Override public String getContentPaths() { if (disks.size() > 0) { LocalDisk selected = (LocalDisk) diskComboBox.getSelectedItem(); @@ -198,7 +196,6 @@ final class LocalDiskPanel extends JPanel { /** * Set the selected disk. */ - // @Override public void setContentPath(String s) { for (int i = 0; i < disks.size(); i++) { if (disks.get(i).getPath().equals(s)) { @@ -223,25 +220,20 @@ final class LocalDiskPanel extends JPanel { * * @return true */ - //@Override public boolean validatePanel() { return enableNext; } - //@Override public void reset() { //nothing to reset - } /** * Set the focus to the diskComboBox and refreshes the list of disks. */ - // @Override public void select() { diskComboBox.requestFocusInWindow(); model.loadDisks(); - } /** @@ -293,8 +285,8 @@ final class LocalDiskPanel extends JPanel { List partitions = new ArrayList<>(); //private String SELECT = "Select a local disk:"; - private String LOADING = NbBundle.getMessage(this.getClass(), "LocalDiskPanel.localDiskModel.loading.msg"); - private String NO_DRIVES = NbBundle.getMessage(this.getClass(), "LocalDiskPanel.localDiskModel.nodrives.msg"); + private final String LOADING = NbBundle.getMessage(this.getClass(), "LocalDiskPanel.localDiskModel.loading.msg"); + private final String NO_DRIVES = NbBundle.getMessage(this.getClass(), "LocalDiskPanel.localDiskModel.nodrives.msg"); LocalDiskThread worker = null; @@ -415,7 +407,7 @@ final class LocalDiskPanel extends JPanel { class LocalDiskThread extends SwingWorker { - private Logger logger = Logger.getLogger(LocalDiskThread.class.getName()); + private final Logger logger = Logger.getLogger(LocalDiskThread.class.getName()); @Override protected Object doInBackground() throws Exception { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index c7825b6458..5fa4c3ec16 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2016 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -122,7 +122,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { @Override public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { if (!setDataSourceOptionsCalled) { - localFilePaths = Arrays.asList(configPanel.getContentPaths().split(LocalFilesPanel.FILES_SEP)); + localFilePaths = configPanel.getContentPaths(); } run(UUID.randomUUID().toString(), configPanel.getFileSetName(), localFilePaths, progressMonitor, callback); } @@ -192,8 +192,11 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { */ @Deprecated public void setDataSourceOptions(String paths) { - //LocalFilesPanel.FILES_SEP is currently "," - this.localFilePaths = Arrays.asList(paths.split(LocalFilesPanel.FILES_SEP)); + // The LocalFilesPanel used to separate file paths with a comma and pass + // them as a string, but because file names are allowed to contain + // commas, this approach was buggy and replaced. We now pass a list of + // String paths. + this.localFilePaths = Arrays.asList(paths.split(",")); setDataSourceOptionsCalled = true; } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index c04aaa5bbf..ba1b357440 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,9 +18,8 @@ */ package org.sleuthkit.autopsy.casemodule; -import java.awt.Dialog; import java.io.File; -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; @@ -32,9 +31,6 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import java.util.logging.Level; import javax.swing.JOptionPane; -import org.openide.DialogDescriptor; -import org.openide.DialogDisplayer; -import org.openide.NotifyDescriptor; import org.sleuthkit.autopsy.casemodule.Case.CaseType; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PathValidator; @@ -42,12 +38,11 @@ import org.sleuthkit.autopsy.coreutils.PathValidator; /** * Add input wizard subpanel for adding local files / dirs to the case */ -class LocalFilesPanel extends JPanel { +final class LocalFilesPanel extends JPanel { - private Set currentFiles = new TreeSet(); //keep currents in a set to disallow duplicates per add + private final Set currentFiles = new TreeSet<>(); //keep currents in a set to disallow duplicates per add private boolean enableNext = false; private static LocalFilesPanel instance; - public static final String FILES_SEP = ","; private static final Logger logger = Logger.getLogger(LocalFilesPanel.class.getName()); private String displayName = ""; @@ -73,38 +68,24 @@ class LocalFilesPanel extends JPanel { this.displayNameLabel.setText(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.displayNameLabel.text")); } - //@Override - public String getContentPaths() { - //TODO consider interface change to return list of paths instead - + public List getContentPaths() { + List pathsList = new ArrayList<>(); if (currentFiles == null) { - return ""; + return pathsList; } - StringBuilder b = new StringBuilder(); for (File f : currentFiles) { - b.append(f.getAbsolutePath()); - b.append(FILES_SEP); + pathsList.add(f.getAbsolutePath()); } - return b.toString(); + return pathsList; } - //@Override - public void setContentPath(String s) { - //for the local file panel we don't need to restore the last paths used - //when the wizard restarts - } - - //@Override public String getContentType() { return NbBundle.getMessage(this.getClass(), "LocalFilesPanel.contentType.text"); } - //@Override public boolean validatePanel() { - // display warning if there is one (but don't disable "next" button) warnIfPathIsInvalid(getContentPaths()); - return enableNext; } @@ -112,13 +93,11 @@ class LocalFilesPanel extends JPanel { * Validates path to selected data source and displays warning if it is * invalid. * - * @param path Absolute path to the selected data source + * @param paths Absolute paths to the selected data source */ - private void warnIfPathIsInvalid(String path) { + private void warnIfPathIsInvalid(List pathsList) { errorLabel.setVisible(false); - // Path variable for "Local files" module is a coma separated string containg multiple paths - List pathsList = Arrays.asList(path.split(",")); CaseType currentCaseType = Case.getCurrentCase().getCaseType(); for (String currentPath : pathsList) { @@ -130,12 +109,10 @@ class LocalFilesPanel extends JPanel { } } - //@Override public void select() { reset(); } - //@Override public void reset() { currentFiles.clear(); selectedPaths.setText(""); @@ -281,14 +258,9 @@ class LocalFilesPanel extends JPanel { } this.selectedPaths.setText(allPaths.toString()); this.selectedPaths.setToolTipText(allPaths.toString()); - } - if (!currentFiles.isEmpty()) { - enableNext = true; - } else { - enableNext = false; - } + enableNext = !currentFiles.isEmpty(); try { firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java index 07cc1b159e..1c20079763 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java @@ -140,6 +140,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.accessed"), ContentUtils.getStringTime(file.getAtime(), file)); addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.created"), ContentUtils.getStringTime(file.getCrtime(), file)); addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.changed"), ContentUtils.getStringTime(file.getCtime(), file)); + String md5 = file.getMd5Hash(); if (md5 == null) { @@ -148,6 +149,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.md5"), md5); addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.hashLookupResults"), file.getKnown().toString()); + addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.internalid"), Long.toString(file.getId())); if (file.getType().compareTo(TSK_DB_FILES_TYPE_ENUM.LOCAL) == 0) { addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.localPath"), file.getLocalAbsPath()); } diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 784556e7a4..473c8fe1ab 100755 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -45,6 +45,8 @@ public final class UserPreferences { public static final String KEEP_PREFERRED_VIEWER = "KeepPreferredViewer"; // NON-NLS public static final String HIDE_KNOWN_FILES_IN_DATA_SOURCES_TREE = "HideKnownFilesInDataSourcesTree"; //NON-NLS public static final String HIDE_KNOWN_FILES_IN_VIEWS_TREE = "HideKnownFilesInViewsTree"; //NON-NLS + public static final String HIDE_SLACK_FILES_IN_DATA_SOURCES_TREE = "HideSlackFilesInDataSourcesTree"; //NON-NLS + public static final String HIDE_SLACK_FILES_IN_VIEWS_TREE = "HideSlackFilesInViewsTree"; //NON-NLS public static final String DISPLAY_TIMES_IN_LOCAL_TIME = "DisplayTimesInLocalTime"; //NON-NLS public static final String NUMBER_OF_FILE_INGEST_THREADS = "NumberOfFileIngestThreads"; //NON-NLS public static final String IS_MULTI_USER_MODE_ENABLED = "IsMultiUserModeEnabled"; //NON-NLS @@ -124,6 +126,22 @@ public final class UserPreferences { preferences.putBoolean(HIDE_KNOWN_FILES_IN_VIEWS_TREE, value); } + public static boolean hideSlackFilesInDataSourcesTree() { + return preferences.getBoolean(HIDE_SLACK_FILES_IN_DATA_SOURCES_TREE, true); + } + + public static void setHideSlackFilesInDataSourcesTree(boolean value) { + preferences.putBoolean(HIDE_SLACK_FILES_IN_DATA_SOURCES_TREE, value); + } + + public static boolean hideSlackFilesInViewsTree() { + return preferences.getBoolean(HIDE_SLACK_FILES_IN_VIEWS_TREE, true); + } + + public static void setHideSlackFilesInViewsTree(boolean value) { + preferences.putBoolean(HIDE_SLACK_FILES_IN_VIEWS_TREE, value); + } + public static boolean displayTimesInLocalTime() { return preferences.getBoolean(DISPLAY_TIMES_IN_LOCAL_TIME, true); } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index f2c44eb4e1..5a169b7329 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -22,12 +22,12 @@ - + - + @@ -49,47 +49,69 @@ - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + - - + + + + + + - - - - - + + + + - - + - @@ -108,7 +130,13 @@ - + + + + + + + @@ -131,7 +159,7 @@ - + @@ -303,6 +331,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 13ee9b0a1b..de9a6e5429 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -101,6 +101,8 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { useBestViewerRB.setSelected(!keepPreferredViewer); dataSourcesHideKnownCB.setSelected(UserPreferences.hideKnownFilesInDataSourcesTree()); viewsHideKnownCB.setSelected(UserPreferences.hideKnownFilesInViewsTree()); + dataSourcesHideSlackCB.setSelected(UserPreferences.hideSlackFilesInDataSourcesTree()); + viewsHideSlackCB.setSelected(UserPreferences.hideSlackFilesInViewsTree()); boolean useLocalTime = UserPreferences.displayTimesInLocalTime(); useLocalTimeRB.setSelected(useLocalTime); useGMTTimeRB.setSelected(!useLocalTime); @@ -124,6 +126,8 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { UserPreferences.setKeepPreferredContentViewer(keepCurrentViewerRB.isSelected()); UserPreferences.setHideKnownFilesInDataSourcesTree(dataSourcesHideKnownCB.isSelected()); UserPreferences.setHideKnownFilesInViewsTree(viewsHideKnownCB.isSelected()); + UserPreferences.setHideSlackFilesInDataSourcesTree(dataSourcesHideSlackCB.isSelected()); + UserPreferences.setHideSlackFilesInViewsTree(viewsHideSlackCB.isSelected()); UserPreferences.setDisplayTimesInLocalTime(useLocalTimeRB.isSelected()); UserPreferences.setNumberOfFileIngestThreads((Integer) numberOfFileIngestThreadsComboBox.getSelectedItem()); @@ -167,6 +171,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { jCheckBoxEnableProcTimeout = new javax.swing.JCheckBox(); jLabelProcessTimeOutUnits = new javax.swing.JLabel(); jFormattedTextFieldProcTimeOutHrs = new JFormattedTextField(NumberFormat.getIntegerInstance()); + dataSourcesHideSlackCB = new javax.swing.JCheckBox(); + viewsHideSlackCB = new javax.swing.JCheckBox(); + jLabelHideSlackFiles = new javax.swing.JLabel(); jScrollPane1.setBorder(null); @@ -253,6 +260,22 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } }); + org.openide.awt.Mnemonics.setLocalizedText(dataSourcesHideSlackCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.dataSourcesHideSlackCB.text")); // NOI18N + dataSourcesHideSlackCB.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + dataSourcesHideSlackCBActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(viewsHideSlackCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.viewsHideSlackCB.text")); // NOI18N + viewsHideSlackCB.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + viewsHideSlackCBActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabelHideSlackFiles, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelHideSlackFiles.text")); // NOI18N + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( @@ -260,38 +283,52 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(10, 10, 10) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(keepCurrentViewerRB) - .addComponent(useBestViewerRB) - .addComponent(dataSourcesHideKnownCB) - .addComponent(viewsHideKnownCB) .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(10, 10, 10) .addComponent(numberOfFileIngestThreadsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) - .addComponent(restartRequiredLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + .addComponent(restartRequiredLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabelTimeDisplay) + .addComponent(jLabelNumThreads) + .addComponent(jLabelSetProcessTimeOut) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(10, 10, 10) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(useLocalTimeRB) + .addComponent(useGMTTimeRB) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jCheckBoxEnableProcTimeout) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jFormattedTextFieldProcTimeOutHrs, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabelProcessTimeOutUnits))))) + .addGap(213, 213, 213))) + .addContainerGap()) .addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabelHideKnownFiles) - .addComponent(jLabelTimeDisplay) + .addComponent(jLabelSelectFile) .addGroup(jPanel1Layout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(useLocalTimeRB) - .addComponent(useGMTTimeRB))) - .addComponent(jLabelSelectFile) - .addComponent(jLabelNumThreads) + .addComponent(keepCurrentViewerRB) + .addComponent(useBestViewerRB) + .addComponent(dataSourcesHideKnownCB) + .addComponent(viewsHideKnownCB)))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabelHideSlackFiles) .addGroup(jPanel1Layout.createSequentialGroup() .addGap(10, 10, 10) - .addComponent(jCheckBoxEnableProcTimeout) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jFormattedTextFieldProcTimeOutHrs, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jLabelProcessTimeOutUnits)) - .addComponent(jLabelSetProcessTimeOut)) - .addGap(213, 213, 213))) - .addContainerGap()) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(dataSourcesHideSlackCB) + .addComponent(viewsHideSlackCB)))) + .addGap(0, 0, Short.MAX_VALUE)))) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -308,7 +345,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addComponent(dataSourcesHideKnownCB) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(viewsHideKnownCB) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabelHideSlackFiles) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(dataSourcesHideSlackCB) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(viewsHideSlackCB) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabelTimeDisplay) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(useLocalTimeRB) @@ -328,7 +371,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jFormattedTextFieldProcTimeOutHrs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabelProcessTimeOutUnits))) - .addContainerGap()) + .addContainerGap(49, Short.MAX_VALUE)) ); jScrollPane1.setViewportView(jPanel1); @@ -337,11 +380,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 657, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 402, Short.MAX_VALUE) + .addComponent(jScrollPane1) ); }// //GEN-END:initComponents @@ -382,13 +425,23 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_jFormattedTextFieldProcTimeOutHrsActionPerformed + private void dataSourcesHideSlackCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataSourcesHideSlackCBActionPerformed + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + }//GEN-LAST:event_dataSourcesHideSlackCBActionPerformed + + private void viewsHideSlackCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewsHideSlackCBActionPerformed + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + }//GEN-LAST:event_viewsHideSlackCBActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup buttonGroup1; private javax.swing.ButtonGroup buttonGroup3; private javax.swing.JCheckBox dataSourcesHideKnownCB; + private javax.swing.JCheckBox dataSourcesHideSlackCB; private javax.swing.JCheckBox jCheckBoxEnableProcTimeout; private javax.swing.JFormattedTextField jFormattedTextFieldProcTimeOutHrs; private javax.swing.JLabel jLabelHideKnownFiles; + private javax.swing.JLabel jLabelHideSlackFiles; private javax.swing.JLabel jLabelNumThreads; private javax.swing.JLabel jLabelProcessTimeOutUnits; private javax.swing.JLabel jLabelSelectFile; @@ -403,5 +456,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private javax.swing.JRadioButton useGMTTimeRB; private javax.swing.JRadioButton useLocalTimeRB; private javax.swing.JCheckBox viewsHideKnownCB; + private javax.swing.JCheckBox viewsHideSlackCB; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 5c705ac4a4..824f195ca4 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -197,3 +197,6 @@ MultiUserSettingsPanel.lbTestSolrWarning.text= MultiUserSettingsPanel.lbTestDbWarning.text= MultiUserSettingsPanel.KeywordSearchNull=Cannot find keyword search service MultiUserSettingsPanel.InvalidPortNumber=Invalid port number +AutopsyOptionsPanel.jLabelHideSlackFiles.text=Hide slack files in the: +AutopsyOptionsPanel.dataSourcesHideSlackCB.text=Data Sources area (the directory hierarchy) +AutopsyOptionsPanel.viewsHideSlackCB.text=Views area diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java index f2babbc88e..10bfbcbcee 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java @@ -33,6 +33,7 @@ import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalFile; +import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.SleuthkitItemVisitor; import org.sleuthkit.datamodel.SleuthkitVisitableItem; import org.sleuthkit.datamodel.VirtualDirectory; @@ -107,6 +108,11 @@ abstract class AbstractContentChildren extends Keys { public AbstractContentNode visit(VirtualDirectory ld) { return new VirtualDirectoryNode(ld); } + + @Override + public AbstractContentNode visit(SlackFile sf) { + return new SlackFileNode(sf); + } @Override protected AbstractContentNode defaultVisit(SleuthkitVisitableItem di) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java index 90a9a38b85..0ea877d9a5 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java @@ -130,6 +130,14 @@ public class ArtifactStringContent implements StringContent { buffer.append(""); //NON-NLS buffer.append("\n"); //NON-NLS + // add artifact ID (useful for debugging) + buffer.append(""); //NON-NLS + buffer.append(NbBundle.getMessage(this.getClass(), "ArtifactStringContent.getStr.artifactId.text")); + buffer.append(""); //NON-NLS + buffer.append(artifact.getArtifactID()); + buffer.append(""); //NON-NLS + buffer.append("\n"); //NON-NLS + buffer.append(""); //NON-NLS buffer.append("\n"); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties index 3c24e02283..cec49dcdeb 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties @@ -222,6 +222,10 @@ ReportNode.reportNameProperty.name=Report Name ReportNode.reportNameProperty.displayName=Report Name ReportNode.reportNameProperty.desc=Name of the report ReportsListNode.displayName=Reports +SlackFileFilterNode.selectionContext.dataSources=Data Sources +SlackFileFilterNode.selectionContext.views=Views +SlackFileNode.getActions.viewInNewWin.text=View in New Window +SlackFileNode.getActions.viewFileInDir.text=View File in Directory TagNameNode.namePlusTags.text={0} Tags TagNameNode.contentTagTypeNodeKey.text=Content Tags TagNameNode.bbArtTagTypeNodeKey.text=Result Tags diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentNodeVisitor.java index fdda586414..6dbd8002ee 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentNodeVisitor.java @@ -41,6 +41,8 @@ interface ContentNodeVisitor { T visit(LayoutFileNode lcn); T visit(LocalFileNode dfn); + + T visit(SlackFileNode sfn); /** * Visitor with an implementable default behavior for all types. Override @@ -93,5 +95,10 @@ interface ContentNodeVisitor { public T visit(VirtualDirectoryNode ldn) { return defaultVisit(ldn); } + + @Override + public T visit(SlackFileNode sfn) { + return defaultVisit(sfn); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java index cd127d5276..1b457966fe 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java @@ -43,6 +43,7 @@ import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.ReadContentInputStream; +import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.VirtualDirectory; @@ -355,6 +356,18 @@ public final class ContentUtils { } return null; } + + @Override + public Void visit(SlackFile f) { + try { + ContentUtils.writeToFile(f, dest, progress, worker, source); + } catch (IOException ex) { + logger.log(Level.SEVERE, + "Trouble extracting slack file to " + dest.getAbsolutePath(), //NON-NLS + ex); + } + return null; + } @Override public Void visit(Directory dir) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataModelActionsFactory.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataModelActionsFactory.java index 6f47d94093..7ab744d712 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataModelActionsFactory.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataModelActionsFactory.java @@ -37,6 +37,7 @@ import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalFile; +import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.VirtualDirectory; /** @@ -80,6 +81,23 @@ public class DataModelActionsFactory { actions.addAll(ContextMenuExtensionPoint.getActions()); return actions; } + + public static List getActions(SlackFile slackFile, boolean isArtifactSource) { + List actions = new ArrayList<>(); + actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), slackFile)); + final SlackFileNode slackFileNode = new SlackFileNode(slackFile); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, slackFileNode)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + actions.add(null); // creates a menu separator + actions.add(AddContentTagAction.getInstance()); + if (isArtifactSource) { + actions.add(AddBlackboardArtifactTagAction.getInstance()); + } + actions.addAll(ContextMenuExtensionPoint.getActions()); + return actions; + } public static List getActions(LayoutFile file, boolean isArtifactSource) { List actions = new ArrayList<>(); @@ -184,6 +202,8 @@ public class DataModelActionsFactory { return getActions((LocalFile) content, isArtifactSource); } else if (content instanceof DerivedFile) { return getActions((DerivedFile) content, isArtifactSource); + } else if (content instanceof SlackFile) { + return getActions((SlackFile) content, isArtifactSource); } else { return new ArrayList<>(); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index e300ace134..a8c5714fb8 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -48,6 +48,9 @@ public interface DisplayableItemNodeVisitor { T visit(ImageNode in); T visit(VolumeNode vn); + + T visit(SlackFileNode sfn); + /* * Views Area @@ -177,6 +180,11 @@ public interface DisplayableItemNodeVisitor { return defaultVisit(vn); } + @Override + public T visit(SlackFileNode sfn) { + return defaultVisit(sfn); + } + @Override public T visit(BlackboardArtifactNode ban) { return defaultVisit(ban); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileFilterNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileFilterNode.java new file mode 100644 index 0000000000..54ce0daad5 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileFilterNode.java @@ -0,0 +1,180 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013-2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed 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. + */ +package org.sleuthkit.autopsy.datamodel; + +import java.util.prefs.PreferenceChangeEvent; +import java.util.prefs.PreferenceChangeListener; +import org.openide.nodes.FilterNode; +import org.openide.nodes.Node; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.TskData; + +/** + * A Filter Node responsible for conditionally filtering out Nodes that + * represent slack files. + * + * Filters known files IF the option to Filter Slack files for the given + * SelectionContext is set. Otherwise, does nothing. + * + */ +public class SlackFileFilterNode extends FilterNode { + + private static boolean filterFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree(); + private static boolean filterFromViews = UserPreferences.hideSlackFilesInViewsTree(); + + static { + UserPreferences.addChangeListener(new PreferenceChangeListener() { + @Override + public void preferenceChange(PreferenceChangeEvent evt) { + switch (evt.getKey()) { + case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SOURCES_TREE: + filterFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree(); + break; + case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE: + filterFromViews = UserPreferences.hideSlackFilesInViewsTree(); + break; + } + } + }); + } + + public enum SelectionContext { + + DATA_SOURCES(NbBundle.getMessage(SlackFileFilterNode.class, "SlackFileFilterNode.selectionContext.dataSources")), + VIEWS(NbBundle.getMessage(SlackFileFilterNode.class, "SlackFileFilterNode.selectionContext.views")), + OTHER(""); // Subnode of another node. + + private final String displayName; + + SelectionContext(String displayName) { + this.displayName = displayName; + } + + public static SelectionContext getContextFromName(String name) { + if (name.equals(DATA_SOURCES.getName())) { + return DATA_SOURCES; + } else if (name.equals(VIEWS.getName())) { + return VIEWS; + } else { + return OTHER; + } + } + + private String getName() { + return displayName; + } + } + + /** + * Create a SlackFileFilterNode from the given Node. Note that the Node + * should be from the directory tree. + * + * @param arg + * @param context + */ + public SlackFileFilterNode(Node arg, SelectionContext context) { + super(arg, new SlackFileFilterChildren(arg, context)); + } + + private SlackFileFilterNode(Node arg, boolean filter) { + super(arg, new SlackFileFilterChildren(arg, filter)); + } + + /** + * Get the selection context of a Node in the DirectoryTree. + * + * @param n + * + * @return + */ + public static SelectionContext getSelectionContext(Node n) { + if (n == null || n.getParentNode() == null) { + // Parent of root node or root node. Occurs during case open / close. + return SelectionContext.OTHER; + } else if (n.getParentNode().getParentNode() == null) { + // One level below root node. Should be one of DataSources, Views, or Results + return SelectionContext.getContextFromName(n.getDisplayName()); + } else { + return getSelectionContext(n.getParentNode()); + } + } + + /** + * Complementary class to SlackFileFilterNode. + * + * Filters out children Nodes that represent slack files. Otherwise, returns + * the original node wrapped in another instance of the SlackFileFilterNode. + * + * @author jwallace + */ + private static class SlackFileFilterChildren extends FilterNode.Children { + + /** + * True if this SlackFileFilterChildren should filter out slack files. + */ + private boolean filter; + + /** + * Constructor used when the context has already been determined. + * + * @param arg + * @param filter + */ + private SlackFileFilterChildren(Node arg, boolean filter) { + super(arg); + this.filter = filter; + } + + /** + * Constructor used when the context has not been determined. + * + * @param arg + * @param context + */ + private SlackFileFilterChildren(Node arg, SlackFileFilterNode.SelectionContext context) { + super(arg); + + switch (context) { + case DATA_SOURCES: + filter = filterFromDataSources; + break; + case VIEWS: + filter = filterFromViews; + break; + default: + filter = false; + break; + } + } + + @Override + protected Node[] createNodes(Node arg) { + if (filter) { + // Filter out child nodes that represent slack files + AbstractFile file = arg.getLookup().lookup(AbstractFile.class); + if ((file != null) && file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) { + return new Node[]{}; + } + } + return new Node[]{new SlackFileFilterNode(arg, filter)}; + } + } +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java new file mode 100644 index 0000000000..863de3d9d8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java @@ -0,0 +1,120 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2016 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed 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. + */ +package org.sleuthkit.autopsy.datamodel; + +import java.util.ArrayList; +import java.util.List; +import javax.swing.Action; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; +import org.sleuthkit.autopsy.directorytree.ExtractAction; +import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; +import org.sleuthkit.autopsy.directorytree.ViewContextAction; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; +import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM; + +/** + * This class is the Node for an AbstractFile. It may have derived files + * children. + */ +public class SlackFileNode extends AbstractFsContentNode { + + /** + * Constructor + * + * @param file underlying Content + */ + public SlackFileNode(AbstractFile file) { + this(file, true); + + setIcon(file); + } + + public SlackFileNode(AbstractFile file, boolean directoryBrowseMode) { + super(file, directoryBrowseMode); + + setIcon(file); + } + + private void setIcon(AbstractFile file) { + // set name, display name, and icon + if (file.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC)) { + if (file.getType().equals(TSK_DB_FILES_TYPE_ENUM.CARVED)) { + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-icon-16.png"); //NON-NLS + } else { + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS + } + } else { + this.setIconBaseWithExtension(getIconForFileType(file)); + } + } + + @Override + public Action[] getActions(boolean popup) { + List actionsList = new ArrayList<>(); + for (Action a : super.getActions(true)) { + actionsList.add(a); + } + + if (!this.getDirectoryBrowseMode()) { + actionsList.add(new ViewContextAction(NbBundle.getMessage(this.getClass(), "SlackFileNode.viewFileInDir.text"), this.content)); + actionsList.add(null); // creates a menu separator + } + actionsList.add(new NewWindowViewAction( + NbBundle.getMessage(this.getClass(), "SlackFileNode.getActions.viewInNewWin.text"), this)); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList.toArray(new Action[actionsList.size()]); + } + + @Override + public T accept(ContentNodeVisitor v) { + return v.visit(this); + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + // Given a file, returns the correct icon for said + // file based off it's extension + static String getIconForFileType(AbstractFile file) { + + return "org/sleuthkit/autopsy/images/file-icon.png"; //NON-NLS + } + + @Override + public boolean isLeafTypeNode() { + // This seems wrong, but it also seems that it is never called + // because the visitor to figure out if there are children or + // not will check if it has children using the Content API + return true; + } + + @Override + public String getItemType() { + return getClass().getName(); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index ec66a5d4c7..97d5edf35b 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -45,6 +45,7 @@ import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.Reports; +import org.sleuthkit.autopsy.datamodel.SlackFileNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -55,6 +56,7 @@ import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalFile; +import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.VirtualDirectory; @@ -200,6 +202,8 @@ public class DataResultFilterNode extends FilterNode { } else if ((c = ban.getLookup().lookup(LocalFile.class)) != null || (c = ban.getLookup().lookup(DerivedFile.class)) != null) { n = new LocalFileNode((AbstractFile) c); + } else if ((c = ban.getLookup().lookup(SlackFile.class)) != null) { + n = new SlackFileNode((SlackFile) c); } if (n != null) { actions.add(null); // creates a menu separator diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java index e6ce27bc0e..4ea3d721f0 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java @@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; +import org.sleuthkit.autopsy.datamodel.SlackFileNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VolumeNode; import org.sleuthkit.datamodel.AbstractFile; @@ -225,6 +226,11 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { public Boolean visit(LayoutFileNode fn) { return visitDeep(fn); } + + @Override + public Boolean visit(SlackFileNode sfn) { + return visitDeep(sfn); + } @Override public Boolean visit(VolumeNode vn) { @@ -267,6 +273,11 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { public Boolean visit(LayoutFileNode ln) { return ln.hasContentChildren(); } + + @Override + public Boolean visit(SlackFileNode sfn) { + return sfn.hasContentChildren(); + } @Override public Boolean visit(VirtualDirectoryNode vdn) { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 8f63752a27..dbd38cf9aa 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -68,6 +68,7 @@ import org.sleuthkit.autopsy.datamodel.Reports; import org.sleuthkit.autopsy.datamodel.Results; import org.sleuthkit.autopsy.datamodel.ResultsNode; import org.sleuthkit.autopsy.datamodel.RootContentChildren; +import org.sleuthkit.autopsy.datamodel.SlackFileFilterNode; import org.sleuthkit.autopsy.datamodel.Tags; import org.sleuthkit.autopsy.datamodel.Views; import org.sleuthkit.autopsy.datamodel.ViewsNode; @@ -128,9 +129,11 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat public void preferenceChange(PreferenceChangeEvent evt) { switch (evt.getKey()) { case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SOURCES_TREE: + case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SOURCES_TREE: refreshContentTreeSafe(); break; case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE: + case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE: // TODO: Need a way to refresh the Views subtree break; } @@ -637,12 +640,14 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat //set node, wrap in filter node first to filter out children Node drfn = new DataResultFilterNode(originNode, DirectoryTreeTopComponent.this.em); Node kffn = new KnownFileFilterNode(drfn, KnownFileFilterNode.getSelectionContext(originNode)); + Node sffn = new SlackFileFilterNode(kffn, SlackFileFilterNode.getSelectionContext(originNode)); + // Create a TableFilterNode with knowledge of the node's type to allow for column order settings if (originNode instanceof DisplayableItemNode) { - dataResult.setNode(new TableFilterNode(kffn, true, ((DisplayableItemNode) originNode).getItemType())); + dataResult.setNode(new TableFilterNode(sffn, true, ((DisplayableItemNode) originNode).getItemType())); } else { - dataResult.setNode(new TableFilterNode(kffn, true)); + dataResult.setNode(new TableFilterNode(sffn, true)); } String displayName = ""; diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerAction.java index d9551499cc..e79840fd20 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerAction.java @@ -30,6 +30,7 @@ import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.datamodel.SlackFileNode; /** * Extracts a File object to a temporary file in the case directory, and then @@ -68,7 +69,8 @@ public class ExternalViewerAction extends AbstractAction { // no point opening a file if it's empty, and java doesn't know how to // find an application for files without an extension // or if file is executable (for security reasons) - if (!(size > 0) || extPos == -1 || isExecutable) { + // Also skip slack files since their extension is the original extension + "-slack" + if (!(size > 0) || extPos == -1 || isExecutable || (fileNode instanceof SlackFileNode)) { this.setEnabled(false); } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/GetRootDirectoryVisitor.java b/Core/src/org/sleuthkit/autopsy/ingest/GetRootDirectoryVisitor.java index 14a1f446ae..28085cee96 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/GetRootDirectoryVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/GetRootDirectoryVisitor.java @@ -27,6 +27,7 @@ import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.FileSystem; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalFile; +import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.VirtualDirectory; /** @@ -85,4 +86,11 @@ final class GetRootDirectoryVisitor extends GetFilesContentVisitor { return getAllFromChildren(localFile); } + @Override + public Collection visit(SlackFile slackFile) { + //can have slack files + //TODO test this and overall scheduler with local files + return getAllFromChildren(slackFile); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java index dfd5adf689..04052b1ce6 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java @@ -46,9 +46,9 @@ final class IngestMessageTopComponent extends TopComponent { private static final Logger logger = Logger.getLogger(IngestMessageTopComponent.class.getName()); private IngestMessageMainPanel messagePanel; private IngestManager manager; - private static String PREFERRED_ID = "IngestMessageTopComponent"; //NON-NLS - private ActionListener showIngestInboxAction; - private static final Pattern tagRemove = Pattern.compile("<.+?>"); + private static final String PREFERRED_ID = "IngestMessageTopComponent"; //NON-NLS + private final ActionListener showIngestInboxAction; + private static final Pattern TAG_REMOVE = Pattern.compile("<.+?>"); public IngestMessageTopComponent() { initComponents(); @@ -292,6 +292,7 @@ final class IngestMessageTopComponent extends TopComponent { */ } + @Override public Action[] getActions() { //disable TC toolbar actions return new Action[0]; @@ -302,7 +303,7 @@ final class IngestMessageTopComponent extends TopComponent { return string; } - Matcher m = tagRemove.matcher(string); + Matcher m = TAG_REMOVE.matcher(string); return m.replaceAll(""); } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java index 5c44c49cbf..fac3307653 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed 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. @@ -145,8 +145,9 @@ class IngestMessagesToolbar extends javax.swing.JPanel { if (mode != null) { //TopComponent[] tcs = mode.getTopComponents(); mode.dockInto(tc); + String something = mode.getName(); tc.open(); - //tc.requestActive(); + //tc.requestActive(); } } @@ -158,7 +159,7 @@ class IngestMessagesToolbar extends javax.swing.JPanel { private static class IngestMessagesButton extends JButton { - private static final int fontSize = 9; + private static final int FONT_SIZE = 9; private int messages = 0; @Override @@ -169,7 +170,7 @@ class IngestMessagesToolbar extends javax.swing.JPanel { return; } //paint text - Font messagesFont = g.getFont().deriveFont(Font.PLAIN, fontSize); + Font messagesFont = g.getFont().deriveFont(Font.PLAIN, FONT_SIZE); String messageStr = Integer.toString(messages); final int len = messageStr.length(); g.setFont(messagesFont); @@ -181,9 +182,9 @@ class IngestMessagesToolbar extends javax.swing.JPanel { } g.setColor(Color.GRAY); //g.fillRect(x, 1, dx, fontSize); - g.fillRoundRect(x, 1, dx, fontSize, 2, 2); + g.fillRoundRect(x, 1, dx, FONT_SIZE, 2, 2); g.setColor(Color.WHITE); - g.drawString(messageStr, x + 2, fontSize); + g.drawString(messageStr, x + 2, FONT_SIZE); } void setMessages(int messages) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java index b1fa9d478e..582c5c04c4 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java @@ -108,7 +108,8 @@ public final class EmbeddedFileExtractorIngestModule implements FileIngestModule @Override public ProcessResult process(AbstractFile abstractFile) { // skip the unallocated blocks - if (abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)) { + if ((abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)) || + (abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) { return ProcessResult.OK; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java index 1fd1bd9116..a1d0809ae0 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java @@ -104,7 +104,8 @@ public final class ExifParserFileIngestModule implements FileIngestModule { blackboard = Case.getCurrentCase().getServices().getBlackboard(); //skip unalloc - if (content.getType().equals(TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)) { + if ((content.getType().equals(TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || + (content.getType().equals(TSK_DB_FILES_TYPE_ENUM.SLACK)))) { return ProcessResult.OK; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties index 6faf2a71eb..79d8ab3dff 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties @@ -19,7 +19,6 @@ FileExtMismatchIngestModule.complete.totalFiles=Total Files Processed FileExtMismatchIngestModule.complete.svcMsg.text=File Extension Mismatch Results FileExtMismatchOptionsPanelController.moduleErr=Module Error FileExtMismatchOptionsPanelController.moduleErr.msg=A module caused an error listening to FileExtMismatchOptionsPanelController updates. See log to determine which module. Some data could be incomplete. -FileExtMismatchModuleSettingsPanel.skipTextPlain.text=Skip text files FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text=Skip files without extensions FileExtMismatchSettingsPanel.extHeaderLabel.text=Allowed Extensions: FileExtMismatchSettingsPanel.removeExtButton.text=Delete Extension @@ -55,3 +54,6 @@ FileExtMismatchSettingsPanel.removeExtButton.noneSelected.title=No extension sel FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.message=No MIME type selected\! FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.title=No MIME type selected FileExtMismatchSettingsPanel.removeTypeButton.toolTipText= +FileExtMismatchModuleSettingsPanel.checkAllRadioButton.text=Check all file types +FileExtMismatchModuleSettingsPanel.checkNoTextRadioButton.text=Check all file types except text files +FileExtMismatchModuleSettingsPanel.checkMediaExeRadioButton.text=Check only multimedia and executable files diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties index e4e4186689..fc35bab029 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties @@ -33,7 +33,6 @@ FileExtMismatchIngestModule.complete.svcMsg.text=\u30d5\u30a1\u30a4\u30eb\u62e1\ FileExtMismatchOptionsPanelController.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc FileExtMismatchOptionsPanelController.moduleErr.msg=FileExtMismatchOptionsPanelController\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306e\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 AddFileExtensionAction.extHeaderLbl.text=\u4e0b\u8a18\u7528\u306b\u8a31\u53ef\u3059\u308b\u62e1\u5f35\u5b50 -FileExtMismatchModuleSettingsPanel.skipTextPlain.text=\u30c6\u30ad\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u30b9\u30ad\u30c3\u30d7 FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text=\u62e1\u5f35\u5b50\u306e\u7121\u3044\u30d5\u30a1\u30a4\u30eb\u3092\u30b9\u30ad\u30c3\u30d7 FileExtMismatchSettingsPanel.extHeaderLabel.text=\u8a31\u53ef\u3059\u308b\u62e1\u5f35\u5b50\uff1a FileExtMismatchSettingsPanel.removeExtButton.text=\u9078\u629e\u3057\u305f\u62e1\u5f35\u5b50\u3092\u524a\u9664 diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java index 0efbd24db8..2e11bccc41 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java @@ -20,71 +20,161 @@ package org.sleuthkit.autopsy.modules.fileextmismatch; import java.io.IOException; import java.io.ObjectInputStream; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; /** - * Ingest options for the file extension mismatch detector ingest module. + * Ingest options for the file extension mismatch detection ingest module. */ final class FileExtMismatchDetectorModuleSettings implements IngestModuleIngestJobSettings { private static final long serialVersionUID = 1L; private long versionNumber; private boolean skipFilesWithNoExtension; - private boolean skipFilesWithTextPlainMimeType; + @Deprecated + private boolean skipFilesWithTextPlainMimeType; // No longer used, retained to maintain serialization compatibility. private boolean skipKnownFiles; + private CHECK_TYPE checkType; + /* + * Extension mismatches can be checked for all files, for all files except + * text files, or for media and executable files only. + */ + enum CHECK_TYPE { + ALL, NO_TEXT_FILES, ONLY_MEDIA_AND_EXE + } + + /* + * The set of the MIME types that will be checked for extension mismatches + * when checkType is ONLY_MEDIA_AND_EXE. + */ + static final Set MEDIA_AND_EXE_MIME_TYPES = Stream.of( + "image/bmp", + "image/gif", + "image/jpeg", + "image/png", + "image/tiff", + "image/x-ms-bmp", + "application/dos-exe", + "application/exe", + "application/x-dosexec", + "application/x-exe", + "application/x-msdownload").collect(Collectors.toSet()); + + /** + * Constructs an object with the ingest options for the file extension + * mismatch detection ingest module. + */ FileExtMismatchDetectorModuleSettings() { + this.versionNumber = 2; this.skipFilesWithNoExtension = true; - this.skipFilesWithTextPlainMimeType = true; this.skipKnownFiles = true; + this.checkType = CHECK_TYPE.ONLY_MEDIA_AND_EXE; } - FileExtMismatchDetectorModuleSettings(boolean skipKnownFiles, boolean skipFilesWithNoExtension, boolean skipFilesWithTextPlainMimeType) { - this.skipFilesWithNoExtension = skipFilesWithNoExtension; - this.skipFilesWithTextPlainMimeType = skipFilesWithTextPlainMimeType; - this.skipKnownFiles = skipKnownFiles; - } - + /** + * Gets the serialization version number. + * + * @return A serialization version number. + */ @Override public long getVersionNumber() { return serialVersionUID; } + /** + * Sets the flag indicating whether or not files without extensions should + * be skipped during file extension mismatch checking. + * + * @param skipFilesWithNoExtension The desired value of the flag. + */ void setSkipFilesWithNoExtension(boolean skipFilesWithNoExtension) { this.skipFilesWithNoExtension = skipFilesWithNoExtension; } + /** + * Gets the flag indicating whether or not files without extensions should + * be skipped during file extension mismatch checking. + * + * @return The flag value. + */ boolean skipFilesWithNoExtension() { return skipFilesWithNoExtension; } - void setSkipFilesWithTextPlainMimeType(boolean skipFilesWithTextPlainMimeType) { - this.skipFilesWithTextPlainMimeType = skipFilesWithTextPlainMimeType; - } - - boolean skipFilesWithTextPlainMimeType() { - return skipFilesWithTextPlainMimeType; - } - - boolean skipKnownFiles() { - return skipKnownFiles; - } - + /** + * Sets the flag indicating whether or not known files should be skipped + * during file extension mismatch checking. + * + * @param skipKnownFiles The desired value of the flag. + */ void setSkipKnownFiles(boolean skipKnownFiles) { this.skipKnownFiles = skipKnownFiles; } + /** + * Gets the flag indicating whether or not known files should be skipped + * during file extension mismatch checking. + * + * @return The flag value. + */ + boolean skipKnownFiles() { + return skipKnownFiles; + } + + /** + * Sets whether extension mismatches should be checked for all files, for + * all files except text files, or for media and executable files only. + * + * @param checkType The check type. + */ + void setCheckType(CHECK_TYPE checkType) { + this.checkType = checkType; + } + + /** + * Gets whether extension mismatches should be checked for all files, for + * all files except text files, or for media and executable files only. + * + * @return checkType The check type. + */ + CHECK_TYPE getCheckType() { + return checkType; + } + + /** + * Called by convention by the serialization infrastructure when + * deserializing a FileExtMismatchDetectorModuleSettings object. + * + * @param in The object input stream provided by the serialization + * infrastructure. + * + * @throws IOException If there is a problem reading the + * serialized data. + * @throws ClassNotFoundException If the class definition for the serialized + * data cannot be found. + */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); if (0L == versionNumber) { /* * If the version number is set to the Java field default value of - * zero, then skipKnownFiles is a new field. Change this to the - * desired default value of true. + * zero, then versionNumber and skipKnownFiles are new fields. + * Change this to the desired default value of true. */ skipKnownFiles = true; + versionNumber = 1; + } + if (1 == versionNumber) { + /* + * Set the default value of the new checkType field, it is currently + * null. + */ + checkType = CHECK_TYPE.ONLY_MEDIA_AND_EXE; + versionNumber = 2; } - versionNumber = 1; } - + } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java index 80fd6280db..76ce1eb28c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java @@ -34,6 +34,7 @@ import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; +import org.sleuthkit.autopsy.modules.fileextmismatch.FileExtMismatchDetectorModuleSettings.CHECK_TYPE; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -116,6 +117,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule { // skip non-files if ((abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || (abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) + || (abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK) || (abstractFile.isFile() == false)) { return ProcessResult.OK; } @@ -173,9 +175,16 @@ public class FileExtMismatchIngestModule implements FileIngestModule { if (currActualSigType == null) { return false; } - if (settings.skipFilesWithTextPlainMimeType()) { - if (!currActualExt.isEmpty() && currActualSigType.equals("text/plain")) { //NON-NLS - return false; + if (settings.getCheckType() != CHECK_TYPE.ALL) { + if (settings.getCheckType() == CHECK_TYPE.NO_TEXT_FILES) { + if (!currActualExt.isEmpty() && currActualSigType.equals("text/plain")) { //NON-NLS + return false; + } + } + if (settings.getCheckType() == CHECK_TYPE.ONLY_MEDIA_AND_EXE) { + if (!FileExtMismatchDetectorModuleSettings.MEDIA_AND_EXE_MIME_TYPES.contains(currActualSigType)) { + return false; + } } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.form index 878f2ca87b..aee1d6cedf 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.form @@ -1,6 +1,10 @@
+ + + + @@ -19,23 +23,30 @@ - + + + - + + + + + + + + - - - + @@ -52,19 +63,6 @@ - - - - - - - - - - - - - @@ -76,5 +74,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.java index a59f445387..7c141f8733 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,11 +22,12 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; /** - * UI component used to set ingest job options for file extension mismatch - * detector ingest modules. + * UI component used to set ingest job options for the file extension mismatch + * detection ingest module. */ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSettingsPanel { + private static final long serialVersionUID = 1L; private final FileExtMismatchDetectorModuleSettings settings; FileExtMismatchModuleSettingsPanel(FileExtMismatchDetectorModuleSettings settings) { @@ -36,8 +37,21 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett } private void customizeComponents() { + switch (settings.getCheckType()) { + case ALL: + checkAllRadioButton.setSelected(true); + break; + case NO_TEXT_FILES: + checkNoTextRadioButton.setSelected(true); + break; + case ONLY_MEDIA_AND_EXE: + checkMediaExeRadioButton.setSelected(true); + break; + default: + checkMediaExeRadioButton.setSelected(true); + break; + } skipNoExtCheckBox.setSelected(settings.skipFilesWithNoExtension()); - skipTextPlain.setSelected(settings.skipFilesWithTextPlainMimeType()); skipKnownFiles.setSelected(settings.skipKnownFiles()); } @@ -55,9 +69,12 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett // //GEN-BEGIN:initComponents private void initComponents() { + checkTypeButtonGroup = new javax.swing.ButtonGroup(); skipNoExtCheckBox = new javax.swing.JCheckBox(); - skipTextPlain = new javax.swing.JCheckBox(); skipKnownFiles = new javax.swing.JCheckBox(); + checkAllRadioButton = new javax.swing.JRadioButton(); + checkNoTextRadioButton = new javax.swing.JRadioButton(); + checkMediaExeRadioButton = new javax.swing.JRadioButton(); skipNoExtCheckBox.setSelected(true); skipNoExtCheckBox.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text")); // NOI18N @@ -67,14 +84,6 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett } }); - skipTextPlain.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.skipTextPlain.text")); // NOI18N - skipTextPlain.setSelected(true); - skipTextPlain.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - skipTextPlainActionPerformed(evt); - } - }); - skipKnownFiles.setSelected(true); skipKnownFiles.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.skipKnownFiles.text")); // NOI18N skipKnownFiles.addActionListener(new java.awt.event.ActionListener() { @@ -83,6 +92,30 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett } }); + checkTypeButtonGroup.add(checkAllRadioButton); + checkAllRadioButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.checkAllRadioButton.text")); // NOI18N + checkAllRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkAllRadioButtonActionPerformed(evt); + } + }); + + checkTypeButtonGroup.add(checkNoTextRadioButton); + checkNoTextRadioButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.checkNoTextRadioButton.text")); // NOI18N + checkNoTextRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkNoTextRadioButtonActionPerformed(evt); + } + }); + + checkTypeButtonGroup.add(checkMediaExeRadioButton); + checkMediaExeRadioButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.checkMediaExeRadioButton.text")); // NOI18N + checkMediaExeRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkMediaExeRadioButtonActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -90,20 +123,27 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(skipTextPlain) + .addComponent(checkAllRadioButton) + .addComponent(checkNoTextRadioButton) + .addComponent(checkMediaExeRadioButton) .addComponent(skipNoExtCheckBox) .addComponent(skipKnownFiles)) - .addGap(0, 10, Short.MAX_VALUE)) + .addGap(0, 0, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(checkAllRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(checkNoTextRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(checkMediaExeRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(skipNoExtCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(skipTextPlain) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(skipKnownFiles) - .addContainerGap(28, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -111,17 +151,28 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett settings.setSkipFilesWithNoExtension(skipNoExtCheckBox.isSelected()); }//GEN-LAST:event_skipNoExtCheckBoxActionPerformed - private void skipTextPlainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipTextPlainActionPerformed - settings.setSkipFilesWithTextPlainMimeType(skipTextPlain.isSelected()); - }//GEN-LAST:event_skipTextPlainActionPerformed - private void skipKnownFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipKnownFilesActionPerformed settings.setSkipKnownFiles(skipKnownFiles.isSelected()); }//GEN-LAST:event_skipKnownFilesActionPerformed + private void checkAllRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkAllRadioButtonActionPerformed + settings.setCheckType(FileExtMismatchDetectorModuleSettings.CHECK_TYPE.ALL); + }//GEN-LAST:event_checkAllRadioButtonActionPerformed + + private void checkNoTextRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkNoTextRadioButtonActionPerformed + settings.setCheckType(FileExtMismatchDetectorModuleSettings.CHECK_TYPE.NO_TEXT_FILES); + }//GEN-LAST:event_checkNoTextRadioButtonActionPerformed + + private void checkMediaExeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkMediaExeRadioButtonActionPerformed + settings.setCheckType(FileExtMismatchDetectorModuleSettings.CHECK_TYPE.ONLY_MEDIA_AND_EXE); + }//GEN-LAST:event_checkMediaExeRadioButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JRadioButton checkAllRadioButton; + private javax.swing.JRadioButton checkMediaExeRadioButton; + private javax.swing.JRadioButton checkNoTextRadioButton; + private javax.swing.ButtonGroup checkTypeButtonGroup; private javax.swing.JCheckBox skipKnownFiles; private javax.swing.JCheckBox skipNoExtCheckBox; - private javax.swing.JCheckBox skipTextPlain; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form index 8c34097b98..162aef8994 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form @@ -47,7 +47,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index 378c758f16..b0f95c93fa 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -207,7 +207,8 @@ public class FileTypeDetector { if (!file.isFile() || file.getSize() <= 0 || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) - || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) { + || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR) + || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) { mimeType = MimeTypes.OCTET_STREAM; } @@ -282,17 +283,6 @@ public class FileTypeDetector { * Add the MIME type to the files table in the case database. */ Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType); - - /* - * Post to the blackboard, adding the file type attribute to the - * general info artifact. A property change is not fired for this - * posting because general info artifacts are different from other - * artifacts, e.g., they are not displayed in the results tree. - */ - BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); - @SuppressWarnings("deprecation") - BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); - getInfoArt.addAttribute(batt); } return mimeType; diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java index 5c02d69424..ef4e0add71 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java @@ -84,7 +84,6 @@ public class FileTypeIdIngestModule implements FileIngestModule { @Override public ProcessResult process(AbstractFile file) { - /** * Attempt to detect the file type. Do it within an exception firewall, * so that any issues with reading file content or complaints from tika diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/TikaFileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/TikaFileTypeDetector.java index fd5b100e54..e8bd4ab29b 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/TikaFileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/TikaFileTypeDetector.java @@ -39,30 +39,6 @@ public class TikaFileTypeDetector { private final int BUFFER_SIZE = 64 * 1024; //how many bytes to pass in private final byte buffer[] = new byte[BUFFER_SIZE]; - /** - * Detect the mime type of the passed in file and save it to the blackboard - * - * @param abstractFile - * - * @return mime type or null - * - * @throws TskCoreException - * @deprecated Use FileTypeDetector.detectAndPostToBlackboard(AbstractFile - * file) instead. - */ - @Deprecated - public synchronized String detectAndSave(AbstractFile abstractFile) throws TskCoreException { - String mimeType = detect(abstractFile); - if (mimeType != null) { - // add artifact - BlackboardArtifact getInfoArt = abstractFile.getGenInfoArtifact(); - BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG.getTypeID(), FileTypeIdModuleFactory.getModuleName(), mimeType); - getInfoArt.addAttribute(batt); - - // we don't fire the event because we just updated TSK_GEN_INFO, which isn't displayed in the tree and is vague. - } - return mimeType; - } /** * Detect the mime type of the passed in file diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 98baebadd5..7326debb84 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -146,7 +146,8 @@ public class HashDbIngestModule implements FileIngestModule { blackboard = Case.getCurrentCase().getServices().getBlackboard(); // Skip unallocated space files. - if (file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)) { + if ((file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || + file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) { return ProcessResult.OK; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java index 26e29091a1..10e314f7ec 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java @@ -39,6 +39,7 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; /** * A file ingest module that generates interesting files set hit artifacts for @@ -102,6 +103,11 @@ final class FilesIdentifierIngestModule implements FileIngestModule { @Messages({"FilesIdentifierIngestModule.indexError.message=Failed to index interesting file hit artifact for keyword search."}) public ProcessResult process(AbstractFile file) { blackboard = Case.getCurrentCase().getServices().getBlackboard(); + + // Skip slack space files. + if (file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) { + return ProcessResult.OK; + } // See if the file belongs to any defined interesting files set. List filesSets = FilesIdentifierIngestModule.interestingFileSetsByJob.get(this.context.getJobId()); diff --git a/Core/src/org/sleuthkit/autopsy/python/JythonModuleLoader.java b/Core/src/org/sleuthkit/autopsy/python/JythonModuleLoader.java index c9175f3754..b50742f197 100755 --- a/Core/src/org/sleuthkit/autopsy/python/JythonModuleLoader.java +++ b/Core/src/org/sleuthkit/autopsy/python/JythonModuleLoader.java @@ -74,7 +74,7 @@ public final class JythonModuleLoader { // add python modules from 'autospy/build/cluster/InternalPythonModules' folder // which are copied from 'autopsy/*/release/InternalPythonModules' folders. - for (File f : InstalledFileLocator.getDefault().locateAll("InternalPythonModules", JythonModuleLoader.class.getPackage().getName(), false)) { //NON-NLS + for (File f : InstalledFileLocator.getDefault().locateAll("InternalPythonModules", "org.sleuthkit.autopsy.core", false)) { //NON-NLS Collections.addAll(pythonModuleDirs, f.listFiles()); } // add python modules from 'testuserdir/python_modules' folder diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java b/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java index 574459fe11..5e32ce5016 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java @@ -65,7 +65,6 @@ public final class ReportWizardAction extends CallableSystemAction implements Pr wiz.setTitleFormat(new MessageFormat("{0} {1}")); wiz.setTitle(NbBundle.getMessage(ReportWizardAction.class, "ReportWizardAction.reportWiz.title")); if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) { - @SuppressWarnings("unchecked") ReportGenerator generator = new ReportGenerator(); //NON-NLS TableReportModule tableReport = (TableReportModule) wiz.getProperty("tableModule"); GeneralReportModule generalReport = (GeneralReportModule) wiz.getProperty("generalModule"); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/actions/ViewFileInTimelineAction.java b/Core/src/org/sleuthkit/autopsy/timeline/actions/ViewFileInTimelineAction.java index f90837e1f6..75085293a2 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/actions/ViewFileInTimelineAction.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/actions/ViewFileInTimelineAction.java @@ -24,6 +24,7 @@ import org.openide.util.NbBundle; import org.openide.util.actions.SystemAction; import org.sleuthkit.autopsy.timeline.OpenTimelineAction; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.TskData; /** * An action to prompt the user to pick an timestamp/event associated with the @@ -38,6 +39,11 @@ public final class ViewFileInTimelineAction extends AbstractAction { private ViewFileInTimelineAction(AbstractFile file, String displayName) { super(displayName); this.file = file; + + if(file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK) + || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)){ + this.setEnabled(false); + } } @NbBundle.Messages({"ViewFileInTimelineAction.viewFile.displayName=View File in Timeline... "}) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java b/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java index 90757b0a69..75c64fc5ef 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java @@ -517,7 +517,8 @@ public class EventsRepository { //reset database //TODO: can we do more incremental updates? -jm eventDB.reInitializeDB(); //grab ids of all files - List fileIDs = skCase.findAllFileIdsWhere("name != '.' AND name != '..'"); //NON-NLS + List fileIDs = skCase.findAllFileIdsWhere("name != '.' AND name != '..'" + + " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()); //NON-NLS final int numFiles = fileIDs.size(); trans = eventDB.beginTransaction(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties index 1ac7f0fbbd..2afdc83e03 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties @@ -29,6 +29,7 @@ KeywordSearchEditListPanel.pasteMenuItem.text=Paste KeywordSearchEditListPanel.copyMenuItem.text=Copy KeywordSearchEditListPanel.exportButton.text=Export List KeywordSearchEditListPanel.deleteListButton.text=Delete List +KeywordSearchEditListPanel.emptyKeyword.text=Empty keyword KeywordSearchListsManagementPanel.newListButton.text=New List KeywordSearchListsManagementPanel.importButton.text=Import List KeywordSearchListsViewerPanel.searchAddButton.text=Search @@ -101,7 +102,6 @@ KeywordSearchEditListPanel.exportButtonActionPerformed.fileFilterLabel=Keyword L KeywordSearchEditListPanel.exportButtonActionPerformed.fileExistPrompt=File {0} exists, overwrite? KeywordSearchEditListPanel.exportButtonActionPerformed.kwListExportedMsg=Keyword lists exported KeywordSearchEditListPanel.kwColName=Keyword -KeywordSearchEditListPanel.exportButtonActionPerformed.regExColName=RegEx KeywordSearchEditListPanel.addKeyword.message=Add a new word to the keyword search list\: KeywordSearchEditListPanel.addKeyword.title=New keyword KeywordSearchFilterNode.getFileActions.openExternViewActLbl=Open in External Viewer @@ -132,7 +132,7 @@ KeywordSearchListsViewerPanel.initIngest.ongoingIngestMsg=Files Indexed\: {0} (i KeywordSearchListsViewerPanel.initIngest.fileIndexCtMsg=Files Indexed\: {0} KeywordSearch.selectedColLbl=Selected KeywordSearch.nameColLbl=Name -KeywordSearch.regExColLbl=RegEx +KeywordSearch.typeColLbl=Keyword Type KeywordSearchQueryManager.execute.exeWinTitle=Keyword search {0} - {1} KeywordSearch.newKeywordListMsg=New Keyword List KeywordSearch.importListFileDialogMsg=Error importing keyword list from file {0} @@ -290,3 +290,8 @@ RawText.getText.error.msg=Error getting text GlobalListsManagementPanel.newListButton.text=New List GlobalListsManagementPanel.importButton.text=Import List GlobalListsManagementPanel.keywordListsLabel.text=Keyword Lists: +NewKeywordPanel.regexButton.text=Regular Expression +NewKeywordPanel.exactButton.text=Exact Match +NewKeywordPanel.substringButton.text=Substring Match +NewKeywordPanel.keywordTextField.text= +NewKeywordPanel.newKeywordLabel.text=Enter a new keyword: diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java index 7a1986d341..40cc83cd92 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed 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. @@ -39,9 +39,6 @@ import org.openide.util.NbBundle; import org.openide.util.actions.SystemAction; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; -import javax.swing.ImageIcon; -import static javax.swing.SwingConstants.CENTER; -import javax.swing.table.DefaultTableCellRenderer; /** * Viewer panel widget for keyword lists that is used in the ingest config and @@ -93,10 +90,9 @@ class DropdownListSearchPanel extends KeywordSearchPanel { for (int i = 0; i < keywordsTable.getColumnCount(); i++) { column = keywordsTable.getColumnModel().getColumn(i); if (i == 0) { - column.setPreferredWidth(((int) (rightWidth * 0.78))); + column.setPreferredWidth(((int) (rightWidth * 0.60))); } else { - column.setPreferredWidth(((int) (rightWidth * 0.20))); - column.setCellRenderer(new CheckBoxRenderer()); + column.setPreferredWidth(((int) (rightWidth * 0.38))); } } @@ -123,12 +119,9 @@ class DropdownListSearchPanel extends KeywordSearchPanel { public void propertyChange(PropertyChangeEvent evt) { Object source = evt.getSource(); if (source instanceof String && ((String) source).equals("LOCAL")) { //NON-NLS - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - ingestRunning = IngestManager.getInstance().isIngestRunning(); - updateComponents(); - } + EventQueue.invokeLater(() -> { + ingestRunning = IngestManager.getInstance().isIngestRunning(); + updateComponents(); }); } } @@ -320,8 +313,8 @@ class DropdownListSearchPanel extends KeywordSearchPanel { private class KeywordListsTableModel extends AbstractTableModel { //data - private XmlKeywordSearchList listsHandle = XmlKeywordSearchList.getCurrent(); - private List listData = new ArrayList<>(); + private final XmlKeywordSearchList listsHandle = XmlKeywordSearchList.getCurrent(); + private final List listData = new ArrayList<>(); @Override public int getColumnCount() { @@ -496,7 +489,7 @@ class DropdownListSearchPanel extends KeywordSearchPanel { ret = NbBundle.getMessage(this.getClass(), "KeywordSearch.nameColLbl"); break; case 1: - ret = NbBundle.getMessage(this.getClass(), "KeywordSearch.regExColLbl"); + ret = NbBundle.getMessage(this.getClass(), "KeywordSearch.typeColLbl"); break; default: break; @@ -519,7 +512,7 @@ class DropdownListSearchPanel extends KeywordSearchPanel { ret = (Object) entry.name; break; case 1: - ret = (Object) entry.regex; + ret = (Object) entry.keywordType; break; default: break; @@ -559,11 +552,11 @@ class DropdownListSearchPanel extends KeywordSearchPanel { private class KeywordTableEntry implements Comparable { String name; - Boolean regex; + String keywordType; KeywordTableEntry(Keyword keyword) { this.name = keyword.getSearchTerm(); - this.regex = !keyword.searchTermIsLiteral(); + this.keywordType = keyword.getSearchTermType(); } @Override @@ -598,33 +591,4 @@ class DropdownListSearchPanel extends KeywordSearchPanel { return this; } } - - /** - * A cell renderer for boolean cells that shows a center-aligned green check - * mark if true, nothing if false. - */ - private class CheckBoxRenderer extends DefaultTableCellRenderer { - - private static final long serialVersionUID = 1L; - final ImageIcon theCheck = new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/checkmark.png")); // NON-NLS - - CheckBoxRenderer() { - setHorizontalAlignment(CENTER); - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - - if ((value instanceof Boolean)) { - if ((Boolean) value) { - setIcon(theCheck); - setToolTipText(Bundle.IsRegularExpression()); - } else { - setIcon(null); - setToolTipText(null); - } - } - return this; - } - } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleKeywordSearchPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleKeywordSearchPanel.java index 9201bcfddf..c6b079bc70 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleKeywordSearchPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleKeywordSearchPanel.java @@ -52,6 +52,7 @@ public class DropdownSingleKeywordSearchPanel extends KeywordSearchPanel { * Gets the default instance of a dropdown panel that provides GUI * components that allow a user to do three types of ad hoc single keyword * searches. + * @return the default instance of DropdownSingleKeywordSearchPanel */ public static synchronized DropdownSingleKeywordSearchPanel getDefault() { if (null == defaultInstance) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.java index 5ec5463d8e..4b9ea3a7bd 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed 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. @@ -42,18 +42,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.FlowLayout; -import javax.swing.ImageIcon; -import javax.swing.JCheckBox; -import javax.swing.JLabel; import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; -import static javax.swing.SwingConstants.CENTER; -import javax.swing.table.DefaultTableCellRenderer; -import org.openide.util.NbBundle.Messages; /** * GlobalEditListPanel widget to manage keywords in lists @@ -90,7 +79,6 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis column.setPreferredWidth(((int) (width * 0.90))); } else { column.setPreferredWidth(((int) (width * 0.10))); - column.setCellRenderer(new CheckBoxRenderer()); } } keywordTable.setCellSelectionEnabled(false); @@ -110,18 +98,13 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis setButtonStates(); - setButtonStates(); - IngestManager.getInstance().addIngestJobEventListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { Object source = evt.getSource(); if (source instanceof String && ((String) source).equals("LOCAL")) { //NON-NLS - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - setButtonStates(); - } + EventQueue.invokeLater(() -> { + setButtonStates(); }); } } @@ -351,35 +334,26 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis }// //GEN-END:initComponents private void newWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newWordButtonActionPerformed - JCheckBox chRegex = new JCheckBox(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.chRegex.text")); - chRegex.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.kwReToolTip")); - JTextField addWordField = new JTextField(25); - addWordField.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.enterNewWordToolTip")); + NewKeywordPanel panel = new NewKeywordPanel(); - JPanel addKeywordPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); - addKeywordPanel.add(new JLabel(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.addKeyword.message"))); - addKeywordPanel.add(addWordField); - addKeywordPanel.add(chRegex); - - addKeywordPanel.setPreferredSize(new Dimension(250, 80)); - - int result = JOptionPane.showConfirmDialog(null, addKeywordPanel, + int result = JOptionPane.showConfirmDialog(null, panel, NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.addKeyword.title"), JOptionPane.OK_CANCEL_OPTION); if (result == JOptionPane.OK_OPTION) { - String newWord = addWordField.getText().trim(); - boolean isLiteral = !chRegex.isSelected(); - final Keyword keyword = new Keyword(newWord, isLiteral); - - if (newWord.equals("")) { + String newWord = panel.getKeywordText(); + if (newWord.isEmpty()) { + KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.newKwTitle"), + NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.emptyKeyword.text"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO); return; - } else if (currentKeywordList.hasKeyword(keyword)) { + } + final Keyword keyword = new Keyword(newWord, !panel.isKeywordRegex(), panel.isKeywordExact()); + if (currentKeywordList.hasKeyword(keyword)) { KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.newKwTitle"), NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.addWordButtonAction.kwAlreadyExistsMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO); return; } - + //check if valid boolean valid = true; try { @@ -394,15 +368,13 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.invalidKwMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); return; } - + //add & reset checkbox tableModel.addKeyword(keyword); XmlKeywordSearchList.getCurrent().addList(currentKeywordList); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); setFocusOnKeywordTextBox(); setButtonStates(); - } else { - return; } }//GEN-LAST:event_newWordButtonActionPerformed @@ -563,11 +535,10 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis colName = NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.kwColName"); break; case 1: - colName = NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.regExColName"); + colName = NbBundle.getMessage(this.getClass(), "KeywordSearch.typeColLbl"); break; default: ; - } return colName; } @@ -581,10 +552,10 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis Keyword word = currentKeywordList.getKeywords().get(rowIndex); switch (columnIndex) { case 0: - ret = (Object) word.getSearchTerm(); + ret = word.getSearchTerm(); break; case 1: - ret = (Object) !word.searchTermIsLiteral(); + ret = word.getSearchTermType(); break; default: logger.log(Level.SEVERE, "Invalid table column index: {0}", columnIndex); //NON-NLS @@ -629,36 +600,6 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis } } - /** - * A cell renderer for boolean cells that shows a center-aligned green check - * mark if true, nothing if false. - */ - private class CheckBoxRenderer extends DefaultTableCellRenderer { - - private static final long serialVersionUID = 1L; - final ImageIcon theCheck = new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/checkmark.png")); // NON-NLS - - CheckBoxRenderer() { - setHorizontalAlignment(CENTER); - } - - @Override - @Messages("IsRegularExpression=Keyword is a regular expression") - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - - if ((value instanceof Boolean)) { - if ((Boolean) value) { - setIcon(theCheck); - setToolTipText(Bundle.IsRegularExpression()); - } else { - setIcon(null); - setToolTipText(null); - } - } - return this; - } - } - /** * Set the keyboard focus to new keyword textbox. */ diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java index 6bae3b666c..bac57fc76d 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * - * Copyright 2011-2014 Basis Technology Corp. + * + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed 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. @@ -76,7 +76,7 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option JOptionPane.PLAIN_MESSAGE, null, null, - currentKeywordList != null ? currentKeywordList.getName() : ""); + currentKeywordList.getName()); if (listName == null || listName.trim().equals("")) { return; } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListsManagementPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListsManagementPanel.java index 031ec3199f..abc9a0bebd 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListsManagementPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListsManagementPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,8 +40,8 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa private static final long serialVersionUID = 1L; - private Logger logger = Logger.getLogger(GlobalListsManagementPanel.class.getName()); - private KeywordListTableModel tableModel; + private final Logger logger = Logger.getLogger(GlobalListsManagementPanel.class.getName()); + private final KeywordListTableModel tableModel; private final org.sleuthkit.autopsy.keywordsearch.GlobalListSettingsPanel globalListSettingsPanel; GlobalListsManagementPanel(org.sleuthkit.autopsy.keywordsearch.GlobalListSettingsPanel gsp) { @@ -345,7 +345,7 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa private class KeywordListTableModel extends AbstractTableModel { - private XmlKeywordSearchList listsHandle = XmlKeywordSearchList.getCurrent(); + private final XmlKeywordSearchList listsHandle = XmlKeywordSearchList.getCurrent(); @Override public int getColumnCount() { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java index 169e9cb0ec..256d4508f2 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java @@ -43,6 +43,7 @@ import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.ReadContentInputStream; +import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.TskCoreException; /** @@ -215,6 +216,13 @@ class Ingester { return params; } + @Override + public Map visit(SlackFile f) { + Map params = getCommonFields(f); + getCommonFileContentFields(params, f); + return params; + } + private Map getCommonFileContentFields(Map params, AbstractFile file) { params.put(Server.Schema.CTIME.toString(), ContentUtils.getStringTimeISO8601(file.getCtime(), file)); params.put(Server.Schema.ATIME.toString(), ContentUtils.getStringTimeISO8601(file.getAtime(), file)); @@ -256,7 +264,6 @@ class Ingester { * @throws org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException */ void ingest(ContentStream cs, Map fields, final long size) throws IngesterException { - if (fields.get(Server.Schema.IMAGE_ID.toString()) == null) { //skip the file, image id unknown String msg = NbBundle.getMessage(this.getClass(), diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java index 93acd0ee78..0c84da9c73 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.keywordsearch; +import org.openide.util.NbBundle; import org.sleuthkit.datamodel.BlackboardAttribute; /** @@ -119,6 +120,18 @@ class Keyword { return isWholeWord; } + String getSearchTermType() { + if (isLiteral) { + if (isWholeWord) { + return NbBundle.getMessage(NewKeywordPanel.class, "NewKeywordPanel.exactButton.text"); + } else { + return NbBundle.getMessage(NewKeywordPanel.class, "NewKeywordPanel.substringButton.text"); + } + } else { + return NbBundle.getMessage(NewKeywordPanel.class, "NewKeywordPanel.regexButton.text"); + } + } + /** * Sets the artifact attribute type associated with the keyword, if any. * @@ -159,9 +172,9 @@ class Keyword { return false; } Keyword other = (Keyword) obj; - return (this.searchTerm.equals(other.searchTerm) - && this.isLiteral == other.isLiteral - && this.isWholeWord == other.isWholeWord); + return (this.searchTerm.equals(other.getSearchTerm()) + && this.isLiteral == other.searchTermIsLiteral() + && this.isWholeWord == other.searchTermIsWholeWord()); } @Override diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java index a88b11582b..1756bfc1ec 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchList.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchList.java index 79e09cd788..01f0e146f0 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchList.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchList.java @@ -46,7 +46,7 @@ abstract class KeywordSearchList { private static final String CCN_REGEX = ".*[3456]([ -]?\\d){11,18}.*"; //12-19 digits, with possible single spaces or dashes in between. first digit is 3,4,5, or 6 //NON-NLS protected String filePath; - Map theLists; //the keyword data + Map theLists; //the keyword data PropertyChangeSupport changeSupport; protected List lockedLists; @@ -320,7 +320,7 @@ abstract class KeywordSearchList { } boolean addList(String name, List newList, boolean useForIngest, boolean ingestMessages) { - //make sure that the list is readded as a locked/built in list + //make sure that the list is readded as a locked/built in list boolean isLocked = this.lockedLists.contains(name); return addList(name, newList, useForIngest, ingestMessages, isLocked); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/NewKeywordPanel.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/NewKeywordPanel.form new file mode 100755 index 0000000000..2c72c5055c --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/NewKeywordPanel.form @@ -0,0 +1,108 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/NewKeywordPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/NewKeywordPanel.java new file mode 100755 index 0000000000..f96738be67 --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/NewKeywordPanel.java @@ -0,0 +1,142 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2016 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed 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. + */ +package org.sleuthkit.autopsy.keywordsearch; + +/** + * A panel that is contained in NewKeywordDialog used when the user wants to add + * a new keyword to a list via the options panel. This panel allows the user to + * indicate whether they want the keyword to be an exact match, a substring, or + * a regular expression. + */ +class NewKeywordPanel extends javax.swing.JPanel { + + /** + * Creates new form NewKeywordPanel + */ + public NewKeywordPanel() { + initComponents(); + } + + /** + * @return the text for the new keyword + */ + String getKeywordText() { + return keywordTextField.getText(); + } + + /** + * @return true if the regular expression radio button is selected + */ + boolean isKeywordRegex() { + return regexButton.isSelected(); + } + + /** + * @return true if the exact match radio button is selected + */ + boolean isKeywordExact() { + return exactButton.isSelected(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + keywordTypeButtonGroup = new javax.swing.ButtonGroup(); + keywordTextField = new javax.swing.JTextField(); + exactButton = new javax.swing.JRadioButton(); + substringButton = new javax.swing.JRadioButton(); + regexButton = new javax.swing.JRadioButton(); + newKeywordLabel = new javax.swing.JLabel(); + + keywordTextField.setText(org.openide.util.NbBundle.getMessage(NewKeywordPanel.class, "NewKeywordPanel.keywordTextField.text")); // NOI18N + keywordTextField.addAncestorListener(new javax.swing.event.AncestorListener() { + public void ancestorMoved(javax.swing.event.AncestorEvent evt) { + } + public void ancestorAdded(javax.swing.event.AncestorEvent evt) { + keywordTextFieldAncestorAdded(evt); + } + public void ancestorRemoved(javax.swing.event.AncestorEvent evt) { + } + }); + + keywordTypeButtonGroup.add(exactButton); + exactButton.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(exactButton, org.openide.util.NbBundle.getMessage(NewKeywordPanel.class, "NewKeywordPanel.exactButton.text")); // NOI18N + + keywordTypeButtonGroup.add(substringButton); + org.openide.awt.Mnemonics.setLocalizedText(substringButton, org.openide.util.NbBundle.getMessage(NewKeywordPanel.class, "NewKeywordPanel.substringButton.text")); // NOI18N + + keywordTypeButtonGroup.add(regexButton); + org.openide.awt.Mnemonics.setLocalizedText(regexButton, org.openide.util.NbBundle.getMessage(NewKeywordPanel.class, "NewKeywordPanel.regexButton.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(newKeywordLabel, org.openide.util.NbBundle.getMessage(NewKeywordPanel.class, "NewKeywordPanel.newKeywordLabel.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(exactButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(substringButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(regexButton)) + .addComponent(newKeywordLabel) + .addComponent(keywordTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 305, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(newKeywordLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(keywordTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(exactButton) + .addComponent(substringButton) + .addComponent(regexButton)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void keywordTextFieldAncestorAdded(javax.swing.event.AncestorEvent evt) {//GEN-FIRST:event_keywordTextFieldAncestorAdded + evt.getComponent().requestFocusInWindow(); + }//GEN-LAST:event_keywordTextFieldAncestorAdded + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JRadioButton exactButton; + private javax.swing.JTextField keywordTextField; + private javax.swing.ButtonGroup keywordTypeButtonGroup; + private javax.swing.JLabel newKeywordLabel; + private javax.swing.JRadioButton regexButton; + private javax.swing.JRadioButton substringButton; + // End of variables declaration//GEN-END:variables +} diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/XmlKeywordSearchList.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/XmlKeywordSearchList.java index 87d792557f..a5c25d1dc7 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/XmlKeywordSearchList.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/XmlKeywordSearchList.java @@ -55,6 +55,7 @@ final class XmlKeywordSearchList extends KeywordSearchList { private static final String LIST_INGEST_MSGS = "ingest_messages"; //NON-NLS private static final String KEYWORD_EL = "keyword"; //NON-NLS private static final String KEYWORD_LITERAL_ATTR = "literal"; //NON-NLS + private static final String KEYWORD_WHOLE_ATTR = "whole"; //NON-NLS private static final String KEYWORD_SELECTOR_ATTR = "selector"; //NON-NLS private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; //NON-NLS private static final String ENCODING = "UTF-8"; //NON-NLS @@ -125,6 +126,8 @@ final class XmlKeywordSearchList extends KeywordSearchList { Element keywordEl = doc.createElement(KEYWORD_EL); String literal = keyword.searchTermIsLiteral() ? "true" : "false"; //NON-NLS keywordEl.setAttribute(KEYWORD_LITERAL_ATTR, literal); + String whole = keyword.searchTermIsWholeWord() ? "true" : "false"; //NON-NLS + keywordEl.setAttribute(KEYWORD_WHOLE_ATTR, whole); BlackboardAttribute.ATTRIBUTE_TYPE selectorType = keyword.getArtifactAttributeType(); if (selectorType != null) { keywordEl.setAttribute(KEYWORD_SELECTOR_ATTR, selectorType.getLabel()); @@ -195,14 +198,20 @@ final class XmlKeywordSearchList extends KeywordSearchList { Element wordEl = (Element) wordsNList.item(j); String literal = wordEl.getAttribute(KEYWORD_LITERAL_ATTR); boolean isLiteral = literal.equals("true"); //NON-NLS - Keyword keyword = new Keyword(wordEl.getTextContent(), isLiteral); + Keyword keyword; + String whole = wordEl.getAttribute(KEYWORD_WHOLE_ATTR); + if (whole.equals("")) { + keyword = new Keyword(wordEl.getTextContent(), isLiteral); + } else { + boolean isWhole = whole.equals("true"); + keyword = new Keyword(wordEl.getTextContent(), isLiteral, isWhole); + } String selector = wordEl.getAttribute(KEYWORD_SELECTOR_ATTR); if (!selector.equals("")) { BlackboardAttribute.ATTRIBUTE_TYPE selectorType = BlackboardAttribute.ATTRIBUTE_TYPE.fromLabel(selector); keyword.setArtifactAttributeType(selectorType); } words.add(keyword); - } theLists.put(name, list); } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 8a55b855e8..d924a9cabe 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -1,19 +1,19 @@ /* * * Autopsy Forensic Browser - * + * * Copyright 2012-2014 Basis Technology Corp. - * + * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com * Project Contact/Architect: carrier sleuthkit org - * + * * Licensed 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. @@ -68,7 +68,7 @@ class ExtractRegistry extends Extract { private String RR_PATH; private String RR_FULL_PATH; private Path rrHome; // Path to the Autopsy version of RegRipper - private Path rrFullHome; // Path to the full version of RegRipper + private Path rrFullHome; // Path to the full version of RegRipper private Content dataSource; private IngestJobContext context; final private static UsbDeviceIdMapper USB_MAPPER = new UsbDeviceIdMapper(); @@ -198,7 +198,7 @@ class ExtractRegistry extends Extract { } // create a report for the full output - if (regOutputFiles.fullPlugins.isEmpty() == false) { + if (!regOutputFiles.fullPlugins.isEmpty()) { try { currentCase.addReport(regOutputFiles.fullPlugins, NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"), "RegRipper " + regFile.getUniquePath()); //NON-NLS } catch (TskCoreException e) { @@ -363,321 +363,327 @@ class ExtractRegistry extends Extract { String winver = ""; // If all artifact nodes should really go under one Blackboard artifact, need to process it differently - if (dataType.equals("WinVersion")) { //NON-NLS + switch (dataType) { + case "WinVersion": //NON-NLS + String version = ""; + String systemRoot = ""; + String productId = ""; + String regOwner = ""; + String regOrg = ""; + Long installtime = null; + for (int j = 0; j < myartlist.getLength(); j++) { + Node artchild = myartlist.item(j); + // If it has attributes, then it is an Element (based off API) + if (artchild.hasAttributes()) { + Element artnode = (Element) artchild; - String version = ""; - String systemRoot = ""; - String productId = ""; - String regOwner = ""; - String regOrg = ""; - Long installtime = null; - - for (int j = 0; j < myartlist.getLength(); j++) { - Node artchild = myartlist.item(j); - // If it has attributes, then it is an Element (based off API) - if (artchild.hasAttributes()) { - Element artnode = (Element) artchild; - - String value = artnode.getTextContent().trim(); - String name = artnode.getAttribute("name"); //NON-NLS - - if (name.equals("ProductName")) { // NON-NLS - version = value; - } else if (name.equals("CSDVersion")) { // NON-NLS - // This is dependant on the fact that ProductName shows up first in the module output - version = version + " " + value; - } else if (name.equals("SystemRoot")) { //NON-NLS - systemRoot = value; - } else if (name.equals("ProductId")) { //NON-NLS - productId = value; - } else if (name.equals("RegisteredOwner")) { //NON-NLS - regOwner = value; - } else if (name.equals("RegisteredOrganization")) { //NON-NLS - regOrg = value; - } else if (name.equals("InstallDate")) { //NON-NLS - try { - Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(value).getTime(); - installtime = epochtime; - String Tempdate = installtime.toString(); - installtime = Long.valueOf(Tempdate) / 1000; - } catch (ParseException e) { - logger.log(Level.SEVERE, "RegRipper::Conversion on DateTime -> ", e); //NON-NLS + String value = artnode.getTextContent().trim(); + String name = artnode.getAttribute("name"); //NON-NLS + switch (name) { + case "ProductName": // NON-NLS + version = value; + break; + case "CSDVersion": // NON-NLS + // This is dependant on the fact that ProductName shows up first in the module output + version = version + " " + value; + break; + case "SystemRoot": //NON-NLS + systemRoot = value; + break; + case "ProductId": //NON-NLS + productId = value; + break; + case "RegisteredOwner": //NON-NLS + regOwner = value; + break; + case "RegisteredOrganization": //NON-NLS + regOrg = value; + break; + case "InstallDate": //NON-NLS + try { + Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(value).getTime(); + installtime = epochtime; + String Tempdate = installtime.toString(); + installtime = Long.valueOf(Tempdate) / 1000; + } catch (ParseException e) { + logger.log(Level.SEVERE, "RegRipper::Conversion on DateTime -> ", e); //NON-NLS + } break; + default: + break; } } - } - } - - try { - Collection bbattributes = new ArrayList<>(); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version)); - if (installtime != null) { - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime)); - } - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg)); - - // Check if there is already an OS_INFO artifact for this file, and add to that if possible. - ArrayList results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); - if (results.isEmpty()) { - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); - bbart.addAttributes(bbattributes); - - // index the artifact for keyword search - this.indexArtifact(bbart); - } else { - results.get(0).addAttributes(bbattributes); - } - - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS - } - } else if (dataType.equals("Profiler")) { // NON-NLS - - String os = ""; - String procArch = ""; - String procId = ""; - String tempDir = ""; - - for (int j = 0; j < myartlist.getLength(); j++) { - Node artchild = myartlist.item(j); - // If it has attributes, then it is an Element (based off API) - if (artchild.hasAttributes()) { - Element artnode = (Element) artchild; - - String value = artnode.getTextContent().trim(); - String name = artnode.getAttribute("name"); //NON-NLS - - if (name.equals("OS")) { // NON-NLS - os = value; - } else if (name.equals("PROCESSOR_ARCHITECTURE")) { // NON-NLS - procArch = value; - } else if (name.equals("PROCESSOR_IDENTIFIER")) { //NON-NLS - procId = value; - } else if (name.equals("TEMP")) { //NON-NLS - tempDir = value; - } - } - } - - try { - Collection bbattributes = new ArrayList<>(); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir)); - - // Check if there is already an OS_INFO artifact for this file and add to that if possible - ArrayList results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); - if (results.isEmpty()) { - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); - bbart.addAttributes(bbattributes); - - // index the artifact for keyword search - this.indexArtifact(bbart); - } else { - results.get(0).addAttributes(bbattributes); - } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS - } - } else if (dataType.equals("CompName")) { // NON-NLS - - String compName = ""; - String domain = ""; - - for (int j = 0; j < myartlist.getLength(); j++) { - Node artchild = myartlist.item(j); - // If it has attributes, then it is an Element (based off API) - if (artchild.hasAttributes()) { - Element artnode = (Element) artchild; - - String value = artnode.getTextContent().trim(); - String name = artnode.getAttribute("name"); //NON-NLS - - if (name.equals("ComputerName")) { // NON-NLS - compName = value; - } else if (name.equals("Domain")) { // NON-NLS - domain = value; - } - } - } - - try { - Collection bbattributes = new ArrayList<>(); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain)); - - // Check if there is already an OS_INFO artifact for this file and add to that if possible - ArrayList results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); - if (results.isEmpty()) { - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); - bbart.addAttributes(bbattributes); - - // index the artifact for keyword search - this.indexArtifact(bbart); - } else { - results.get(0).addAttributes(bbattributes); - } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS - } - } else { - for (int j = 0; j < myartlist.getLength(); j++) { - Node artchild = myartlist.item(j); - // If it has attributes, then it is an Element (based off API) - if (artchild.hasAttributes()) { - Element artnode = (Element) artchild; - - String value = artnode.getTextContent().trim(); + } try { Collection bbattributes = new ArrayList<>(); - - switch (dataType) { - case "recentdocs": //NON-NLS - // BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); - // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime)); - // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem)); - // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value)); - // bbart.addAttributes(bbattributes); - // @@@ BC: Why are we ignoring this... - break; - case "usb": //NON-NLS - try { - Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS - usbMtime = Long.valueOf(usbMtime.toString()); - - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime)); - String dev = artnode.getAttribute("dev"); //NON-NLS - String make = ""; - String model = dev; - if (dev.toLowerCase().contains("vid")) { //NON-NLS - USBInfo info = USB_MAPPER.parseAndLookup(dev); - if (info.getVendor() != null) { - make = info.getVendor(); - } - if (info.getProduct() != null) { - model = info.getProduct(); - } - } - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value)); - bbart.addAttributes(bbattributes); - - // index the artifact for keyword search - this.indexArtifact(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard."); //NON-NLS - } - break; - case "uninstall": //NON-NLS - Long itemMtime = null; - try { - Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute("mtime")).getTime(); //NON-NLS - itemMtime = epochtime; - itemMtime = itemMtime / 1000; - } catch (ParseException e) { - logger.log(Level.WARNING, "Failed to parse epoch time for installed program artifact."); //NON-NLS - } - - try { - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime)); - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG); - bbart.addAttributes(bbattributes); - - // index the artifact for keyword search - this.indexArtifact(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS - } - break; - case "office": //NON-NLS - String officeName = artnode.getAttribute("name"); //NON-NLS - - try { - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); - // @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item - if (mtime != null) { - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime)); - } - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName())); - bbart.addAttributes(bbattributes); - - // index the artifact for keyword search - this.indexArtifact(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding recent object artifact to blackboard."); //NON-NLS - } - break; - - case "ProcessorArchitecture": //NON-NLS - // Architecture is now included under Profiler - //try { - // String processorArchitecture = value; - // if (processorArchitecture.equals("AMD64")) - // processorArchitecture = "x86-64"; - - // BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); - // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID(), parentModuleName, processorArchitecture)); - // bbart.addAttributes(bbattributes); - //} catch (TskCoreException ex) { - // logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS - //} - break; - - case "ProfileList": //NON-NLS - try { - - String homeDir = value; - String sid = artnode.getAttribute("sid"); //NON-NLS - String username = artnode.getAttribute("username"); //NON-NLS - - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); - bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, - parentModuleName, username)); - bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, - parentModuleName, sid)); - bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, - parentModuleName, homeDir)); - // index the artifact for keyword search - this.indexArtifact(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding account artifact to blackboard."); //NON-NLS - } - break; - - case "NtuserNetwork": // NON-NLS - try { - String localPath = artnode.getAttribute("localPath"); //NON-NLS - String remoteName = value; - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE); - bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH, - parentModuleName, localPath)); - bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH, - parentModuleName, remoteName)); - // index the artifact for keyword search - this.indexArtifact(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding network artifact to blackboard."); //NON-NLS - } - break; - - case "shellfolders": // NON-NLS - // The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer - // (https://technet.microsoft.com/en-us/library/Cc962613.aspx). - // No useful information. Skip. - break; - - default: - logger.log(Level.WARNING, "Unrecognized node name: {0}", dataType); //NON-NLS - break; + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version)); + if (installtime != null) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime)); } + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg)); + + // Check if there is already an OS_INFO artifact for this file, and add to that if possible. + ArrayList results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); + if (results.isEmpty()) { + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } else { + results.get(0).addAttributes(bbattributes); + } + + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS } - } + break; + case "Profiler": // NON-NLS + String os = ""; + String procArch = ""; + String procId = ""; + String tempDir = ""; + for (int j = 0; j < myartlist.getLength(); j++) { + Node artchild = myartlist.item(j); + // If it has attributes, then it is an Element (based off API) + if (artchild.hasAttributes()) { + Element artnode = (Element) artchild; + + String value = artnode.getTextContent().trim(); + String name = artnode.getAttribute("name"); //NON-NLS + switch (name) { + case "OS": // NON-NLS + os = value; + break; + case "PROCESSOR_ARCHITECTURE": // NON-NLS + procArch = value; + break; + case "PROCESSOR_IDENTIFIER": //NON-NLS + procId = value; + break; + case "TEMP": //NON-NLS + tempDir = value; + break; + default: + break; + } + } + } try { + Collection bbattributes = new ArrayList<>(); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir)); + + // Check if there is already an OS_INFO artifact for this file and add to that if possible + ArrayList results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); + if (results.isEmpty()) { + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } else { + results.get(0).addAttributes(bbattributes); + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS + } + break; + case "CompName": // NON-NLS + String compName = ""; + String domain = ""; + for (int j = 0; j < myartlist.getLength(); j++) { + Node artchild = myartlist.item(j); + // If it has attributes, then it is an Element (based off API) + if (artchild.hasAttributes()) { + Element artnode = (Element) artchild; + + String value = artnode.getTextContent().trim(); + String name = artnode.getAttribute("name"); //NON-NLS + + if (name.equals("ComputerName")) { // NON-NLS + compName = value; + } else if (name.equals("Domain")) { // NON-NLS + domain = value; + } + } + } try { + Collection bbattributes = new ArrayList<>(); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain)); + + // Check if there is already an OS_INFO artifact for this file and add to that if possible + ArrayList results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); + if (results.isEmpty()) { + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } else { + results.get(0).addAttributes(bbattributes); + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS + } + break; + default: + for (int j = 0; j < myartlist.getLength(); j++) { + Node artchild = myartlist.item(j); + // If it has attributes, then it is an Element (based off API) + if (artchild.hasAttributes()) { + Element artnode = (Element) artchild; + + String value = artnode.getTextContent().trim(); + Collection bbattributes = new ArrayList<>(); + + switch (dataType) { + case "recentdocs": //NON-NLS + // BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); + // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime)); + // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem)); + // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value)); + // bbart.addAttributes(bbattributes); + // @@@ BC: Why are we ignoring this... + break; + case "usb": //NON-NLS + try { + Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS + usbMtime = Long.valueOf(usbMtime.toString()); + + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime)); + String dev = artnode.getAttribute("dev"); //NON-NLS + String make = ""; + String model = dev; + if (dev.toLowerCase().contains("vid")) { //NON-NLS + USBInfo info = USB_MAPPER.parseAndLookup(dev); + if (info.getVendor() != null) { + make = info.getVendor(); + } + if (info.getProduct() != null) { + model = info.getProduct(); + } + } + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value)); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard."); //NON-NLS + } + break; + case "uninstall": //NON-NLS + Long itemMtime = null; + try { + Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute("mtime")).getTime(); //NON-NLS + itemMtime = epochtime; + itemMtime = itemMtime / 1000; + } catch (ParseException e) { + logger.log(Level.WARNING, "Failed to parse epoch time for installed program artifact."); //NON-NLS + } + + try { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime)); + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS + } + break; + case "office": //NON-NLS + String officeName = artnode.getAttribute("name"); //NON-NLS + + try { + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); + // @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item + if (mtime != null) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime)); + } + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName())); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding recent object artifact to blackboard."); //NON-NLS + } + break; + + case "ProcessorArchitecture": //NON-NLS + // Architecture is now included under Profiler + //try { + // String processorArchitecture = value; + // if (processorArchitecture.equals("AMD64")) + // processorArchitecture = "x86-64"; + + // BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); + // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID(), parentModuleName, processorArchitecture)); + // bbart.addAttributes(bbattributes); + //} catch (TskCoreException ex) { + // logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS + //} + break; + + case "ProfileList": //NON-NLS + try { + + String homeDir = value; + String sid = artnode.getAttribute("sid"); //NON-NLS + String username = artnode.getAttribute("username"); //NON-NLS + + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); + bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, + parentModuleName, username)); + bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, + parentModuleName, sid)); + bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, + parentModuleName, homeDir)); + // index the artifact for keyword search + this.indexArtifact(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding account artifact to blackboard."); //NON-NLS + } + break; + + case "NtuserNetwork": // NON-NLS + try { + String localPath = artnode.getAttribute("localPath"); //NON-NLS + String remoteName = value; + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE); + bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH, + parentModuleName, localPath)); + bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH, + parentModuleName, remoteName)); + // index the artifact for keyword search + this.indexArtifact(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding network artifact to blackboard."); //NON-NLS + } + break; + + case "shellfolders": // NON-NLS + // The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer + // (https://technet.microsoft.com/en-us/library/Cc962613.aspx). + // No useful information. Skip. + break; + + default: + logger.log(Level.WARNING, "Unrecognized node name: {0}", dataType); //NON-NLS + break; + } + } + } break; } } return true; @@ -706,5 +712,4 @@ class ExtractRegistry extends Extract { this.context = context; analyzeRegistryFiles(); } - } diff --git a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java index ea5827d49e..9784a1b712 100644 --- a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java @@ -81,7 +81,8 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { } //skip unalloc - if (abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)) { + if ((abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)) || + (abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) { return ProcessResult.OK; }