Merge pull request #3749 from zhhl/3779-addDSFilterToFileSearchByattributes

3779 add data source filter to file search by attributes
This commit is contained in:
Richard Cordovano 2018-05-14 18:48:24 -04:00 committed by GitHub
commit 6f80293990
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 408 additions and 1 deletions

View File

@ -55,3 +55,7 @@ MimeTypePanel.mimeTypeCheckBox.text=MIME Type:
HashSearchPanel.md5CheckBox.text=MD5:
HashSearchPanel.emptyHashMsg.text=Must enter something for hash search.
FileSearchPanel.errorLabel.text=\
DataSourcePanel.dataSourceCheckBox.label=Data Source:
DataSourcePanel.dataSourceCheckBox.actionCommand=Data Source:
DataSourcePanel.dataSourceCheckBox.text=Data Source:
DataSourcePanel.dataSourceNoteLabel.text=*Note: Multiple data sources can be selected

View File

@ -0,0 +1,77 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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.filesearch;
import java.awt.event.ActionListener;
import org.openide.util.NbBundle.Messages;
/**
* Filter by mime type used in filter areas of file search by attribute.
*/
class DataSourceFilter extends AbstractFileSearchFilter<DataSourcePanel> {
/**
* Construct DataSourceFilter with the DataSourcePanel
* @param component A DataSourcePanel
*/
public DataSourceFilter(DataSourcePanel component) {
super(component);
}
/**
* Default constructor to construct a new DataSourceFilter with a new DataSourcePanel
*/
public DataSourceFilter() {
this(new DataSourcePanel());
}
@Override
public boolean isEnabled() {
return this.getComponent().isSelected();
}
@Override
public String getPredicate() throws FilterValidationException {
String predicate = "";
for (Long dataSourceObjId : this.getComponent().getDataSourcesSelected()) {
if (!predicate.isEmpty()) {
predicate += " OR ";
}
predicate += "data_source_obj_id = '" + dataSourceObjId + "'";
}
return predicate;
}
@Override
public void addActionListener(ActionListener lis) {
//Unused by now
}
@Override
@Messages ({
"DataSourceFilter.errorMessage.emptyDataSource=At least one data source must be selected."
})
public boolean isValid() {
if(this.getComponent().getDataSourcesSelected().isEmpty()){
setLastError(Bundle.DataSourceFilter_errorMessage_emptyDataSource());
return false;
}
return true;
}
}

View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[150, 150]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 100]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="dataSourceCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" pref="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="dataSourceNoteLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="dataSourceCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="95" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="dataSourceNoteLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JList" name="dataSourceList">
<Properties>
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.AbstractListModel&lt;String&gt;() {&#xa; List&lt;String&gt; strings = getDataSourceArray();&#xa; public int getSize() { return strings.size(); }&#xa; public String getElementAt(int idx) { return strings.get(idx); }&#xa;}" type="code"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 200]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_SerializeTo" type="java.lang.String" value="DataSourcePanel_dataSourceList"/>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JCheckBox" name="dataSourceCheckBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DataSourcePanel.dataSourceCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleName" type="java.lang.String" value=""/>
</AccessibilityProperties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="dataSourceCheckBoxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="dataSourceNoteLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="10" style="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DataSourcePanel.dataSourceNoteLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,218 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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.filesearch;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.JList;
import javax.swing.event.ListSelectionEvent;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Subpanel with controls for data source filtering.
*/
public class DataSourcePanel extends javax.swing.JPanel {
private static final Logger logger = Logger.getLogger(DataSourcePanel.class.getName());
private static final long serialVersionUID = 1L;
private final Map<Long, String> dataSourceMap = new HashMap<>();
private final List<String> toolTipList = new ArrayList<>();
/**
* Creates new form DataSourcePanel
*/
public DataSourcePanel() {
initComponents();
this.dataSourceList.addListSelectionListener((ListSelectionEvent evt) -> {
firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
});
this.dataSourceList.addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent evt) {
//Unused by now
}
@Override
public void mouseMoved(MouseEvent evt) {
JList<String> DsList = (JList<String>) evt.getSource();
int index = DsList.locationToIndex(evt.getPoint());
if (index > -1) {
DsList.setToolTipText(toolTipList.get(index));
}
}
});
}
/**
* Get dataSourceMap with object id and data source display name. Add the data source full name to toolTipList
*
* @return The list of data source name
*/
private List<String> getDataSourceArray() {
List<String> dsList = new ArrayList<>();
try {
Case currentCase = Case.getCurrentCaseThrows();
SleuthkitCase tskDb = currentCase.getSleuthkitCase();
List<DataSource> dataSources = tskDb.getDataSources();
Collections.sort(dataSources, (DataSource ds1, DataSource ds2) -> ds1.getName().compareTo(ds2.getName()));
for (DataSource ds : dataSources) {
String dsName = ds.getName();
File dataSourceFullName = new File(dsName);
String displayName = dataSourceFullName.getName();
dataSourceMap.put(ds.getId(), displayName);
toolTipList.add(dsName);
dsList.add(displayName);
}
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Unable to get current open case.", ex);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get data source info from database.", ex);
}
return dsList;
}
/**
* Get a set of data source object ids that are selected.
* @return A set of selected object ids.
*/
Set<Long> getDataSourcesSelected() {
Set<Long> dataSourceObjIdSet = new HashSet<>();
for (Long key : dataSourceMap.keySet()) {
String value = dataSourceMap.get(key);
for (String dataSource : this.dataSourceList.getSelectedValuesList()) {
if (value.equals(dataSource)) {
dataSourceObjIdSet.add(key);
}
}
}
return dataSourceObjIdSet;
}
/**
* Is dataSourceCheckBox selected
* @return true if the dataSoureCheckBox is selected
*/
boolean isSelected() {
return this.dataSourceCheckBox.isSelected();
}
/**
* Enable the dsList and dataSourceNoteLable if the dataSourceCheckBox is checked.
*/
final void setComponentsEnabled() {
boolean enabled = this.isSelected();
this.dataSourceList.setEnabled(enabled);
this.dataSourceNoteLabel.setEnabled(enabled);
}
/**
* 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")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
dataSourceList = new javax.swing.JList<>();
dataSourceCheckBox = new javax.swing.JCheckBox();
dataSourceNoteLabel = new javax.swing.JLabel();
setMinimumSize(new java.awt.Dimension(150, 150));
setPreferredSize(new java.awt.Dimension(100, 100));
dataSourceList.setModel(new javax.swing.AbstractListModel<String>() {
List<String> strings = getDataSourceArray();
public int getSize() { return strings.size(); }
public String getElementAt(int idx) { return strings.get(idx); }
});
dataSourceList.setEnabled(false);
dataSourceList.setMinimumSize(new java.awt.Dimension(0, 200));
jScrollPane1.setViewportView(dataSourceList);
org.openide.awt.Mnemonics.setLocalizedText(dataSourceCheckBox, org.openide.util.NbBundle.getMessage(DataSourcePanel.class, "DataSourcePanel.dataSourceCheckBox.text")); // NOI18N
dataSourceCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
dataSourceCheckBoxActionPerformed(evt);
}
});
dataSourceNoteLabel.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(dataSourceNoteLabel, org.openide.util.NbBundle.getMessage(DataSourcePanel.class, "DataSourcePanel.dataSourceNoteLabel.text")); // NOI18N
dataSourceNoteLabel.setEnabled(false);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(dataSourceCheckBox)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(dataSourceNoteLabel)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(dataSourceCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 95, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(dataSourceNoteLabel)
.addContainerGap())
);
dataSourceCheckBox.getAccessibleContext().setAccessibleName("");
}// </editor-fold>//GEN-END:initComponents
private void dataSourceCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataSourceCheckBoxActionPerformed
setComponentsEnabled();
firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
this.dataSourceList.setSelectedIndices(new int[0]);
}//GEN-LAST:event_dataSourceCheckBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox dataSourceCheckBox;
private javax.swing.JList<String> dataSourceList;
private javax.swing.JLabel dataSourceNoteLabel;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration//GEN-END:variables
}

View File

@ -92,12 +92,13 @@ class FileSearchPanel extends javax.swing.JPanel {
metadataFilters.add(new SizeSearchFilter());
metadataFilters.add(new MimeTypeFilter());
metadataFilters.add(new DateSearchFilter());
this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.metadata"), metadataFilters));
this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.knownStatus"), new KnownStatusSearchFilter()));
this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "HashSearchPanel.md5CheckBox.text"), new HashSearchFilter()));
this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "DataSourcePanel.dataSourceCheckBox.text"), new DataSourceFilter()));
for (FilterArea fa : this.filterAreas) {
fa.setMaximumSize(new Dimension(Integer.MAX_VALUE, fa.getMinimumSize().height));
fa.setAlignmentX(Component.LEFT_ALIGNMENT);