Merge branch 'develop' of https://github.com/sleuthkit/autopsy into develop

This commit is contained in:
Eugene Livis 2017-03-13 11:29:35 -04:00
commit 5f7e91b259
89 changed files with 4794 additions and 2937 deletions

View File

@ -26,6 +26,8 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.imagewriter.ImageWriterService;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitJNI;
@ -41,6 +43,7 @@ class AddImageTask implements Runnable {
private final String deviceId;
private final String imagePath;
private final String timeZone;
private final String imageWriterPath;
private final boolean ignoreFatOrphanFiles;
private final DataSourceProcessorProgressMonitor progressMonitor;
private final DataSourceProcessorCallback callback;
@ -74,15 +77,19 @@ class AddImageTask implements Runnable {
* java.util.TimeZone.getID.
* @param ignoreFatOrphanFiles Whether to parse orphans if the image has a
* FAT filesystem.
* @param imageWriterPath Path that a copy of the image should be written to.
* Use empty string to disable image writing
* @param progressMonitor Progress monitor to report progress during
* processing.
* @param callback Callback to call when processing is done.
*/
AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, String imageWriterPath,
DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
this.deviceId = deviceId;
this.imagePath = imagePath;
this.timeZone = timeZone;
this.ignoreFatOrphanFiles = ignoreFatOrphanFiles;
this.imageWriterPath = imageWriterPath;
this.callback = callback;
this.progressMonitor = progressMonitor;
tskAddImageProcessLock = new Object();
@ -101,7 +108,7 @@ class AddImageTask implements Runnable {
try {
currentCase.getSleuthkitCase().acquireExclusiveLock();
synchronized (tskAddImageProcessLock) {
tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles);
tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles, imageWriterPath);
}
Thread progressUpdateThread = new Thread(new ProgressUpdater(progressMonitor, tskAddImageProcess));
progressUpdateThread.start();
@ -201,6 +208,9 @@ class AddImageTask implements Runnable {
if (!verificationError.isEmpty()) {
errorMessages.add(verificationError);
}
if(! imageWriterPath.isEmpty()){
ImageWriterService.createImageWriter(imageId);
}
newDataSources.add(newImage);
} else {
String errorMessage = String.format("Error commiting adding image %s to the case database, no object id returned", imagePath); //NON-NLS

View File

@ -1,132 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="buttonGroup1">
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageWizardChooseDataSourceVisual.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</NonVisualComponents>
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[588, 328]"/>
</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" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="inputPanel" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Component id="inputPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="44" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="inputPanel">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="typeTabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="typeComboBox" min="-2" pref="292" max="-2" attributes="0"/>
<EmptySpace min="0" pref="119" max="32767" attributes="0"/>
</Group>
<Component id="typePanel" alignment="1" pref="548" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="typeTabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="typeComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="typePanel" min="-2" pref="225" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="typeTabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageWizardChooseDataSourceVisual.typeTabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="typePanel">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 65]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[521, 65]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="548" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="225" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
<Component class="javax.swing.JComboBox" name="typeComboBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -1,330 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2014 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.casemodule;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.ListCellRenderer;
import javax.swing.event.DocumentEvent;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datasourceprocessors.RawDSProcessor;
/**
* visual component for the first panel of add image wizard. Allows the user to
* choose the data source type and then select the data source
*
*/
final class AddImageWizardChooseDataSourceVisual extends JPanel {
static final Logger logger = Logger.getLogger(AddImageWizardChooseDataSourceVisual.class.getName());
private AddImageWizardChooseDataSourcePanel wizPanel;
private JPanel currentPanel;
private Map<String, DataSourceProcessor> datasourceProcessorsMap = new HashMap<>();
List<String> coreDSPTypes = new ArrayList<>();
/**
* Creates new form AddImageVisualPanel1
*
* @param wizPanel corresponding WizardPanel to handle logic of wizard step
*/
AddImageWizardChooseDataSourceVisual(AddImageWizardChooseDataSourcePanel wizPanel) {
initComponents();
this.wizPanel = wizPanel;
customInit();
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void customInit() {
typePanel.setLayout(new BorderLayout());
discoverDataSourceProcessors();
// set up the DSP type combobox
typeComboBox.removeAllItems();
Set<String> dspTypes = datasourceProcessorsMap.keySet();
// make a list of core DSPs
// ensure that the core DSPs are at the top and in a fixed order
coreDSPTypes.add(ImageDSProcessor.getType());
// Local disk processing is not allowed for multi-user cases
if (Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) {
coreDSPTypes.add(LocalDiskDSProcessor.getType());
} else {
// remove LocalDiskDSProcessor from list of DSPs
datasourceProcessorsMap.remove(LocalDiskDSProcessor.getType());
}
coreDSPTypes.add(LocalFilesDSProcessor.getType());
coreDSPTypes.add(RawDSProcessor.getType());
for (String dspType : coreDSPTypes) {
typeComboBox.addItem(dspType);
}
// now add any addtional DSPs that haven't already been added
for (String dspType : dspTypes) {
if (!coreDSPTypes.contains(dspType)) {
typeComboBox.addItem(dspType);
}
}
typeComboBox.setRenderer(new ComboboxSeparatorRenderer(typeComboBox.getRenderer()) {
@Override
protected boolean addSeparatorAfter(JList list, Object value, int index) {
return (index == coreDSPTypes.size() - 1);
}
});
//add actionlistner to listen for change
ActionListener cbActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dspSelectionChanged();
}
};
typeComboBox.addActionListener(cbActionListener);
typeComboBox.setSelectedIndex(0);
}
private void discoverDataSourceProcessors() {
for (DataSourceProcessor dsProcessor : Lookup.getDefault().lookupAll(DataSourceProcessor.class)) {
if (!datasourceProcessorsMap.containsKey(dsProcessor.getDataSourceType())) {
datasourceProcessorsMap.put(dsProcessor.getDataSourceType(), dsProcessor);
} else {
logger.log(Level.SEVERE, "discoverDataSourceProcessors(): A DataSourceProcessor already exists for type = {0}", dsProcessor.getDataSourceType()); //NON-NLS
}
}
}
private void dspSelectionChanged() {
// update the current panel to selection
currentPanel = getCurrentDSProcessor().getPanel();
updateCurrentPanel(currentPanel);
}
/**
* Changes the current panel to the given panel.
*
* @param panel instance of ImageTypePanel to change to
*/
@SuppressWarnings("deprecation")
private void updateCurrentPanel(JPanel panel) {
currentPanel = panel;
typePanel.removeAll();
typePanel.add(currentPanel, BorderLayout.CENTER);
typePanel.validate();
typePanel.repaint();
currentPanel.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString())) {
updateUI(null);
}
if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString())) {
wizPanel.moveFocusToNext();
}
}
});
updateUI(null);
}
/**
* Returns the currently selected DS Processor
*
* @return DataSourceProcessor the DataSourceProcessor corresponding to the
* data source type selected in the combobox
*/
protected DataSourceProcessor getCurrentDSProcessor() {
// get the type of the currently selected panel and then look up
// the correspodning DS Handler in the map
String dsType = (String) typeComboBox.getSelectedItem();
DataSourceProcessor dsProcessor = datasourceProcessorsMap.get(dsType);
return dsProcessor;
}
/**
* Returns the name of the this panel. This name will be shown on the left
* panel of the "Add Image" wizard panel.
*
* @return name the name of this panel
*/
@Override
public String getName() {
return NbBundle.getMessage(this.getClass(), "AddImageWizardChooseDataSourceVisual.getName.text");
}
/**
* 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.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
buttonGroup1 = new javax.swing.ButtonGroup();
jLabel2 = new javax.swing.JLabel();
inputPanel = new javax.swing.JPanel();
typeTabel = new javax.swing.JLabel();
typePanel = new javax.swing.JPanel();
typeComboBox = new javax.swing.JComboBox<String>();
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.jLabel2.text")); // NOI18N
setPreferredSize(new java.awt.Dimension(588, 328));
org.openide.awt.Mnemonics.setLocalizedText(typeTabel, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.typeTabel.text")); // NOI18N
typePanel.setMinimumSize(new java.awt.Dimension(0, 65));
typePanel.setPreferredSize(new java.awt.Dimension(521, 65));
javax.swing.GroupLayout typePanelLayout = new javax.swing.GroupLayout(typePanel);
typePanel.setLayout(typePanelLayout);
typePanelLayout.setHorizontalGroup(
typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 548, Short.MAX_VALUE)
);
typePanelLayout.setVerticalGroup(
typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 225, Short.MAX_VALUE)
);
javax.swing.GroupLayout inputPanelLayout = new javax.swing.GroupLayout(inputPanel);
inputPanel.setLayout(inputPanelLayout);
inputPanelLayout.setHorizontalGroup(
inputPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(inputPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(inputPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(inputPanelLayout.createSequentialGroup()
.addComponent(typeTabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(typeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 119, Short.MAX_VALUE))
.addComponent(typePanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 548, Short.MAX_VALUE))
.addContainerGap())
);
inputPanelLayout.setVerticalGroup(
inputPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(inputPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(inputPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(typeTabel)
.addComponent(typeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(typePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
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()
.addComponent(inputPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(6, 6, 6)
.addComponent(inputPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(44, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.ButtonGroup buttonGroup1;
private javax.swing.JPanel inputPanel;
private javax.swing.JLabel jLabel2;
private javax.swing.JComboBox<String> typeComboBox;
private javax.swing.JPanel typePanel;
private javax.swing.JLabel typeTabel;
// End of variables declaration//GEN-END:variables
/**
* The "listener" that updates the UI of this panel based on the changes of
* fields on this panel. This is also the method to check whether all the
* fields on this panel are correctly filled and decides whether to enable
* the "Next" button or not.
*
* @param e the document event
*/
public void updateUI(DocumentEvent e) {
// Enable the Next button if the current DSP panel is valid
this.wizPanel.enableNextButton(getCurrentDSProcessor().isPanelValid());
}
@SuppressWarnings("rawtypes")
public abstract class ComboboxSeparatorRenderer implements ListCellRenderer {
private ListCellRenderer delegate;
private JPanel separatorPanel = new JPanel(new BorderLayout());
private JSeparator separator = new JSeparator();
public ComboboxSeparatorRenderer(ListCellRenderer delegate) {
this.delegate = delegate;
}
@SuppressWarnings("unchecked")
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component comp = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (index != -1 && addSeparatorAfter(list, value, index)) {
separatorPanel.removeAll();
separatorPanel.add(comp, BorderLayout.CENTER);
separatorPanel.add(separator, BorderLayout.SOUTH);
return separatorPanel;
} else {
return comp;
}
}
protected abstract boolean addSeparatorAfter(JList list, Object value, int index);
}
}

View File

@ -39,23 +39,17 @@ import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescript
* The "Add Image" wizard panel1 handling the logic of selecting image file(s)
* to add to Case, and pick the time zone.
*/
class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel implements PropertyChangeListener {
class AddImageWizardDataSourceSettingsPanel extends ShortcutWizardDescriptorPanel implements PropertyChangeListener {
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private final AddImageWizardAddingProgressPanel progressPanel;
private AddImageWizardChooseDataSourceVisual component;
private AddImageWizardDataSourceSettingsVisual component;
private boolean isNextEnable = false;
private static final String PROP_LASTDATASOURCE_PATH = "LBL_LastDataSource_PATH"; //NON-NLS
private static final String PROP_LASTDATASOURCE_TYPE = "LBL_LastDataSource_TYPE"; //NON-NLS
// paths to any set hash lookup databases (can be null)
private String NSRLPath, knownBadPath;
AddImageWizardChooseDataSourcePanel(AddImageWizardAddingProgressPanel proPanel) {
this.progressPanel = proPanel;
AddImageWizardDataSourceSettingsPanel() {
}
@ -68,10 +62,10 @@ class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel
* @return component the UI component of this wizard panel
*/
@Override
public AddImageWizardChooseDataSourceVisual getComponent() {
public AddImageWizardDataSourceSettingsVisual getComponent() {
if (component == null) {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
component = new AddImageWizardChooseDataSourceVisual(this);
component = new AddImageWizardDataSourceSettingsVisual(this);
}
component.addPropertyChangeListener(this);
return component;
@ -87,8 +81,7 @@ class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel
public HelpCtx getHelp() {
// Show no Help button for this panel:
return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx(SampleWizardPanel1.class);
}
/**
@ -164,10 +157,6 @@ class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel
}
}
// You can use a settings object to keep track of state. Normally the
// settings object will be the WizardDescriptor, so you can use
// WizardDescriptor.getProperty & putProperty to store information entered
// by the user.
/**
* Provides the wizard panel with the current data--either the default data
* or already-modified settings, if the user used the previous and/or next
@ -178,26 +167,16 @@ class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel
*/
@Override
public void readSettings(WizardDescriptor settings) {
//reset settings if supports it
//getComponent().reset();
// Prepopulate the image directory from the properties file
try {
// Load hash database settings, enable or disable the checkbox
this.NSRLPath = null;
this.knownBadPath = null;
//JCheckBox lookupFilesCheckbox = component.getLookupFilesCheckbox();
//lookupFilesCheckbox.setSelected(false);
//lookupFilesCheckbox.setEnabled(this.NSRLPath != null || this.knownBadPath != null);
// If there is a process object in the settings, revert it and remove it from the settings
AddImageAction.CleanupTask cleanupTask = (AddImageAction.CleanupTask) settings.getProperty(AddImageAction.IMAGECLEANUPTASK_PROP);
if (cleanupTask != null) {
try {
cleanupTask.cleanup();
} catch (Exception ex) {
Logger logger = Logger.getLogger(AddImageWizardChooseDataSourcePanel.class.getName());
Logger logger = Logger.getLogger(AddImageWizardDataSourceSettingsPanel.class.getName());
logger.log(Level.WARNING, "Error cleaning up image task", ex); //NON-NLS
} finally {
cleanupTask.disable();
@ -205,7 +184,7 @@ class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel
}
} catch (Exception e) {
}
component.setDspSelection((String)settings.getProperty("SelectedDsp")); //NON-NLS magic string used SelectDataSourceProcessorPanel
}
/**

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[588, 328]"/>
</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">
<Component id="typePanel" alignment="0" pref="588" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="typePanel" alignment="0" pref="328" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="typePanel">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 65]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[521, 65]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="588" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="328" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,215 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.casemodule;
import java.awt.BorderLayout;
import java.awt.Component;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.ListCellRenderer;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* visual component for the first panel of add image wizard. Allows the user to
* choose the data source type and then select the data source
*
*/
final class AddImageWizardDataSourceSettingsVisual extends JPanel {
private static final Logger logger = Logger.getLogger(AddImageWizardDataSourceSettingsVisual.class.getName());
private final AddImageWizardDataSourceSettingsPanel wizPanel;
private JPanel currentPanel;
private final Map<String, DataSourceProcessor> datasourceProcessorsMap = new HashMap<>();
private String currentDsp;
/**
* Creates new form AddImageVisualPanel1
*
* @param wizPanel corresponding WizardPanel to handle logic of wizard step
*/
AddImageWizardDataSourceSettingsVisual(AddImageWizardDataSourceSettingsPanel wizPanel) {
initComponents();
this.wizPanel = wizPanel;
typePanel.setLayout(new BorderLayout());
discoverDataSourceProcessors();
currentDsp = ImageDSProcessor.getType(); //default value to the ImageDSProcessor
}
/**
* Populate the map of DataSourceProcessors which so they can be retrieved
* by name.
*/
private void discoverDataSourceProcessors() {
for (DataSourceProcessor dsProcessor : Lookup.getDefault().lookupAll(DataSourceProcessor.class)) {
if (!datasourceProcessorsMap.containsKey(dsProcessor.getDataSourceType())) {
datasourceProcessorsMap.put(dsProcessor.getDataSourceType(), dsProcessor);
} else {
logger.log(Level.SEVERE, "discoverDataSourceProcessors(): A DataSourceProcessor already exists for type = {0}", dsProcessor.getDataSourceType()); //NON-NLS
}
}
}
/**
* Set the current DataSourceProcessor and update the panel to reflect that
* selection.
*
* @param dsType - the name of the DataSourceProcessor you wish to have this
* panel display settings for.
*/
void setDspSelection(String dsType) {
currentDsp = dsType;
currentPanel = datasourceProcessorsMap.get(dsType).getPanel();
updateCurrentPanel(currentPanel);
}
/**
* Changes the current panel to the given panel.
*
* @param panel instance of ImageTypePanel to change to
*/
@SuppressWarnings("deprecation")
private void updateCurrentPanel(JPanel panel) {
currentPanel = panel;
typePanel.removeAll();
typePanel.add(currentPanel, BorderLayout.CENTER);
typePanel.validate();
typePanel.repaint();
currentPanel.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString())) {
wizPanel.enableNextButton(getCurrentDSProcessor().isPanelValid());
}
if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString())) {
wizPanel.moveFocusToNext();
}
}
});
this.wizPanel.enableNextButton(getCurrentDSProcessor().isPanelValid());
}
/**
* Returns the currently selected DS Processor
*
* @return DataSourceProcessor the DataSourceProcessor corresponding to the
* data source type selected in the combobox
*/
protected DataSourceProcessor getCurrentDSProcessor() {
// get the type of the currently selected panel and then look up
// the correspodning DS Handler in the map
DataSourceProcessor dsProcessor = datasourceProcessorsMap.get(currentDsp);
return dsProcessor;
}
/**
* Returns the name of the this panel. This name will be shown on the left
* panel of the "Add Image" wizard panel.
*
* @return name the name of this panel
*/
@Override
public String getName() {
return NbBundle.getMessage(this.getClass(), "AddImageWizardChooseDataSourceVisual.getName.text");
}
/**
* 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.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
typePanel = new javax.swing.JPanel();
setPreferredSize(new java.awt.Dimension(588, 328));
typePanel.setMinimumSize(new java.awt.Dimension(0, 65));
typePanel.setPreferredSize(new java.awt.Dimension(521, 65));
javax.swing.GroupLayout typePanelLayout = new javax.swing.GroupLayout(typePanel);
typePanel.setLayout(typePanelLayout);
typePanelLayout.setHorizontalGroup(
typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 588, Short.MAX_VALUE)
);
typePanelLayout.setVerticalGroup(
typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 328, Short.MAX_VALUE)
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(typePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 588, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(typePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel typePanel;
// End of variables declaration//GEN-END:variables
@SuppressWarnings("rawtypes")
public abstract class ComboboxSeparatorRenderer implements ListCellRenderer {
private final ListCellRenderer delegate;
private final JPanel separatorPanel = new JPanel(new BorderLayout());
private final JSeparator separator = new JSeparator();
public ComboboxSeparatorRenderer(ListCellRenderer delegate) {
this.delegate = delegate;
}
@SuppressWarnings("unchecked")
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component comp = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (index != -1 && addSeparatorAfter(list, value, index)) {
separatorPanel.removeAll();
separatorPanel.add(comp, BorderLayout.CENTER);
separatorPanel.add(separator, BorderLayout.SOUTH);
return separatorPanel;
} else {
return comp;
}
}
protected abstract boolean addSeparatorAfter(JList list, Object value, int index);
}
}

View File

@ -69,12 +69,12 @@ class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
private final AddImageAction addImageAction;
private final AddImageWizardAddingProgressPanel progressPanel;
private final AddImageWizardChooseDataSourcePanel dataSourcePanel;
private final AddImageWizardDataSourceSettingsPanel dataSourcePanel;
private DataSourceProcessor dsProcessor;
private boolean cancelled;
AddImageWizardIngestConfigPanel(AddImageWizardChooseDataSourcePanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
AddImageWizardIngestConfigPanel(AddImageWizardDataSourceSettingsPanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
this.addImageAction = action;
this.progressPanel = proPanel;
this.dataSourcePanel = dsPanel;

View File

@ -40,6 +40,7 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
private List<ShortcutWizardDescriptorPanel> panels;
private final AddImageAction action;
private int progressPanelIndex;
private int dsPanelIndex;
private final static String PROP_LASTPROFILE_NAME = "AIW_LASTPROFILE_NAME"; //NON-NLS
AddImageWizardIterator(AddImageAction action) {
@ -53,10 +54,11 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
private List<ShortcutWizardDescriptorPanel> getPanels() {
if (panels == null) {
panels = new ArrayList<>();
AddImageWizardSelectDspPanel dspSelection = new AddImageWizardSelectDspPanel();
panels.add(dspSelection);
AddImageWizardAddingProgressPanel progressPanel = new AddImageWizardAddingProgressPanel();
AddImageWizardChooseDataSourcePanel dsPanel = new AddImageWizardChooseDataSourcePanel(progressPanel);
AddImageWizardDataSourceSettingsPanel dsPanel = new AddImageWizardDataSourceSettingsPanel();
AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(dsPanel, action, progressPanel);
panels.add(dsPanel);
List<IngestProfiles.IngestProfile> profiles = IngestProfiles.getIngestProfiles();
@ -66,6 +68,7 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
panels.add(ingestConfigPanel);
panels.add(progressPanel);
progressPanelIndex = panels.indexOf(progressPanel); //Doing programatically because number of panels is variable
dsPanelIndex = panels.indexOf(dsPanel);
String[] steps = new String[panels.size()];
for (int i = 0; i < panels.size(); i++) {
Component c = panels.get(i).getComponent();
@ -157,9 +160,9 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
* @return boolean true if it has previous panel, false if not
*/
@Override
// disable the previous button on all panels
// disable the previous button on all panels except the data source panel
public boolean hasPrevious() {
return false;
return (index == dsPanelIndex); //Users should be able to back up to select a different DSP
}
/**

View File

@ -0,0 +1,98 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.casemodule;
import java.awt.Component;
import java.awt.Cursor;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.logging.Level;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
/**
* Create a wizard panel which contains a panel allowing the selection of the
* DataSourceProcessor
*/
final class AddImageWizardSelectDspPanel extends ShortcutWizardDescriptorPanel implements PropertyChangeListener {
@NbBundle.Messages("SelectDataSourceProcessorPanel.name.text=Select Type of Data")
private AddImageWizardSelectDspVisual component;
private static final String LAST_DSP_PROPERTIES_FILE = "LastDspUsed"; //NON-NLS
private static final String LAST_DSP_USED_KEY = "Last_Dsp_Used"; //NON-NLS
private static final Logger logger = Logger.getLogger(AddImageWizardSelectDspVisual.class.getName());
@Override
public Component getComponent() {
if (component == null) {
String lastDspUsed;
if (!(ModuleSettings.getConfigSetting(LAST_DSP_PROPERTIES_FILE, LAST_DSP_USED_KEY) == null)
&& !ModuleSettings.getConfigSetting(LAST_DSP_PROPERTIES_FILE, LAST_DSP_USED_KEY).isEmpty()) {
lastDspUsed = ModuleSettings.getConfigSetting(LAST_DSP_PROPERTIES_FILE, LAST_DSP_USED_KEY);
} else {
lastDspUsed = ImageDSProcessor.getType();
logger.log(Level.WARNING, "There was no properties file containing the last DataSourceProcessor used, Disk Image or VM will be selected as default selection"); //NON-NLS
}
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
component = new AddImageWizardSelectDspVisual(lastDspUsed);
component.setName(Bundle.SelectDataSourceProcessorPanel_name_text());
}
component.addPropertyChangeListener(this);
return component;
}
@Override
public HelpCtx getHelp() {
return HelpCtx.DEFAULT_HELP;
}
@Override
public void readSettings(WizardDescriptor data) {
}
@Override
public void storeSettings(WizardDescriptor data) {
String lastDspUsed = component.getSelectedDsp();
ModuleSettings.setConfigSetting(LAST_DSP_PROPERTIES_FILE, LAST_DSP_USED_KEY, lastDspUsed);
data.putProperty("SelectedDsp", lastDspUsed); //NON-NLS magic string necesary to AddImageWizardChooseDataSourcePanel
}
@Override
public boolean isValid() {
return true;
}
@Override
public void addChangeListener(ChangeListener cl) {
}
@Override
public void removeChangeListener(ChangeListener cl) {
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
}
}

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="buttonGroup1">
</Component>
</NonVisualComponents>
<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">
<EmptySpace min="0" pref="588" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="588" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="328" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="328" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.Box$Filler" name="filler1">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[6, 8]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[6, 8]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[6, 8]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.RigidArea"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,241 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.casemodule;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.swing.AbstractButton;
import javax.swing.Box.Filler;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.datasourceprocessors.RawDSProcessor;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Panel which displays the available DataSourceProcessors and allows selection of one
*/
final class AddImageWizardSelectDspVisual extends JPanel {
private static final Logger logger = Logger.getLogger(AddImageWizardSelectDspVisual.class.getName());
private String selectedDsp;
/**
* Creates new form SelectDataSourceProcessorPanel
*/
AddImageWizardSelectDspVisual(String lastDspUsed) {
initComponents();
selectedDsp = lastDspUsed;
createDataSourceProcessorButtons();
//add actionlistner to listen for change
}
/**
* Find the DSP which is currently selected and save it as the selected
* DataSourceProcessor.
*
*/
private void updateSelectedDsp() {
Enumeration<AbstractButton> buttonGroup = buttonGroup1.getElements();
while (buttonGroup.hasMoreElements()) {
AbstractButton dspButton = buttonGroup.nextElement();
if (dspButton.isSelected()) {
selectedDsp = dspButton.getName();
break;
}
}
}
/**
* Get the DataSourceProcessor which is currently selected in this panel
*
* @return selectedDsp the DataSourceProcessor which is selected in this panel
*/
String getSelectedDsp() {
return selectedDsp;
}
/**
* Create the a button for each DataSourceProcessor that should exist as an option.
*/
private void createDataSourceProcessorButtons() {
//Listener for button selection
ActionListener cbActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateSelectedDsp();
}
};
List<String> dspList = getListOfDsps();
//Set up the constraints for the panel layout
GridBagLayout gridBagLayout = new GridBagLayout();
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weighty = 0;
constraints.anchor = GridBagConstraints.LINE_START;
Dimension spacerBlockDimension = new Dimension(6, 4); // Space between left edge and button, Space between rows
for (String dspType : dspList) {
constraints.weightx = 1;
//Add a spacer
Filler spacer = new Filler(spacerBlockDimension, spacerBlockDimension, spacerBlockDimension);
gridBagLayout.setConstraints(spacer, constraints);
jPanel1.add(spacer);
constraints.gridx++;
constraints.gridy++;
//Add the button
JToggleButton dspButton = createDspButton(dspType);
dspButton.addActionListener(cbActionListener);
jPanel1.add(dspButton);
buttonGroup1.add(dspButton);
gridBagLayout.setConstraints(dspButton, constraints);
constraints.gridx++;
//Add the text area serving as a label to the right of the button
JTextArea myLabel = new JTextArea(dspType);
myLabel.setBackground(new Color(240, 240, 240));//matches background of panel
myLabel.setEditable(false);
myLabel.setWrapStyleWord(true);
myLabel.setLineWrap(true);
jPanel1.add(myLabel);
gridBagLayout.setConstraints(myLabel, constraints);
constraints.weightx = 0;
constraints.gridy++;
constraints.gridx = 0;
}
Component vertGlue = javax.swing.Box.createVerticalGlue();
jPanel1.add(vertGlue);
constraints.gridy++;
constraints.gridx = 0;
constraints.weighty = 1;
gridBagLayout.setConstraints(vertGlue, constraints);
jPanel1.setLayout(gridBagLayout);
}
/**
* Create a list of the DataSourceProcessors which should exist as options on this panel.
* The default Autopsy DataSourceProcessors will appear
* at the beggining of the list in the same order.
*
* @return dspList a list of DataSourceProcessors which can be chose in this panel
*/
private List<String> getListOfDsps() {
List<String> dspList = new ArrayList<>();
final Map<String, DataSourceProcessor> datasourceProcessorsMap = new HashMap<>();
for (DataSourceProcessor dsProcessor : Lookup.getDefault().lookupAll(DataSourceProcessor.class)) {
if (!datasourceProcessorsMap.containsKey(dsProcessor.getDataSourceType())) {
datasourceProcessorsMap.put(dsProcessor.getDataSourceType(), dsProcessor);
} else {
logger.log(Level.SEVERE, "discoverDataSourceProcessors(): A DataSourceProcessor already exists for type = {0}", dsProcessor.getDataSourceType()); //NON-NLS
}
}
dspList.add(ImageDSProcessor.getType());
if (Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) {
dspList.add(LocalDiskDSProcessor.getType());
} else {
// remove LocalDiskDSProcessor from list of DSPs
datasourceProcessorsMap.remove(LocalDiskDSProcessor.getType());
}
dspList.add(LocalFilesDSProcessor.getType());
dspList.add(RawDSProcessor.getType());
// now add any addtional DSPs that haven't already been added
for (String dspType : datasourceProcessorsMap.keySet()) {
if (!dspList.contains(dspType)) {
dspList.add(dspType);
}
}
return dspList;
}
/**
* Create a single button for a DataSourceProcessor
*
* @param dspType - the name of the DataSourceProcessor
*
* @return dspButton a JToggleButton for the specified dspType
*/
private JToggleButton createDspButton(String dspType) {
JToggleButton dspButton = new JToggleButton();
dspButton.setMaximumSize(new java.awt.Dimension(48, 48));
dspButton.setMinimumSize(new java.awt.Dimension(48, 48));
dspButton.setPreferredSize(new java.awt.Dimension(48, 48));
dspButton.setName(dspType);
dspButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/fileextmismatch/options-icon.png")));
dspButton.setSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/checkbox32.png")));
dspButton.setFocusable(false);
if (dspType.equals(selectedDsp)) {
dspButton.setSelected(true);
} else {
dspButton.setSelected(false);
}
return dspButton;
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
buttonGroup1 = new javax.swing.ButtonGroup();
jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(6, 8), new java.awt.Dimension(6, 8), new java.awt.Dimension(6, 8));
jPanel1.setLayout(new java.awt.GridBagLayout());
jPanel1.add(filler1, new java.awt.GridBagConstraints());
jScrollPane1.setViewportView(jPanel1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 588, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 588, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 328, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.ButtonGroup buttonGroup1;
private javax.swing.Box.Filler filler1;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration//GEN-END:variables
}

View File

@ -55,8 +55,6 @@ LocalFilesPanel.localFileChooser.approveButtonText=Select
LocalFilesPanel.localFileChooser.approveButtonToolTipText=
LocalFilesPanel.selectButton.actionCommand=Add
AddImageWizardAddingProgressVisual.statusLabel.text=Data source has been added to the local database. Files are being analyzed.
AddImageWizardChooseDataSourceVisual.typeTabel.text=Select data source type:
AddImageWizardChooseDataSourceVisual.jLabel2.text=jLabel2
AddImageWizardAddingProgressVisual.progressLabel.text=<progress>
AddImageWizardAddingProgressVisual.viewLogButton.text=View Log
AddImageWizardAddingProgressVisual.subTitle1Label.text=Processing data source and adding it to a local database. File analysis will start when this finishes.
@ -68,6 +66,10 @@ LocalDiskPanel.timeZoneLabel.text=Please select the input timezone:
LocalDiskPanel.noFatOrphansCheckbox.toolTipText=
LocalDiskPanel.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems
LocalDiskPanel.descLabel.text=(faster results, although some data will not be searched)
LocalDiskPanel.imageWriterDirError.text=Error - directory does not exist
LocalDiskPanel.imageWriterEmptyPathError.text=Error - enter path for VHD
LocalDiskPanel.imageWriterIsDirError.text=Error - VHD path is a directory
LocalDiskPanel.imageWriterFileExistsError.text=Error - VHD path already exists
MissingImageDialog.browseButton.text=Browse
MissingImageDialog.pathNameTextField.text=
AddImageWizardAddingProgressVisual.progressTextArea.border.title=Status
@ -224,6 +226,11 @@ LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default
IngestJobInfoPanel.jLabel1.text=Ingest Modules
IngestJobInfoPanel.jLabel2.text=Ingest Jobs
CaseInformationPanel.closeButton.text=Close
LocalDiskPanel.copyImageCheckbox.text=Make a VHD image of the drive while it is being analyzed
LocalDiskPanel.imageWriterErrorLabel.text=Error Label
LocalDiskPanel.jLabel1.text=Note that at least one ingest module must be run to create a complete copy
LocalDiskPanel.pathTextField.text=
LocalDiskPanel.browseButton.text=Browse
CasePropertiesPanel.updateCaseNameButton.text=Update Name
CasePropertiesPanel.caseNameTextField.text=
CasePropertiesPanel.caseDirLabel.text=Case Directory:

View File

@ -42,8 +42,6 @@ LocalFilesPanel.clearButton.toolTipText=\u73fe\u5728\u9078\u629e\u3055\u308c\u30
LocalFilesPanel.localFileChooser.approveButtonText=\u9078\u629e
LocalFilesPanel.selectButton.actionCommand=\u8ffd\u52a0
AddImageWizardAddingProgressVisual.statusLabel.text=\u30ed\u30fc\u30ab\u30eb\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u304c\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\u3002\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u4e2d\u3067\u3059\u3002
AddImageWizardChooseDataSourceVisual.typeTabel.text=\u8ffd\u52a0\u3059\u308b\u30bd\u30fc\u30b9\u30bf\u30a4\u30d7\u3092\u9078\u629e\uff1a
AddImageWizardChooseDataSourceVisual.jLabel2.text=jLabel2
AddImageWizardAddingProgressVisual.progressLabel.text=\uff1c\u30d7\u30ed\u30b0\u30ec\u30b9\uff1e
AddImageWizardAddingProgressVisual.viewLogButton.text=\u30ed\u30b0\u3092\u8868\u793a
AddImageWizardAddingProgressVisual.subTitle1Label.text=\u30ed\u30fc\u30ab\u30eb\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u60c5\u5831\u3092\u8ffd\u52a0\u4e2d\u3067\u3059\u3002\u3053\u3061\u3089\u304c\u5b8c\u4e86\u6b21\u7b2c\u3001\u30d5\u30a1\u30a4\u30eb\u89e3\u6790\u304c\u59cb\u307e\u308a\u307e\u3059\u3002

View File

@ -72,9 +72,9 @@ import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent;
import org.sleuthkit.autopsy.casemodule.services.Services;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CategoryNode;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.core.UserPreferencesException;
@ -673,7 +673,7 @@ public class Case {
* cannot be deleted if another node has it open.
*/
progressIndicator.start(Bundle.Case_progressMessage_acquiringLocks());
try (CoordinationService.Lock dirLock = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, metadata.getCaseDirectory())) {
try (CoordinationService.Lock dirLock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, metadata.getCaseDirectory())) {
assert (null != dirLock);
/*
@ -945,7 +945,7 @@ public class Case {
@Messages({"Case.creationException.couldNotAcquireNameLock=Failed to get lock on case name"})
private static CoordinationService.Lock acquireExclusiveCaseNameLock(String caseName) throws CaseActionException {
try {
Lock lock = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, caseName, NAME_LOCK_TIMOUT_HOURS, TimeUnit.HOURS);
Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, caseName, NAME_LOCK_TIMOUT_HOURS, TimeUnit.HOURS);
if (null == lock) {
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireNameLock());
}
@ -971,7 +971,7 @@ public class Case {
private static CoordinationService.Lock acquireExclusiveCaseResourcesLock(String caseName) throws CaseActionException {
try {
String resourcesNodeName = caseName + "_resources";
Lock lock = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, resourcesNodeName, RESOURCE_LOCK_TIMOUT_HOURS, TimeUnit.HOURS);
Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, resourcesNodeName, RESOURCE_LOCK_TIMOUT_HOURS, TimeUnit.HOURS);
if (null == lock) {
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
}
@ -1604,7 +1604,7 @@ public class Case {
"Case.progressIndicatorTitle.creatingCase=Creating Case",
"Case.progressIndicatorCancelButton.label=Cancel",
"Case.progressMessage.preparing=Preparing...",
"Case.progressMessage.acquiringLocks=Acquiring locks..."
"Case.progressMessage.acquiringLocks=<html>Preparing to open case resources.<br>This may take time if another user is upgrading the case.</html>"
})
private void open(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType) throws CaseActionException {
/*
@ -2337,7 +2337,7 @@ public class Case {
@Messages({"Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directory."})
private void acquireSharedCaseDirLock(String caseDir) throws CaseActionException {
try {
caseDirLock = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()).tryGetSharedLock(CoordinationService.CategoryNode.CASES, caseDir, SHARED_DIR_LOCK_TIMOUT_HOURS, TimeUnit.HOURS);
caseDirLock = CoordinationService.getInstance().tryGetSharedLock(CategoryNode.CASES, caseDir, SHARED_DIR_LOCK_TIMOUT_HOURS, TimeUnit.HOURS);
if (null == caseDirLock) {
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock());
}

View File

@ -455,13 +455,6 @@ public final class CaseMetadata {
this.caseDatabaseName = caseDirectoryPath.relativize(possibleAbsoluteCaseDbPath).toString();
}
/*
* Update the file to the current schema, if necessary.
*/
if (!schemaVersion.equals(CURRENT_SCHEMA_VERSION)) {
writeToFile();
}
} catch (ParserConfigurationException | SAXException | IOException ex) {
throw new CaseMetadataException(String.format("Error reading from case metadata file %s", metadataFilePath), ex);
}

View File

@ -115,7 +115,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
protected void done() {
try {
get();
} catch (InterruptedException | ExecutionException ex) {
} catch (InterruptedException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(
@ -124,6 +124,15 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
StartupWindowProvider.getInstance().open();
} catch (ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(),
ex.getCause().getMessage(), //get the message of the wrapped exception
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
StartupWindowProvider.getInstance().open();
}
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}

View File

@ -185,7 +185,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
* @param callback Callback to call when processing is done.
*/
public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addImageTask = new AddImageTask(deviceId, imagePath, timeZone, ignoreFatOrphanFiles, progressMonitor, callback);
addImageTask = new AddImageTask(deviceId, imagePath, timeZone, ignoreFatOrphanFiles, "", progressMonitor, callback);
new Thread(addImageTask).start();
}

View File

@ -54,6 +54,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData
private String deviceId;
private String drivePath;
private String timeZone;
private String imageWriterPath = "";
private boolean ignoreFatOrphanFiles;
private boolean setDataSourceOptionsCalled;
@ -137,8 +138,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData
drivePath = configPanel.getContentPaths();
timeZone = configPanel.getTimeZone();
ignoreFatOrphanFiles = configPanel.getNoFatOrphans();
if(configPanel.getImageWriterEnabled()){
imageWriterPath = configPanel.getImageWriterPath();
}
}
addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, progressMonitor, callback);
addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterPath, progressMonitor, callback);
new Thread(addDiskTask).start();
}
@ -164,7 +168,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData
* @param callback Callback to call when processing is done.
*/
public void run(String deviceId, String drivePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, progressMonitor, callback);
addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterPath, progressMonitor, callback);
new Thread(addDiskTask).start();
}

View File

@ -3,10 +3,10 @@
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 65]"/>
<Dimension value="[0, 420]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[485, 65]"/>
<Dimension value="[485, 410]"/>
</Property>
</Properties>
<AuxValues>
@ -26,21 +26,38 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="diskLabel" min="-2" max="-2" attributes="0"/>
<Component id="diskComboBox" min="-2" pref="345" max="-2" attributes="0"/>
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="timeZoneComboBox" min="-2" pref="215" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="pathTextField" alignment="1" min="-2" pref="362" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="diskLabel" min="-2" max="-2" attributes="0"/>
<Component id="diskComboBox" min="-2" pref="345" max="-2" attributes="0"/>
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="timeZoneComboBox" min="-2" pref="215" max="-2" attributes="0"/>
</Group>
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
<Component id="copyImageCheckbox" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="21" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" min="-2" pref="423" max="-2" attributes="0"/>
<Component id="imageWriterErrorLabel" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace min="0" pref="102" max="32767" attributes="0"/>
<EmptySpace min="0" pref="29" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -61,7 +78,18 @@
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="copyImageCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="pathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="imageWriterErrorLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="170" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -165,5 +193,58 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="copyImageCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalDiskPanel.copyImageCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="copyImageCheckboxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="imageWriterErrorLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="imageWriterErrorLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalDiskPanel.imageWriterErrorLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalDiskPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="pathTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalDiskPanel.pathTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="pathTextFieldKeyReleased"/>
<EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="pathTextFieldKeyTyped"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="browseButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalDiskPanel.browseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View File

@ -22,6 +22,8 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
@ -30,6 +32,7 @@ import java.util.TimeZone;
import java.util.concurrent.CancellationException;
import java.util.logging.Level;
import javax.swing.ComboBoxModel;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
@ -57,6 +60,7 @@ final class LocalDiskPanel extends JPanel {
private List<LocalDisk> disks;
private LocalDiskModel model;
private boolean enableNext = false;
private final JFileChooser fc = new JFileChooser();
/**
* Creates new form LocalDiskPanel
@ -88,6 +92,10 @@ final class LocalDiskPanel extends JPanel {
errorLabel.setVisible(false);
errorLabel.setText("");
diskComboBox.setEnabled(false);
imageWriterErrorLabel.setOpaque(true);
imageWriterErrorLabel.setText("");
pathTextField.setEnabled(copyImageCheckbox.isSelected());
browseButton.setEnabled(copyImageCheckbox.isSelected());
}
/**
@ -106,9 +114,14 @@ final class LocalDiskPanel extends JPanel {
timeZoneComboBox = new javax.swing.JComboBox<>();
noFatOrphansCheckbox = new javax.swing.JCheckBox();
descLabel = new javax.swing.JLabel();
copyImageCheckbox = new javax.swing.JCheckBox();
imageWriterErrorLabel = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
pathTextField = new javax.swing.JTextField();
browseButton = new javax.swing.JButton();
setMinimumSize(new java.awt.Dimension(0, 65));
setPreferredSize(new java.awt.Dimension(485, 65));
setMinimumSize(new java.awt.Dimension(0, 420));
setPreferredSize(new java.awt.Dimension(485, 410));
diskLabel.setFont(diskLabel.getFont().deriveFont(diskLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(diskLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.diskLabel.text")); // NOI18N
@ -132,24 +145,66 @@ final class LocalDiskPanel extends JPanel {
descLabel.setFont(descLabel.getFont().deriveFont(descLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.descLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(copyImageCheckbox, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.copyImageCheckbox.text")); // NOI18N
copyImageCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
copyImageCheckboxActionPerformed(evt);
}
});
imageWriterErrorLabel.setFont(imageWriterErrorLabel.getFont().deriveFont(imageWriterErrorLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
imageWriterErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(imageWriterErrorLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.imageWriterErrorLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.jLabel1.text")); // NOI18N
pathTextField.setText(org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.pathTextField.text")); // NOI18N
pathTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
pathTextFieldKeyReleased(evt);
}
public void keyTyped(java.awt.event.KeyEvent evt) {
pathTextFieldKeyTyped(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.browseButton.text")); // NOI18N
browseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(diskLabel)
.addComponent(diskComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(errorLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(timeZoneLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(noFatOrphansCheckbox)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 362, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(diskLabel)
.addComponent(diskComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(errorLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(timeZoneLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(noFatOrphansCheckbox)
.addComponent(copyImageCheckbox)
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
.addComponent(descLabel))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(browseButton))
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
.addComponent(descLabel)))
.addGap(0, 102, Short.MAX_VALUE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 423, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(imageWriterErrorLabel))))
.addGap(0, 29, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -167,19 +222,76 @@ final class LocalDiskPanel extends JPanel {
.addComponent(noFatOrphansCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(descLabel)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(copyImageCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(browseButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(imageWriterErrorLabel)
.addContainerGap(170, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
String oldText = pathTextField.getText();
// set the current directory of the FileChooser if the ImagePath Field is valid
File currentFile = new File(oldText);
if ((currentFile.getParentFile() != null) && (currentFile.getParentFile().exists())) {
fc.setCurrentDirectory(currentFile.getParentFile());
}
int retval = fc.showOpenDialog(this);
if (retval == JFileChooser.APPROVE_OPTION) {
String path = fc.getSelectedFile().getPath();
pathTextField.setText(path);
}
fireUpdateEvent();
}//GEN-LAST:event_browseButtonActionPerformed
private void copyImageCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyImageCheckboxActionPerformed
pathTextField.setEnabled(copyImageCheckbox.isSelected());
browseButton.setEnabled(copyImageCheckbox.isSelected());
fireUpdateEvent();
}//GEN-LAST:event_copyImageCheckboxActionPerformed
private void pathTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_pathTextFieldKeyTyped
}//GEN-LAST:event_pathTextFieldKeyTyped
private void pathTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_pathTextFieldKeyReleased
fireUpdateEvent();
}//GEN-LAST:event_pathTextFieldKeyReleased
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton browseButton;
private javax.swing.JCheckBox copyImageCheckbox;
private javax.swing.JLabel descLabel;
private javax.swing.JComboBox<LocalDisk> diskComboBox;
private javax.swing.JLabel diskLabel;
private javax.swing.JLabel errorLabel;
private javax.swing.JLabel imageWriterErrorLabel;
private javax.swing.JLabel jLabel1;
private javax.swing.JCheckBox noFatOrphansCheckbox;
private javax.swing.JTextField pathTextField;
private javax.swing.JComboBox<String> timeZoneComboBox;
private javax.swing.JLabel timeZoneLabel;
// End of variables declaration//GEN-END:variables
private void fireUpdateEvent(){
try {
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
} catch (Exception e) {
logger.log(Level.SEVERE, "LocalDiskPanel listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "LocalDiskPanel.moduleErr"),
NbBundle.getMessage(this.getClass(), "LocalDiskPanel.moduleErr.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
}
/**
* Return the currently selected disk path.
*
@ -215,13 +327,68 @@ final class LocalDiskPanel extends JPanel {
return noFatOrphansCheckbox.isSelected();
}
private static String getDefaultImageWriterFolder(){
return Paths.get(Case.getCurrentCase().getModuleDirectory(), "Image Writer").toString();
}
private void setPotentialImageWriterPath(LocalDisk disk){
File subDirectory = Paths.get(getDefaultImageWriterFolder()).toFile();
if (!subDirectory.exists()) {
subDirectory.mkdirs();
}
String path = disk.getName().replaceAll("[:]", "");
path += " " + System.currentTimeMillis();
path += ".vhd";
pathTextField.setText(Paths.get(getDefaultImageWriterFolder(), path).toString());
}
private boolean imageWriterPathIsValid(){
if(pathTextField.getText().isEmpty()){
imageWriterErrorLabel.setText(NbBundle.getMessage(this.getClass(), "LocalDiskPanel.imageWriterEmptyPathError.text"));
return false;
}
File f = new File(pathTextField.getText());
if(((f.getParentFile() != null) && (! f.getParentFile().exists())) ||
(f.getParentFile() == null)) {
imageWriterErrorLabel.setText(NbBundle.getMessage(this.getClass(), "LocalDiskPanel.imageWriterDirError.text"));
return false;
}
if(f.isDirectory()){
imageWriterErrorLabel.setText(NbBundle.getMessage(this.getClass(), "LocalDiskPanel.imageWriterIsDirError.text"));
return false;
}
if(f.exists()){
imageWriterErrorLabel.setText(NbBundle.getMessage(this.getClass(), "LocalDiskPanel.imageWriterFileExistsError.text"));
return false;
}
imageWriterErrorLabel.setText("");
return true;
}
boolean getImageWriterEnabled(){
return copyImageCheckbox.isSelected();
}
String getImageWriterPath(){
return pathTextField.getText();
}
/**
* Should we enable the wizard's next button? Always return true because we
* control the possible selections.
* Should we enable the wizard's next button? We control all the possible
* selections except for Image Writer.
*
* @return true
* @return true if panel is valid
*/
public boolean validatePanel() {
if(copyImageCheckbox.isSelected() &&
! imageWriterPathIsValid()){
return false;
}
return enableNext;
}
@ -318,15 +485,8 @@ final class LocalDiskPanel extends JPanel {
if (ready) {
selected = (LocalDisk) anItem;
enableNext = true;
try {
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
} catch (Exception e) {
logger.log(Level.SEVERE, "LocalDiskPanel listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "LocalDiskPanel.moduleErr"),
NbBundle.getMessage(this.getClass(), "LocalDiskPanel.moduleErr.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
setPotentialImageWriterPath((LocalDisk) selected);
fireUpdateEvent();
}
}

View File

@ -19,9 +19,13 @@
package org.sleuthkit.autopsy.coordinationservice;
import java.io.IOException;
import java.util.HashMap;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
@ -34,25 +38,28 @@ import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.core.UserPreferences;
/**
* A coordination service for maintaining configuration information and
* providing distributed synchronization using a shared hierarchical namespace
* of nodes.
*
* TODO (JIRA 2205): Simple refactoring for general use.
*/
@ThreadSafe
public final class CoordinationService {
private static CuratorFramework curator = null;
private static final Map<String, CoordinationService> rootNodesToServices = new HashMap<>();
private static final int SESSION_TIMEOUT_MILLISECONDS = 300000;
private static final int CONNECTION_TIMEOUT_MILLISECONDS = 300000;
private static final int ZOOKEEPER_SESSION_TIMEOUT_MILLIS = 3000;
private static final int ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS = 15000;
private static final int PORT_OFFSET = 1000; // When run in Solr, ZooKeeper defaults to Solr port + 1000
private final Map<String, String> categoryNodeToPath = new HashMap<>();
private static final String DEFAULT_NAMESPACE_ROOT = "autopsy";
@GuardedBy("CoordinationService.class")
private static CoordinationService instance;
private final CuratorFramework curator;
@GuardedBy("categoryNodeToPath")
private final Map<String, String> categoryNodeToPath;
/**
* Determines if ZooKeeper is accessible with the current settings. Closes
@ -86,44 +93,31 @@ public final class CoordinationService {
}
/**
* Gets a coordination service for a specific namespace.
* Gets the coordination service for maintaining configuration information
* and providing distributed synchronization using a shared hierarchical
* namespace of nodes.
*
* @param rootNode The name of the root node that defines the namespace.
* @return The corrdination service.
*
* @return The coordination service.
*
* @throws CoordinationServiceException If an instance of the coordination
* service cannot be created.
* @throws CoordinationServiceException
*/
public static synchronized CoordinationService getServiceForNamespace(String rootNode) throws CoordinationServiceException {
/*
* Connect to ZooKeeper via Curator.
*/
if (null == curator) {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET;
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort;
curator = CuratorFrameworkFactory.newClient(connectString, SESSION_TIMEOUT_MILLISECONDS, CONNECTION_TIMEOUT_MILLISECONDS, retryPolicy);
curator.start();
}
/*
* Get or create a coordination service for the namespace defined by the
* specified root node.
*/
if (rootNodesToServices.containsKey(rootNode)) {
return rootNodesToServices.get(rootNode);
} else {
CoordinationService service;
public synchronized static CoordinationService getInstance() throws CoordinationServiceException {
if (null == instance) {
String rootNode;
Collection<? extends CoordinationServiceNamespace> providers = Lookup.getDefault().lookupAll(CoordinationServiceNamespace.class);
Iterator<? extends CoordinationServiceNamespace> it = providers.iterator();
if (it.hasNext()) {
rootNode = it.next().getNamespaceRoot();
} else {
rootNode = DEFAULT_NAMESPACE_ROOT;
}
try {
service = new CoordinationService(rootNode);
instance = new CoordinationService(rootNode);
} catch (IOException | InterruptedException | KeeperException | CoordinationServiceException ex) {
curator = null;
throw new CoordinationServiceException("Failed to create coordination service", ex);
}
rootNodesToServices.put(rootNode, service);
return service;
}
return instance;
}
/**
@ -141,11 +135,23 @@ public final class CoordinationService {
throw new CoordinationServiceException("Unable to access ZooKeeper");
}
/*
* Connect to ZooKeeper via Curator.
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET;
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort;
curator = CuratorFrameworkFactory.newClient(connectString, SESSION_TIMEOUT_MILLISECONDS, CONNECTION_TIMEOUT_MILLISECONDS, retryPolicy);
curator.start();
/*
* Create the top-level root and category nodes.
*/
String rootNode = rootNodeName;
if (!rootNode.startsWith("/")) {
rootNode = "/" + rootNode;
}
categoryNodeToPath = new ConcurrentHashMap<>();
for (CategoryNode node : CategoryNode.values()) {
String nodePath = rootNode + "/" + node.getDisplayName();
try {
@ -422,8 +428,7 @@ public final class CoordinationService {
CASES("cases"),
MANIFESTS("manifests"),
CONFIG("config"),
RESOURCE("resource");
CONFIG("config");
private final String displayName;

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2016-2017 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,15 +19,18 @@
package org.sleuthkit.autopsy.coordinationservice;
/**
* Root node for Autopsy coordination service namespace.
* An interface that allows the root node of the coordination service namespace
* for the application to be specified at runtime. An application built on the
* Autopsy platform should provide at most one implementation of this interface
* (additional implementations are ignored).
*/
public final class CoordinationServiceNamespace {
private static final String ROOT = "autopsy";
public interface CoordinationServiceNamespace {
public static String getRoot() {
return ROOT;
}
/**
* Gets the name of the root node of the coordination service namespace.
*
* @return The name of the root node.
*/
public String getNamespaceRoot();
private CoordinationServiceNamespace() {
}
}

View File

@ -163,12 +163,22 @@ public final class ExecUtil {
process.waitFor(timeOut, units);
if (process.isAlive() && terminator.shouldTerminateProcess()) {
killProcess(process);
try {
process.waitFor(); //waiting to help ensure process is shutdown before calling interrupt() or returning
} catch (InterruptedException exx) {
Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, String.format("Wait for process termination following killProcess was interrupted for command %s", processBuilder.command().get(0)));
}
}
} while (process.isAlive());
} catch (InterruptedException ex) {
if (process.isAlive()) {
killProcess(process);
}
try {
process.waitFor(); //waiting to help ensure process is shutdown before calling interrupt() or returning
} catch (InterruptedException exx) {
Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, String.format("Wait for process termination following killProcess was interrupted for command %s", processBuilder.command().get(0)));
}
Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, "Thread interrupted while running {0}", processBuilder.command().get(0)); // NON-NLS
Thread.currentThread().interrupt();
}

View File

@ -51,7 +51,9 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
* Uses lazy Content.Keys
*/
AbstractContentChildren() {
super(true); // use lazy behavior
/*This was turned off because we were getting out of memory errors when the
filter nodes were hiding nodes. Turning this off seemed to help */
super(false); //don't use lazy behavior
}
@Override

View File

@ -61,7 +61,7 @@ public class ArtifactStringContent implements StringContent {
* @return The HTML representation of the artifact as a string.
*/
@Messages({
"ArtifactStringContent.attrsTableHeader.attribute=Attribute",
"ArtifactStringContent.attrsTableHeader.type=Type",
"ArtifactStringContent.attrsTableHeader.value=Value",
"ArtifactStringContent.attrsTableHeader.sources=Source(s)",
"ArtifactStringContent.failedToGetSourcePath.message=Failed to get source file path from case database",
@ -90,15 +90,15 @@ public class ArtifactStringContent implements StringContent {
*/
buffer.append("<table border='1'>"); //NON-NLS
buffer.append("<tr>"); //NON-NLS
buffer.append("<td>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_attribute());
buffer.append("</td>"); //NON-NLS
buffer.append("<td>"); //NON-NLS
buffer.append("<td><b>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_type());
buffer.append("</b></td>"); //NON-NLS
buffer.append("<td><b>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_value());
buffer.append("</td>"); //NON-NLS
buffer.append("<td>"); //NON-NLS
buffer.append("</b></td>"); //NON-NLS
buffer.append("<td><b>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_sources());
buffer.append("</td>"); //NON-NLS
buffer.append("</b></td>"); //NON-NLS
buffer.append("</tr>\n"); //NON-NLS
try {
Content content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID());

View File

@ -171,8 +171,6 @@ KeywordHits.createNodeForKey.chgTime.desc=Change Time
KeywordHits.createNodeForKey.chgTime.name=ChangeTime
KeywordHits.createNodeForKey.accessTime.name=AccessTime
KeywordHits.createNodeForKey.modTime.name=ModifiedTime
KnownFileFilterNode.selectionContext.dataSources=Data Sources
KnownFileFilterNode.selectionContext.views=Views
LayoutFileNode.propertyType.parts=Parts
LayoutFileNode.createSheet.name.name=Name
LayoutFileNode.createSheet.name.displayName=Name
@ -221,8 +219,6 @@ 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

View File

@ -1,181 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2014 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.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 known files.
*
* Filters known files IF the option to Filter Known files for the given
* SelectionContext is set. Otherwise, does nothing.
*
* @author jwallace
*/
public class KnownFileFilterNode extends FilterNode {
private static boolean filterFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
private static boolean filterFromViews = UserPreferences.hideKnownFilesInViewsTree();
static {
UserPreferences.addChangeListener(new PreferenceChangeListener() {
@Override
public void preferenceChange(PreferenceChangeEvent evt) {
switch (evt.getKey()) {
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
filterFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
break;
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
filterFromViews = UserPreferences.hideKnownFilesInViewsTree();
break;
}
}
});
}
public enum SelectionContext {
DATA_SOURCES(NbBundle.getMessage(KnownFileFilterNode.class, "KnownFileFilterNode.selectionContext.dataSources")),
VIEWS(NbBundle.getMessage(KnownFileFilterNode.class, "KnownFileFilterNode.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 KnownFileFilterNode from the given Node. Note that the Node
* should be from the directory tree.
*
* @param arg
* @param context
*/
public KnownFileFilterNode(Node arg, SelectionContext context) {
super(arg, new KnownFileFilterChildren(arg, context));
}
private KnownFileFilterNode(Node arg, boolean filter) {
super(arg, new KnownFileFilterChildren(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 KnownFileFilterNode.
*
* Filters out children Nodes that represent known files. Otherwise, returns
* the original node wrapped in another instance of the KnownFileFilterNode.
*
* @author jwallace
*/
private static class KnownFileFilterChildren extends FilterNode.Children {
/**
* True if this KnownFileFilterChildren should filter out known files.
*/
private boolean filter;
/**
* Constructor used when the context has already been determined.
*
* @param arg
* @param filter
*/
private KnownFileFilterChildren(Node arg, boolean filter) {
super(arg);
this.filter = filter;
}
/**
* Constructor used when the context has not been determined.
*
* @param arg
* @param context
*/
private KnownFileFilterChildren(Node arg, KnownFileFilterNode.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 known files
AbstractFile file = arg.getLookup().lookup(AbstractFile.class);
if (file != null && (file.getKnown() == TskData.FileKnown.KNOWN)) {
return new Node[]{};
}
}
return new Node[]{new KnownFileFilterNode(arg, filter)};
}
}
}

View File

@ -1,180 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2014 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.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_SRCS_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)};
}
}
}

View File

@ -10,3 +10,4 @@ RawDSInputPanel.jBreakFileUpLabel.text=Break image up into:
RawDSInputPanel.jNoBreakupRadioButton.text=Do not break up
RawDSInputPanel.j2GBBreakupRadioButton.text=2GB chunks
RawDSInputPanel.timeZoneLabel.text=Please select the input timezone:

View File

@ -1,46 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 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.directorytree;
import org.openide.explorer.ExplorerManager;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
/**
* This class is used for the creation of all the children for the
* DataResultFilterNode that created in the DataResultFilterNode.java.
*
*/
class DataResultFilterChildren extends FilterNode.Children {
ExplorerManager sourceEm;
/**
* the constructor
*/
public DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
super(arg);
this.sourceEm = sourceEm;
}
@Override
protected Node copyNode(Node arg0) {
return new DataResultFilterNode(arg0, sourceEm);
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,6 +23,8 @@ import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.openide.explorer.ExplorerManager;
@ -33,6 +35,7 @@ import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
@ -58,6 +61,7 @@ import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.VirtualDirectory;
@ -67,11 +71,37 @@ import org.sleuthkit.datamodel.VirtualDirectory;
*/
public class DataResultFilterNode extends FilterNode {
private ExplorerManager sourceEm;
private static boolean filterKnownFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
private static boolean filterKnownFromViews = UserPreferences.hideKnownFilesInViewsTree();
private static boolean filterSlackFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
private static boolean filterSlackFromViews = UserPreferences.hideSlackFilesInViewsTree();
private final DisplayableItemNodeVisitor<List<Action>> getActionsDIV;
static {
UserPreferences.addChangeListener(new PreferenceChangeListener() {
@Override
public void preferenceChange(PreferenceChangeEvent evt) {
switch (evt.getKey()) {
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
filterKnownFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
break;
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
filterKnownFromViews = UserPreferences.hideKnownFilesInViewsTree();
break;
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
filterSlackFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
break;
case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE:
filterSlackFromViews = UserPreferences.hideSlackFilesInViewsTree();
break;
}
}
});
}
private final DisplayableItemNodeVisitor<AbstractAction> getPreferredActionsDIV;
static private final DisplayableItemNodeVisitor<List<Action>> getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor();
private final DisplayableItemNodeVisitor<AbstractAction> getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor();
private final ExplorerManager sourceEm;
/**
*
@ -81,8 +111,17 @@ public class DataResultFilterNode extends FilterNode {
public DataResultFilterNode(Node node, ExplorerManager em) {
super(node, new DataResultFilterChildren(node, em));
this.sourceEm = em;
getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor();
getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor();
}
/**
*
* @param node Root node to be passed to DataResult viewers
* @param em ExplorerManager for component that is creating the node
*/
private DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack) {
super(node, new DataResultFilterChildren(node, em, filterKnown, filterSlack));
this.sourceEm = em;
}
/**
@ -150,6 +189,64 @@ public class DataResultFilterNode extends FilterNode {
return propertySets;
}
/**
* This class is used for the creation of all the children for the
* DataResultFilterNode that created in the DataResultFilterNode.java.
*
*/
private static class DataResultFilterChildren extends FilterNode.Children {
private final ExplorerManager sourceEm;
private boolean filterKnown;
private boolean filterSlack;
/**
* the constructor
*/
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
super(arg);
switch (SelectionContext.getSelectionContext(arg)) {
case DATA_SOURCES:
filterSlack = filterSlackFromDataSources;
filterKnown = filterKnownFromDataSources;
break;
case VIEWS:
filterSlack = filterSlackFromViews;
filterKnown = filterKnownFromViews;
break;
default:
filterSlack = false;
filterKnown = false;
break;
}
this.sourceEm = sourceEm;
}
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm, boolean filterKnown, boolean filterSlack) {
super(arg);
this.filterKnown = filterKnown;
this.filterSlack = filterSlack;
this.sourceEm = sourceEm;
}
@Override
protected Node[] createNodes(Node key) {
AbstractFile file = key.getLookup().lookup(AbstractFile.class);
if (file != null) {
if (filterKnown && (file.getKnown() == TskData.FileKnown.KNOWN)) {
// Filter out child nodes that represent known files
return new Node[]{};
}
if (filterSlack && file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
// Filter out child nodes that represent slack files
return new Node[]{};
}
}
return new Node[]{new DataResultFilterNode(key, sourceEm, filterKnown, filterSlack)};
}
}
/**
* Uses the default nodes actions per node, adds some custom ones and
* returns them per visited node type
@ -239,7 +336,7 @@ public class DataResultFilterNode extends FilterNode {
@Override
public List<Action> visit(FileTypesNode fileTypes) {
return defaultVisit(fileTypes);
return defaultVisit(fileTypes);
}

View File

@ -65,12 +65,10 @@ import org.sleuthkit.autopsy.datamodel.EmptyNode;
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType;
import org.sleuthkit.autopsy.datamodel.KeywordHits;
import org.sleuthkit.autopsy.datamodel.KnownFileFilterNode;
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;
@ -656,22 +654,17 @@ 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
//Special case for when File Type Identification has not yet been run and
//there are no mime types to populate Files by Mime Type Tree
if (FileTypesByMimeType.isEmptyMimeTypeNode(originNode)) {
//Special case for when File Type Identification has not yet been run and
//there are no mime types to populate Files by Mime Type Tree
EmptyNode emptyNode = new EmptyNode(Bundle.DirectoryTreeTopComponent_emptyMimeNode_text());
Node emptyDrfn = new DataResultFilterNode(emptyNode, DirectoryTreeTopComponent.this.em);
Node emptyKffn = new KnownFileFilterNode(emptyDrfn, KnownFileFilterNode.getSelectionContext(emptyNode));
Node emptySffn = new SlackFileFilterNode(emptyKffn, SlackFileFilterNode.getSelectionContext(originNode));
dataResult.setNode(new TableFilterNode(emptySffn, true, "This Node Is Empty")); //NON-NLS
dataResult.setNode(new TableFilterNode(emptyNode, true, "This Node Is Empty")); //NON-NLS
} else if (originNode instanceof DisplayableItemNode) {
dataResult.setNode(new TableFilterNode(sffn, true, ((DisplayableItemNode) originNode).getItemType()));
dataResult.setNode(new TableFilterNode(drfn, true, ((DisplayableItemNode) originNode).getItemType()));
} else {
dataResult.setNode(new TableFilterNode(sffn, true));
dataResult.setNode(new TableFilterNode(drfn, true));
}
String displayName = "";

View File

@ -0,0 +1,71 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.directorytree;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import static org.sleuthkit.autopsy.directorytree.Bundle.*;
@NbBundle.Messages({"SelectionContext.dataSources=Data Sources",
"SelectionContext.views=Views"})
enum SelectionContext {
DATA_SOURCES(SelectionContext_dataSources()),
VIEWS(SelectionContext_views()),
OTHER(""); // Subnode of another node.
private final String displayName;
private 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;
}
/**
* 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());
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,8 @@
# To change this license header, choose License Headers in Project Properties.
# To change this template file, choose Tools | Templates
# and open the template in the editor.
ImageWriterService.serviceName=Image Writer
ImageWriterService.waitingForVHDs=Waiting for VHD(s) to complete
ImageWriterService.shouldWait=Wait for VHD(s) in progress to complete?
ImageWriterService.localDisk=Local disk image copy

View File

@ -0,0 +1,288 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 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.imagewriter;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import org.netbeans.api.progress.ProgressHandle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent;
import org.sleuthkit.datamodel.SleuthkitJNI;
import org.sleuthkit.datamodel.TskCoreException;
/**
* The ImageWriter class is used to complete VHD copies created from local disks
* after the ingest process completes. The AddImageTask for this data source must have included
* a non-empty imageWriterPath parameter to enable Image Writer.
*
* Most of the cancellation/cleanup is handled through ImageWriterService
*/
class ImageWriter implements PropertyChangeListener{
private final Logger logger = Logger.getLogger(ImageWriter.class.getName());
private final Long dataSourceId;
private Long imageHandle = null;
private Future<?> finishTask = null;
private ProgressHandle progressHandle = null;
private ScheduledFuture<?> progressUpdateTask = null;
private boolean isCancelled = false;
private boolean isStarted = false;
private final Object currentTasksLock = new Object(); // Get this lock before accessing imageHandle, finishTask, progressHandle, progressUpdateTask,
// isCancelled, isStarted, or isFinished
private ScheduledThreadPoolExecutor periodicTasksExecutor = null;
private final boolean doUI;
/**
* Create the Image Writer object.
* After creation, startListeners() should be called.
* @param dataSourceId
*/
ImageWriter(Long dataSourceId){
this.dataSourceId = dataSourceId;
doUI = RuntimeProperties.runningWithGUI();
}
/**
* Add this ImageWriter object as a listener to the necessary events
*/
void subscribeToEvents(){
IngestManager.getInstance().addIngestJobEventListener(this);
}
/**
* Deregister this object from the events. This is ok to call multiple times.
*/
void unsubscribeFromEvents(){
IngestManager.getInstance().removeIngestJobEventListener(this);
}
/**
* Handle the events:
* DATA_SOURCE_ANALYSIS_COMPLETED - start the finish image process and clean up after it is complete
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt instanceof DataSourceAnalysisCompletedEvent){
DataSourceAnalysisCompletedEvent event = (DataSourceAnalysisCompletedEvent)evt;
if(event.getDataSource() != null){
long imageId = event.getDataSource().getId();
String name = event.getDataSource().getName();
// Check that the event corresponds to this datasource
if(imageId != dataSourceId){
return;
}
new Thread(() -> {
startFinishImage(name);
}).start();
} else {
logger.log(Level.SEVERE, "DataSourceAnalysisCompletedEvent did not contain a dataSource object"); //NON-NLS
}
}
}
private void startFinishImage(String dataSourceName){
synchronized(currentTasksLock){
if(isCancelled){
return;
}
// If we've already started the finish process for this datasource, return.
// Multiple DataSourceAnalysisCompletedEvent events can come from
// the same image if more ingest modules are run later
if(isStarted){
return;
}
Image image;
try{
image = Case.getCurrentCase().getSleuthkitCase().getImageById(dataSourceId);
imageHandle = image.getImageHandle();
} catch (IllegalStateException ex){
// This exception means that getCurrentCase() failed because no case was open.
// This can happen when the user closes the case while ingest is ongoing - canceling
// ingest fires off the DataSourceAnalysisCompletedEvent while the case is in the
// process of closing.
logger.log(Level.WARNING, String.format("Case closed before ImageWriter could start the finishing process for %s",
dataSourceName));
return;
} catch (TskCoreException ex){
logger.log(Level.SEVERE, "Error loading image", ex);
return;
}
logger.log(Level.INFO, String.format("Finishing VHD image for %s",
dataSourceName)); //NON-NLS
if(doUI){
periodicTasksExecutor = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("image-writer-progress-update-%d").build()); //NON-NLS
progressHandle = ProgressHandle.createHandle("Image writer - " + dataSourceName);
progressHandle.start(100);
progressUpdateTask = periodicTasksExecutor.scheduleAtFixedRate(
new ProgressUpdateTask(progressHandle, imageHandle), 0, 250, TimeUnit.MILLISECONDS);
}
// The added complexity here with the Future is because we absolutely need to make sure
// the call to finishImageWriter returns before allowing the TSK data structures to be freed
// during case close.
finishTask = Executors.newSingleThreadExecutor().submit(() -> {
try{
SleuthkitJNI.finishImageWriter(imageHandle);
} catch (TskCoreException ex){
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
}
});
// Setting this means that finishTask and all the UI updaters are initialized (if running UI)
isStarted = true;
}
// Wait for finishImageWriter to complete
try{
// The call to get() can happen multiple times if the user closes the case, which is ok
finishTask.get();
} catch (InterruptedException | ExecutionException ex){
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
}
synchronized(currentTasksLock){
if(doUI){
// Some of these may be called twice if the user closes the case
progressUpdateTask.cancel(true);
progressHandle.finish();
periodicTasksExecutor.shutdown();
}
}
logger.log(Level.INFO, String.format("Finished writing VHD image for %s", dataSourceName)); //NON-NLS
}
/**
* If a task hasn't been started yet, set the cancel flag so it can no longer
* start.
* This is intended to be used in case close so a job doesn't suddenly start
* up during cleanup.
*/
void cancelIfNotStarted(){
synchronized(currentTasksLock){
if(! isStarted){
isCancelled = true;
}
}
}
/**
* Check if the finishTask process is running.
* @return true if the finish task is still going on, false if it is finished or
* never started
*/
boolean jobIsInProgress(){
synchronized(currentTasksLock){
return((isStarted) && (! finishTask.isDone()));
}
}
/**
* Cancels a single job.
* Does not wait for the job to complete. Safe to call with Image Writer in any state.
*/
void cancelJob(){
synchronized(currentTasksLock){
// All of the following is redundant but safe to call on a complete job
isCancelled = true;
if(isStarted){
SleuthkitJNI.cancelFinishImage(imageHandle);
// Stop the progress bar update task.
// The thread from startFinishImage will also stop it
// once the task completes, but we don't have a guarantee on
// when that happens.
// Since we've stopped the update task, we'll stop the associated progress
// bar now, too.
if(doUI){
progressUpdateTask.cancel(true);
progressHandle.finish();
}
}
}
}
/**
* Blocks while all finishImage tasks complete.
* Also makes sure the progressUpdateTask is canceled.
*/
void waitForJobToFinish(){
synchronized(currentTasksLock){
// Wait for the finish task to end
if(isStarted){
try{
finishTask.get();
} catch (InterruptedException | ExecutionException ex){
Logger.getLogger(ImageWriter.class.getName()).log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
}
if(doUI){
progressUpdateTask.cancel(true);
}
}
}
}
/**
* Task to query the Sleuthkit processing to get the percentage done.
*/
private final class ProgressUpdateTask implements Runnable {
final long imageHandle;
final ProgressHandle progressHandle;
ProgressUpdateTask(ProgressHandle progressHandle, long imageHandle){
this.imageHandle = imageHandle;
this.progressHandle = progressHandle;
}
@Override
public void run() {
try {
int progress = SleuthkitJNI.getFinishImageProgress(imageHandle);
progressHandle.progress(progress);
} catch (Exception ex) {
logger.log(Level.SEVERE, "Unexpected exception in ProgressUpdateTask", ex); //NON-NLS
}
}
}
}

View File

@ -0,0 +1,123 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 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.imagewriter;
import java.util.HashSet;
import java.util.Set;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.framework.AutopsyService;
@ServiceProviders(value = {@ServiceProvider(service = AutopsyService.class)})
/**
* Creates and handles closing of ImageWriter objects.
* Currently, ImageWriter is only enabled for local disks, and local disks can
* not be processed in multi user mode. If ImageWriter is ever enabled for multi user
* cases this code will need to be revised.
*/
public class ImageWriterService implements AutopsyService {
private static final Set<ImageWriter> imageWriters = new HashSet<>(); // Contains all Image Writer objects
private static final Object imageWritersLock = new Object(); // Get this lock before accessing currentImageWriters
/**
* Create an image writer object for the given data source ID.
* @param imageId ID for the image
*/
public static void createImageWriter(Long imageId){
// ImageWriter objects are created during the addImageTask. They can not arrive while
// we're closing case resources so we don't need to worry about one showing up while
// doing our close/cleanup.
synchronized(imageWritersLock){
ImageWriter writer = new ImageWriter(imageId);
writer.subscribeToEvents();
imageWriters.add(writer);
}
}
@Override
public String getServiceName() {
return NbBundle.getMessage(this.getClass(), "ImageWriterService.serviceName");
}
@Override
public void closeCaseResources(CaseContext context) throws AutopsyServiceException {
context.getProgressIndicator().progress(NbBundle.getMessage(this.getClass(), "ImageWriterService.waitingForVHDs"));
synchronized(imageWritersLock){
// If any of our ImageWriter objects haven't started the finish task, set the cancel flag
// to make sure they don't start now. The reason they haven't started is that
// ingest was not complete, and the user already confirmed that they want to exit
// even though ingest is not complete so we will take that to mean that they
// also don't want to wait for Image Writer.
for(ImageWriter writer: imageWriters){
writer.cancelIfNotStarted();
}
// Test whether any finishImage tasks are in progress
boolean jobsAreInProgress = false;
for(ImageWriter writer: imageWriters){
if(writer.jobIsInProgress()){
jobsAreInProgress = true;
break;
}
}
if(jobsAreInProgress){
// If jobs are in progress, ask the user if they want to wait for them to complete
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
NbBundle.getMessage(this.getClass(), "ImageWriterService.shouldWait"),
NbBundle.getMessage(this.getClass(), "ImageWriterService.localDisk"),
NotifyDescriptor.YES_NO_OPTION,
NotifyDescriptor.WARNING_MESSAGE);
descriptor.setValue(NotifyDescriptor.NO_OPTION);
Object response = DialogDisplayer.getDefault().notify(descriptor);
if(response == DialogDescriptor.NO_OPTION){
// Cancel all the jobs
for(ImageWriter writer: imageWriters){
writer.cancelJob();
}
}
// Wait for all finishImage jobs to complete. If the jobs got cancelled
// this will be very fast.
for(ImageWriter writer: imageWriters){
writer.waitForJobToFinish();
}
}
// Stop listening for events
for(ImageWriter writer: imageWriters){
writer.unsubscribeFromEvents();
}
// Clear out the list of Image Writers
imageWriters.clear();
}
}
}

View File

@ -25,6 +25,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
@ -413,19 +414,34 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
FilesSetDefsPanel fileIngestFilterPanel;
fileIngestFilterPanel = new FilesSetDefsPanel(FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS);
fileIngestFilterPanel.load();
//save the filters that exist before any are created
final ArrayList<String> oldFilterList = new ArrayList<>(Arrays.asList(getComboBoxContents()));
dialog.addApplyButtonListener(
(ActionEvent e) -> {
fileIngestFilterPanel.store();
ArrayList<FilesSet> newFilterList = new ArrayList<>();
try {
newFilterList.addAll(FilesSetsManager.getInstance().getCustomFileIngestFilters().values());
} catch (FilesSetsManager.FilesSetsManagerException ex) {
logger.log(Level.SEVERE, "Failed to get user created file ingest filters, only default available for selection", ex); //NON-NLS
}
for (FilesSet filter : newFilterList) { //getting one of the recently created filters
if (!oldFilterList.contains(filter.getName())) {
//set newly created filter to selected filter
settings.setFileIngestFilter(filter);
break;
}
}
fileIngestFilterComboBox.setModel(new DefaultComboBoxModel<>(getComboBoxContents()));
//set the selected filter after the comboBox Contents were updated to include it
fileIngestFilterComboBox.setSelectedItem(settings.getFileIngestFilter().getName());
dialog.close();
}
);
dialog.display(fileIngestFilterPanel);
//return to saved selection in case they cancel out of filter creation
fileIngestFilterComboBox.setSelectedItem(settings.getFileIngestFilter().getName());
} else if (evt.getActionCommand().equals("comboBoxChanged")) {
try {
Map<String, FilesSet> fileIngestFilters = FilesSetsManager.getInstance()
.getCustomFileIngestFilters();

View File

@ -47,6 +47,7 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
private final static int INDEX_OF_SETTINGS_PANEL = 2;
private ProfileSettingsPanel profilePanel;
private final static int INDEX_OF_PROFILE_PANEL = 1;
private int indexOfPreviousTab;
/**
* This panel implements a property change listener that listens to ingest
* job events so it can disable the buttons on the panel if ingest is
@ -58,6 +59,7 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
public IngestOptionsPanel() {
initComponents();
customizeComponents();
indexOfPreviousTab = tabbedPane.getSelectedIndex();
}
private void customizeComponents() {
@ -78,15 +80,16 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
@Override
public void stateChanged(ChangeEvent e) {
if (e.getSource() instanceof JTabbedPane) {
//because we can have two filterPanels open at the same time
//we need to save the settings when we change tabs otherwise
//they could be overwritten with out of date
if (tabbedPane.getSelectedIndex() == INDEX_OF_FILTER_PANEL) {
filterPanel.load();
}
else {
filterPanel.saveSettings();
}
//If we are switching to a filter panel we should load
//load the filter panel to ensure it is up to date
//incase a filter was addded through the Profile->new->create new filter manner
if (tabbedPane.getSelectedIndex() == INDEX_OF_FILTER_PANEL && tabbedPane.getSelectedIndex() != indexOfPreviousTab) {
filterPanel.load();
}
//save the contents of whichever Tab we just switched from
saveTabByIndex(indexOfPreviousTab);
//save the index of the current tab for the next time we switch
indexOfPreviousTab = tabbedPane.getSelectedIndex();
}
}
});
@ -160,8 +163,30 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
*/
@Override
public void saveSettings() {
filterPanel.store();
settingsPanel.store();
saveTabByIndex(tabbedPane.getSelectedIndex());
}
/**
* Save the panel which is in the tab corresponding to the specified index.
*
* @param index - the index of the tab you wish to save the contents of
*/
private void saveTabByIndex(int index) {
//Because we can create filters in two seperate windows here we need
//to be careful not to save an out of date list over the current list
switch (index) {
case (INDEX_OF_FILTER_PANEL):
filterPanel.saveSettings();
break;
case (INDEX_OF_PROFILE_PANEL):
profilePanel.saveSettings();
break;
case (INDEX_OF_SETTINGS_PANEL):
settingsPanel.saveSettings();
break;
default:
//don't save anything if it wasn't a tab index that should exist
}
}
/**

View File

@ -27,22 +27,28 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="profileListLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="profileListPane" alignment="1" min="-2" pref="339" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="newProfileButton" linkSize="5" min="-2" pref="107" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="editProfileButton" linkSize="5" min="-2" pref="107" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deleteProfileButton" linkSize="5" min="-2" pref="109" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="newProfileButton" linkSize="5" min="-2" pref="107" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="editProfileButton" linkSize="5" min="-2" pref="107" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deleteProfileButton" linkSize="5" min="-2" pref="109" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane2" linkSize="6" alignment="1" min="-2" pref="346" max="-2" attributes="0"/>
</Group>
<Component id="profileListLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="profileListPane" linkSize="6" min="-2" pref="346" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
<Component id="jSeparator2" min="-2" pref="2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
@ -60,7 +66,7 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<EmptySpace min="0" pref="69" max="32767" attributes="0"/>
</Group>
<Component id="profileDescPane" alignment="1" max="32767" attributes="0"/>
<Component id="selectedModulesPane" alignment="1" max="32767" attributes="0"/>
@ -97,13 +103,10 @@
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="profileListLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="profileDescLabel" alignment="3" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="profileDescLabel" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="profileDescPane" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
@ -115,9 +118,16 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="selectedModulesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="selectedModulesPane" max="32767" attributes="0"/>
<Component id="selectedModulesPane" pref="171" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="jScrollPane2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="profileListLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="profileListPane" pref="346" max="32767" attributes="0"/>
<EmptySpace min="9" pref="9" max="-2" attributes="0"/>
</Group>
<Component id="profileListPane" pref="415" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
@ -128,7 +138,7 @@
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jSeparator2" alignment="1" max="32767" attributes="0"/>
<Component id="jSeparator2" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
@ -355,5 +365,41 @@
<Property name="orientation" type="int" value="1"/>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="jScrollPane2" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
</Properties>
<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.JTextArea" name="infoTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="f0" green="f0" red="f0" type="rgb"/>
</Property>
<Property name="columns" type="int" value="20"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="infoTextArea" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="3"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="ProfileSettingsPanel.infoTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="wrapStyleWord" type="boolean" value="true"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -18,6 +18,7 @@
*/
package org.sleuthkit.autopsy.ingest;
import java.awt.Cursor;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.DefaultListModel;
@ -44,12 +45,15 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
"ProfileSettingsPanel.deleteProfileButton.text=Delete Profile",
"ProfileSettingsPanel.messages.filterLoadFailed=Failed to load file ingest filter",
"# {0} - profile name",
"ProfileSettingsPanel.doFileSetsDialog.duplicateProfile.text=Profile with name {0} already exists."
"ProfileSettingsPanel.doFileSetsDialog.duplicateProfile.text=Profile with name {0} already exists.",
"ProfileSettingsPanel.infoTextArea.text=An Ingest Profile runs a preconfigured set of ingest modules"
+ " on some or all of the files in a data source. Create a profile if you frequently run the same set of modules on a subset of the files."
})
private final DefaultListModel<IngestProfile> profilesListModel;
private Map<String, IngestProfile> profiles;
private ProfilePanel panel;
private boolean canBeEnabled; //if something can be enabled ingest is not running
/**
* Creates new form ProfileOptionsPanel
@ -60,8 +64,8 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
this.profileList.setModel(profilesListModel);
this.profileList.addListSelectionListener(new ProfileSettingsPanel.ProfileListSelectionListener());
ingestWarningLabel.setVisible(false);
editProfileButton.setEnabled(false);
deleteProfileButton.setEnabled(false);
canBeEnabled = !IngestManager.getInstance().isIngestRunning();
refreshButtons();
}
/**
@ -91,6 +95,8 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
selectedModulesLabel = new javax.swing.JLabel();
ingestWarningLabel = new javax.swing.JLabel();
jSeparator2 = new javax.swing.JSeparator();
jScrollPane2 = new javax.swing.JScrollPane();
infoTextArea = new javax.swing.JTextArea();
setBorder(javax.swing.BorderFactory.createEtchedBorder());
setPreferredSize(new java.awt.Dimension(800, 488));
@ -175,6 +181,18 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
jSeparator2.setOrientation(javax.swing.SwingConstants.VERTICAL);
jScrollPane2.setFont(jScrollPane2.getFont().deriveFont(jScrollPane2.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
infoTextArea.setEditable(false);
infoTextArea.setBackground(new java.awt.Color(240, 240, 240));
infoTextArea.setColumns(20);
infoTextArea.setFont(infoTextArea.getFont().deriveFont(infoTextArea.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
infoTextArea.setLineWrap(true);
infoTextArea.setRows(3);
infoTextArea.setText(org.openide.util.NbBundle.getMessage(ProfileSettingsPanel.class, "ProfileSettingsPanel.infoTextArea.text")); // NOI18N
infoTextArea.setWrapStyleWord(true);
jScrollPane2.setViewportView(infoTextArea);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@ -182,17 +200,21 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(profileListLabel)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(newProfileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editProfileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteProfileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jScrollPane2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 346, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(profileListLabel))
.addGap(6, 6, 6))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(profileListPane, javax.swing.GroupLayout.PREFERRED_SIZE, 339, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(newProfileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editProfileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteProfileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(6, 6, 6)))
.addComponent(profileListPane, javax.swing.GroupLayout.PREFERRED_SIZE, 346, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)))
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
@ -208,7 +230,7 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(ingestWarningLabel)
.addGap(0, 0, Short.MAX_VALUE))
.addGap(0, 69, Short.MAX_VALUE))
.addComponent(profileDescPane, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(selectedModulesPane, javax.swing.GroupLayout.Alignment.TRAILING)))
.addGroup(layout.createSequentialGroup()
@ -229,18 +251,18 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteProfileButton, editProfileButton, newProfileButton});
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jScrollPane2, profileListPane});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(profileListLabel)
.addComponent(profileDescLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(profileDescLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(profileDescPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -251,8 +273,14 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(selectedModulesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(selectedModulesPane))
.addComponent(profileListPane, javax.swing.GroupLayout.DEFAULT_SIZE, 415, Short.MAX_VALUE))
.addComponent(selectedModulesPane, javax.swing.GroupLayout.DEFAULT_SIZE, 171, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(profileListLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(profileListPane, javax.swing.GroupLayout.DEFAULT_SIZE, 346, Short.MAX_VALUE)
.addGap(9, 9, 9)))
.addGap(4, 4, 4)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newProfileButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
@ -260,7 +288,7 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
.addComponent(deleteProfileButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(ingestWarningLabel))
.addContainerGap())
.addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.TRAILING)))
.addComponent(jSeparator2)))
);
}// </editor-fold>//GEN-END:initComponents
@ -288,10 +316,9 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
* @param isEnabled
*/
void enableButtons(boolean isEnabled) {
newProfileButton.setEnabled(isEnabled);
editProfileButton.setEnabled(isEnabled);
deleteProfileButton.setEnabled(isEnabled);
ingestWarningLabel.setVisible(!isEnabled);
canBeEnabled = isEnabled; //update value of canBeEnabled to be used by refresh
refreshButtons();
ingestWarningLabel.setVisible(!canBeEnabled);
}
/**
@ -307,23 +334,20 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
this.filterNameText.setText("");
this.selectedModulesArea.setText("");
}
refreshEditDeleteButtons();
refreshButtons();
}
/**
* When Ingest is not running this will changed enabled status of the edit
* and delete buttons to reflect their current availability.
* When Ingest is not running this will change the enabled status of the
* edit and delete buttons to reflect their current availability.
*/
private void refreshEditDeleteButtons() {
if (newProfileButton.isEnabled()) {
if (profilesListModel.isEmpty()) {
editProfileButton.setEnabled(false);
deleteProfileButton.setEnabled(false);
} else {
editProfileButton.setEnabled(true);
deleteProfileButton.setEnabled(true);
}
}
private void refreshButtons() {
IngestProfile selectedProfile = ProfileSettingsPanel.this.profileList.getSelectedValue();
boolean profileIsSelected = (selectedProfile != null);
newProfileButton.setEnabled(canBeEnabled);
editProfileButton.setEnabled(canBeEnabled && profileIsSelected);
deleteProfileButton.setEnabled(canBeEnabled && profileIsSelected);
}
@ -340,6 +364,8 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
*/
private void doProfileDialog(IngestProfile selectedProfile) {
// Create a files set defintion panel.
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
//start wait cursor for ingest job settings construction
if (selectedProfile != null) {
// Editing an existing set definition.
panel = new ProfilePanel(selectedProfile);
@ -347,6 +373,8 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
// Creating a new set definition.
panel = new ProfilePanel();
}
//end wait Cursor for ingest job settings construction
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
// Do a dialog box with the profilePanel till the user enters a name or chooses cancel
int option = JOptionPane.OK_OPTION;
do {
@ -366,7 +394,6 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
panel.saveSettings();
load();
}
}
@Override
@ -392,7 +419,7 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
if (currentIndex < 0 || currentIndex >= profilesListModel.getSize()) {
currentIndex = 0;
}
refreshEditDeleteButtons();
refreshButtons();
this.profileList.setSelectedIndex(currentIndex);
}
@ -406,11 +433,10 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
// Get the selected interesting files set and populate the set
// components.
IngestProfile selectedProfile = ProfileSettingsPanel.this.profileList.getSelectedValue();
refreshButtons();
if (selectedProfile != null) {
profileDescArea.setText(selectedProfile.getDescription());
filterNameText.setText(selectedProfile.getFileIngestFilter());
editProfileButton.setEnabled(true);
deleteProfileButton.setEnabled(true);
try {
Map<String, FilesSet> fileIngestFilters = FilesSetsManager.getInstance().getCustomFileIngestFilters();
for (FilesSet fSet : FilesSetsManager.getStandardFileIngestFilters()) {
@ -424,10 +450,6 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
for (String moduleName : IngestJobSettings.getEnabledModules(selectedProfile.getName())) {
selectedModulesArea.append(moduleName + "\n");
}
} else {
editProfileButton.setEnabled(false);
deleteProfileButton.setEnabled(false);
}
}
}
@ -439,7 +461,9 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
private javax.swing.JScrollPane filterDescPane;
private javax.swing.JLabel filterNameLabel;
private javax.swing.JLabel filterNameText;
private javax.swing.JTextArea infoTextArea;
private javax.swing.JLabel ingestWarningLabel;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JSeparator jSeparator2;
private javax.swing.JButton newProfileButton;
private javax.swing.JTextArea profileDescArea;

View File

@ -19,39 +19,40 @@
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="mimeTypeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="mimeTypeTextField" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="addSigButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="editSigButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="deleteSigButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="1" min="-2" pref="393" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
<Component id="setNameLabel" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="1" groupAlignment="0" attributes="0">
<Group type="103" alignment="0" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="addSigButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="setNameTextField" min="-2" pref="144" max="-2" attributes="0"/>
<Component id="editSigButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="deleteSigButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="1" min="-2" pref="393" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
<Component id="setNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="setNameTextField" min="-2" pref="144" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<Component id="postHitCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="71" pref="71" max="-2" attributes="0"/>
<Component id="mimeFormatLabel" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -65,7 +66,9 @@
<Component id="mimeTypeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="mimeTypeTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="mimeFormatLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Component id="jScrollPane1" min="-2" pref="83" max="-2" attributes="0"/>
@ -207,5 +210,12 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="mimeFormatLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties" key="AddFileTypePanel.mimeFormatLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -29,6 +29,7 @@ import org.openide.util.NbBundle.Messages;
import static org.sleuthkit.autopsy.modules.filetypeid.AddFileTypePanel.EVENT.SIG_LIST_CHANGED;
import org.sleuthkit.autopsy.modules.filetypeid.AddFileTypeSignatureDialog.BUTTON_PRESSED;
import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature;
@Messages("AddFileTypePanel.mimeFormatLabel.text=Form of MIME type should be: media type/media subtype")
/**
* Panel for adding or editing file types.
@ -87,7 +88,10 @@ class AddFileTypePanel extends javax.swing.JPanel {
@Messages({"AddMimeTypePanel.emptySigList.message=Must have at least one signature.",
"AddMimeTypePanel.emptySigList.title=Invalid Signature List",
"AddMimeTypePanel.emptySetName.message=Interesting files set name is required if alert is requested.",
"AddMimeTypePanel.emptySetName.title=Missing Interesting Files Set Name"})
"AddMimeTypePanel.emptySetName.title=Missing Interesting Files Set Name",
"AddFileTypePanel.nonStandardMIMEType.message="
+ "Files of this MIME type will not appear under the Views, File Types, By MIME Type tree because it is not in the format of: media type/media subtype",
"AddFileTypePanel.nonStandardMIMEType.title=Non-standard MIME Type"})
FileType getFileType() {
String typeName = mimeTypeTextField.getText();
if (typeName.isEmpty()) {
@ -97,7 +101,12 @@ class AddFileTypePanel extends javax.swing.JPanel {
JOptionPane.ERROR_MESSAGE);
return null;
}
if (typeName.split("/").length != 2) {
JOptionPane.showMessageDialog(null,
NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "AddFileTypePanel.nonStandardMIMEType.message"),
NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "AddFileTypePanel.nonStandardMIMEType.title"),
JOptionPane.WARNING_MESSAGE);
}
if (this.signaturesListModel.isEmpty()) {
JOptionPane.showMessageDialog(null,
Bundle.AddMimeTypePanel_emptySigList_message(),
@ -180,6 +189,7 @@ class AddFileTypePanel extends javax.swing.JPanel {
postHitCheckBox = new javax.swing.JCheckBox();
setNameLabel = new javax.swing.JLabel();
setNameTextField = new javax.swing.JTextField();
mimeFormatLabel = new javax.swing.JLabel();
editSigButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/edit16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(editSigButton, org.openide.util.NbBundle.getMessage(AddFileTypePanel.class, "AddFileTypePanel.editSigButton.text")); // NOI18N
@ -233,6 +243,8 @@ class AddFileTypePanel extends javax.swing.JPanel {
setNameTextField.setText(org.openide.util.NbBundle.getMessage(AddFileTypePanel.class, "AddFileTypePanel.setNameTextField.text")); // NOI18N
setNameTextField.setEnabled(postHitCheckBox.isSelected());
org.openide.awt.Mnemonics.setLocalizedText(mimeFormatLabel, org.openide.util.NbBundle.getMessage(AddFileTypePanel.class, "AddFileTypePanel.mimeFormatLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@ -244,27 +256,28 @@ class AddFileTypePanel extends javax.swing.JPanel {
.addComponent(mimeTypeLabel)
.addGap(18, 18, 18)
.addComponent(mimeTypeTextField))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(addSigButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(editSigButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(deleteSigButton))
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 393, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(28, 28, 28)
.addComponent(setNameLabel)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(addSigButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(setNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 144, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addComponent(editSigButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(deleteSigButton))
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 393, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(28, 28, 28)
.addComponent(setNameLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(setNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 144, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1)
.addComponent(postHitCheckBox))
.addGap(0, 0, Short.MAX_VALUE)))
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGap(71, 71, 71)
.addComponent(mimeFormatLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
@ -274,7 +287,9 @@ class AddFileTypePanel extends javax.swing.JPanel {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(mimeTypeLabel)
.addComponent(mimeTypeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(3, 3, 3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(mimeFormatLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)
.addGap(1, 1, 1)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE)
@ -338,6 +353,7 @@ class AddFileTypePanel extends javax.swing.JPanel {
private javax.swing.JButton editSigButton;
private javax.swing.JLabel jLabel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel mimeFormatLabel;
private javax.swing.JLabel mimeTypeLabel;
private javax.swing.JTextField mimeTypeTextField;
private javax.swing.JCheckBox postHitCheckBox;

View File

@ -29,15 +29,12 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
<Component id="jScrollPane1" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@ -68,114 +65,135 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="setsListLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane2" alignment="0" min="-2" pref="314" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="newSetButton" linkSize="3" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
<Component id="editSetButton" linkSize="3" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" max="-2" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="copySetButton" linkSize="6" min="-2" pref="103" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="importSetButton" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="newSetButton" linkSize="6" min="-2" pref="97" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="editSetButton" linkSize="6" min="-2" pref="98" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="deleteSetButton" linkSize="3" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="exportSetButton" min="-2" pref="112" max="-2" attributes="0"/>
<Component id="deleteSetButton" linkSize="6" pref="111" max="32767" attributes="0"/>
</Group>
</Group>
<Component id="setsListScrollPane" min="-2" pref="344" max="-2" attributes="0"/>
<Component id="setsListScrollPane" alignment="0" min="-2" pref="346" max="-2" attributes="0"/>
<Component id="jScrollPane2" alignment="0" min="-2" pref="346" max="-2" attributes="0"/>
<Component id="setsListLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="separator" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="101" max="-2" attributes="0"/>
<Component id="filesRadioButton" min="-2" pref="47" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="dirsRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="allRadioButton" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="105" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="fileNameRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Component id="fileNameExtensionRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="101" max="-2" attributes="0"/>
<Component id="filesRadioButton" min="-2" pref="47" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="fileNameRegexCheckbox" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="rulePathConditionRegexCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="rulesListLabel" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="newRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="editRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="ignoreKnownFilesCheckbox" min="-2" max="-2" attributes="0"/>
<Component id="dirsRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="ingoreUnallocCheckbox" min="-2" pref="158" max="-2" attributes="0"/>
<Component id="allRadioButton" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="105" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel5" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel6" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel7" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel8" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
</Group>
<Group type="103" alignment="0" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="fileNameRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Component id="fileNameExtensionRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="fileNameRegexCheckbox" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="jLabel4" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="rulePathConditionRegexCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="mimeTypeComboBox" alignment="0" pref="313" max="32767" attributes="0"/>
<Component id="rulePathConditionTextField" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="equalitySignComboBox" min="-2" pref="44" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="fileSizeSpinner" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="fileSizeUnitComboBox" min="-2" pref="81" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="rulesListLabel" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="newRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="editRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="ignoreKnownFilesCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="ingoreUnallocCheckbox" min="-2" pref="158" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel5" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel6" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<Component id="fileNameTextField" max="32767" attributes="0"/>
</Group>
<EmptySpace min="24" pref="28" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="setDescScrollPanel" max="32767" attributes="0"/>
<Component id="rulesListScrollPane" pref="414" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="22" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel7" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel8" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
</Group>
<Group type="103" alignment="0" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="jLabel4" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="equalitySignComboBox" min="-2" pref="44" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="fileSizeSpinner" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="fileSizeUnitComboBox" min="-2" pref="79" max="-2" attributes="0"/>
</Group>
<Component id="rulePathConditionTextField" alignment="0" max="32767" attributes="0"/>
<Component id="fileNameTextField" alignment="1" max="32767" attributes="0"/>
<Component id="mimeTypeComboBox" alignment="0" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="rulesListScrollPane" alignment="1" max="32767" attributes="0"/>
<Component id="setDescScrollPanel" alignment="1" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -185,94 +203,94 @@
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="separator" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jScrollPane2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="setsListLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="setsListScrollPane" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="newSetButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="editSetButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteSetButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jLabel6" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
<Component id="setDescScrollPanel" min="-2" pref="45" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="ignoreKnownFilesCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ingoreUnallocCheckbox" alignment="3" min="-2" pref="23" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="rulesListLabel" min="-2" max="-2" attributes="0"/>
<Component id="jLabel6" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="rulesListScrollPane" pref="64" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="newRuleButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="editRuleButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteRuleButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="filesRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dirsRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="allRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="16" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileNameTextField" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="fileNameRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileNameExtensionRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileNameRegexCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="16" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="rulePathConditionTextField" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
<Component id="rulePathConditionRegexCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="mimeTypeComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel8" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="equalitySignComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileSizeSpinner" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileSizeUnitComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
</Group>
<Component id="ingestWarningLabel" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="setDescScrollPanel" min="-2" pref="45" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="ignoreKnownFilesCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ingoreUnallocCheckbox" alignment="3" min="-2" pref="23" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="rulesListLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="rulesListScrollPane" pref="82" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="newRuleButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="editRuleButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteRuleButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="filesRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dirsRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="allRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileNameTextField" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="fileNameRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileNameExtensionRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileNameRegexCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="rulePathConditionTextField" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Component id="rulePathConditionRegexCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="mimeTypeComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel8" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="equalitySignComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileSizeSpinner" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileSizeUnitComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="jScrollPane2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="setsListLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="setsListScrollPane" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="newSetButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="editSetButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteSetButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="copySetButton" alignment="3" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="importSetButton" alignment="3" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="exportSetButton" alignment="3" min="-2" pref="23" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
@ -868,6 +886,47 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="copySetButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/images/new16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties" key="FilesSetDefsPanel.interesting.copySetButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="copySetButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="importSetButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/images/import16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties" key="FilesSetDefsPanel.interesting.importSetButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="importSetButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="exportSetButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/images/export16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties" key="FilesSetDefsPanel.interesting.exportSetButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="exportSetButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>

View File

@ -19,7 +19,9 @@
package org.sleuthkit.autopsy.modules.interestingitems;
import java.awt.EventQueue;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -29,11 +31,14 @@ import java.util.TreeMap;
import java.util.logging.Level;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
@ -55,7 +60,10 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
"FilesSetDefsPanel.megaBytes=Megabytes",
"FilesSetDefsPanel.gigaBytes=Gigabytes",
"FilesSetDefsPanel.loadError=Error loading interesting files sets from file.",
"FilesSetDefsPanel.saveError=Error saving interesting files sets to file."
"FilesSetDefsPanel.saveError=Error saving interesting files sets to file.",
"FilesSetDefsPanel.interesting.copySetButton.text=Copy Set",
"FilesSetDefsPanel.interesting.importSetButton.text=Import Set",
"FilesSetDefsPanel.interesting.exportSetButton.text=Export Set"
})
public static enum PANEL_TYPE {
FILE_INGEST_FILTERS,
@ -93,12 +101,14 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
this.rulesList.addListSelectionListener(new FilesSetDefsPanel.RulesListSelectionListener());
this.ingestWarningLabel.setVisible(false);
if (panelType == PANEL_TYPE.FILE_INGEST_FILTERS) { //Hide the mimetype settings when this is displaying FileSet rules instead of interesting item rules
this.copySetButton.setVisible(false);
this.importSetButton.setVisible(false);
this.exportSetButton.setVisible(false);
this.mimeTypeComboBox.setVisible(false);
this.jLabel7.setVisible(false);
this.fileSizeUnitComboBox.setVisible(false);
this.fileSizeSpinner.setVisible(false);
this.ruleDialogTitle = "FilesSetPanel.ingest.title";
this.jLabel8.setVisible(false);
this.equalitySignComboBox.setVisible(false);
this.ignoreKnownFilesCheckbox.setVisible(false);
@ -173,17 +183,23 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
} catch (FilesSetsManager.FilesSetsManagerException ex) {
MessageNotifyUtil.Message.error(Bundle.FilesSetDefsPanel_saveError());
logger.log(Level.WARNING, Bundle.FilesSetDefsPanel_saveError(), ex);
}
}
public void enableButtons(boolean isEnabled) {
boolean setSelected = (FilesSetDefsPanel.this.setsList.getSelectedValue() != null);
boolean ruleSelected = (FilesSetDefsPanel.this.rulesList.getSelectedValue() != null);
canBeEnabled = isEnabled;
newRuleButton.setEnabled(isEnabled);
copySetButton.setEnabled(isEnabled && setSelected);
newSetButton.setEnabled(isEnabled);
editRuleButton.setEnabled(isEnabled);
editSetButton.setEnabled(isEnabled);
deleteRuleButton.setEnabled(isEnabled);
deleteSetButton.setEnabled(isEnabled);
editRuleButton.setEnabled(isEnabled && ruleSelected);
editSetButton.setEnabled(isEnabled && setSelected);
exportSetButton.setEnabled(setSelected);
importSetButton.setEnabled(isEnabled);
deleteRuleButton.setEnabled(isEnabled && ruleSelected);
deleteSetButton.setEnabled(isEnabled && setSelected);
ingestWarningLabel.setVisible(!isEnabled);
}
@ -213,6 +229,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
} catch (FilesSetsManager.FilesSetsManagerException ex) {
MessageNotifyUtil.Message.error(Bundle.FilesSetDefsPanel_loadError());
logger.log(Level.WARNING, Bundle.FilesSetDefsPanel_loadError(), ex);
this.filesSets = new TreeMap<>();
}
@ -242,6 +259,9 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
this.ingoreUnallocCheckbox.setSelected(true);
this.newSetButton.setEnabled(true && canBeEnabled);
this.editSetButton.setEnabled(false);
this.copySetButton.setEnabled(false);
this.exportSetButton.setEnabled(false);
this.importSetButton.setEnabled(true && canBeEnabled);
this.deleteSetButton.setEnabled(false);
}
@ -275,30 +295,31 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
if (e.getValueIsAdjusting()) {
return;
}
FilesSetDefsPanel.this.rulesListModel.clear();
FilesSetDefsPanel.this.resetRuleComponents();
//enable the new button
FilesSetDefsPanel.this.newSetButton.setEnabled(canBeEnabled);
FilesSetDefsPanel.this.importSetButton.setEnabled(canBeEnabled);
// Get the selected interesting files set and populate the set
// components.
FilesSet selectedSet = FilesSetDefsPanel.this.setsList.getSelectedValue();
if (selectedSet != null) {
// Populate the components that display the properties of the
// selected files set.
FilesSetDefsPanel.this.setDescriptionTextArea.setText(selectedSet.getDescription());
FilesSetDefsPanel.this.ignoreKnownFilesCheckbox.setSelected(selectedSet.ignoresKnownFiles());
FilesSetDefsPanel.this.ingoreUnallocCheckbox.setSelected(selectedSet.ingoresUnallocatedSpace());
// Enable the new, edit and delete set buttons.
FilesSetDefsPanel.this.newSetButton.setEnabled(true && canBeEnabled);
FilesSetDefsPanel.this.editSetButton.setEnabled(true && canBeEnabled);
FilesSetDefsPanel.this.deleteSetButton.setEnabled(true && canBeEnabled);
// Enable the copy, export, edit and delete set buttons.
FilesSetDefsPanel.this.editSetButton.setEnabled(canBeEnabled);
FilesSetDefsPanel.this.deleteSetButton.setEnabled(canBeEnabled);
FilesSetDefsPanel.this.copySetButton.setEnabled(canBeEnabled);
FilesSetDefsPanel.this.exportSetButton.setEnabled(true);
// Populate the rule definitions list, sorted by name.
TreeMap<String, FilesSet.Rule> rules = new TreeMap<>(selectedSet.getRules());
for (FilesSet.Rule rule : rules.values()) {
FilesSetDefsPanel.this.rulesListModel.addElement(rule);
}
// Select the first rule by default.
if (!FilesSetDefsPanel.this.rulesListModel.isEmpty()) {
FilesSetDefsPanel.this.rulesList.setSelectedIndex(0);
@ -391,11 +412,14 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
* Display an interesting files set definition panel in a dialog box and
* respond to user interactions with the dialog.
*
* @param selectedSet The currently selected files set, may be null to
* indicate a new interesting files set definition is to
* be created.
* @param selectedSet The currently selected files set, may be null to
* indicate a new interesting files set definition is
* to be created.
* @param shouldCreateNew Wether this should be creating a new set or
* replacing the selectedSet. False for edit, true
* for copy or new.
*/
private void doFileSetsDialog(FilesSet selectedSet) {
private void doFileSetsDialog(FilesSet selectedSet, boolean shouldCreateNew) {
// Create a files set defintion panle.
FilesSetPanel panel;
if (selectedSet != null) {
@ -416,7 +440,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
// While adding new ruleset(selectedSet == null), if rule set with same name already exists, do not add to the filesSets hashMap.
// In case of editing an existing ruleset(selectedSet != null), following check is not performed.
if (this.filesSets.containsKey(panel.getFilesSetName()) && selectedSet == null) {
if (this.filesSets.containsKey(panel.getFilesSetName()) && shouldCreateNew) {
MessageNotifyUtil.Message.error(NbBundle.getMessage(this.getClass(),
"FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text",
panel.getFilesSetName()));
@ -431,7 +455,11 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
// Preserve the existing rules from the set being edited.
rules.putAll(selectedSet.getRules());
}
this.replaceFilesSet(selectedSet, panel.getFilesSetName(), panel.getFilesSetDescription(), panel.getFileSetIgnoresKnownFiles(), panel.getFileSetIgnoresUnallocatedSpace(), rules);
if (shouldCreateNew) {
this.replaceFilesSet(null, panel.getFilesSetName(), panel.getFilesSetDescription(), panel.getFileSetIgnoresKnownFiles(), panel.getFileSetIgnoresUnallocatedSpace(), rules);
} else {
this.replaceFilesSet(selectedSet, panel.getFilesSetName(), panel.getFilesSetDescription(), panel.getFileSetIgnoresKnownFiles(), panel.getFileSetIgnoresUnallocatedSpace(), rules);
}
}
}
@ -583,6 +611,9 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
fileSizeUnitComboBox = new javax.swing.JComboBox<String>();
ingoreUnallocCheckbox = new javax.swing.JCheckBox();
ingestWarningLabel = new javax.swing.JLabel();
copySetButton = new javax.swing.JButton();
importSetButton = new javax.swing.JButton();
exportSetButton = new javax.swing.JButton();
setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11));
@ -785,6 +816,32 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
ingestWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/hashdatabase/warning16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(ingestWarningLabel, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.ingestWarningLabel.text")); // NOI18N
copySetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/new16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(copySetButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.interesting.copySetButton.text")); // NOI18N
copySetButton.setEnabled(false);
copySetButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
copySetButtonActionPerformed(evt);
}
});
importSetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/import16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(importSetButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.interesting.importSetButton.text")); // NOI18N
importSetButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
importSetButtonActionPerformed(evt);
}
});
exportSetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/export16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(exportSetButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.interesting.exportSetButton.text")); // NOI18N
exportSetButton.setEnabled(false);
exportSetButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
exportSetButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
@ -792,92 +849,105 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(setsListLabel)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 314, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(newSetButton)
.addGap(9, 9, 9)
.addComponent(editSetButton)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
.addComponent(copySetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 103, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(importSetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
.addComponent(newSetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 97, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editSetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteSetButton))
.addComponent(setsListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 344, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(exportSetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(deleteSetButton, javax.swing.GroupLayout.DEFAULT_SIZE, 111, Short.MAX_VALUE)))
.addComponent(setsListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 346, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 346, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(setsListLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(separator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(101, 101, 101)
.addComponent(filesRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(dirsRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(allRadioButton))
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(105, 105, 105)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(fileNameRadioButton)
.addGap(4, 4, 4)
.addComponent(fileNameExtensionRadioButton)
.addGap(101, 101, 101)
.addComponent(filesRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(fileNameRegexCheckbox))
.addComponent(rulePathConditionRegexCheckBox)))
.addGroup(jPanel1Layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(rulesListLabel)
.addComponent(jLabel1)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(newRuleButton)
.addGap(18, 18, 18)
.addComponent(editRuleButton)
.addGap(18, 18, 18)
.addComponent(deleteRuleButton))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(ignoreKnownFilesCheckbox)
.addComponent(dirsRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 158, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(allRadioButton))
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(105, 105, 105)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel5)
.addComponent(jLabel6))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(fileNameRadioButton)
.addGap(4, 4, 4)
.addComponent(fileNameExtensionRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(fileNameRegexCheckbox))
.addComponent(rulePathConditionRegexCheckBox)))
.addGroup(jPanel1Layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ingestWarningLabel))))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(rulesListLabel)
.addComponent(jLabel1)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(newRuleButton)
.addGap(18, 18, 18)
.addComponent(editRuleButton)
.addGap(18, 18, 18)
.addComponent(deleteRuleButton))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(ignoreKnownFilesCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 158, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel5)
.addComponent(jLabel6))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ingestWarningLabel)))))
.addGap(24, 28, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(29, 29, 29)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(22, 22, 22)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel7)
.addComponent(jLabel8))
.addGap(18, 18, 18))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel7)
.addComponent(jLabel8))
.addGap(18, 18, 18))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel3)
.addComponent(jLabel2))
.addGap(6, 6, 6))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addComponent(jLabel4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED))))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(mimeTypeComboBox, 0, 313, Short.MAX_VALUE)
.addComponent(rulePathConditionTextField)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel3)
.addComponent(jLabel2))
.addGap(6, 6, 6))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addComponent(jLabel4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED))))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fileSizeSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(rulePathConditionTextField)
.addComponent(fileNameTextField, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(mimeTypeComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fileSizeSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(fileNameTextField)))
.addGroup(jPanel1Layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(setDescScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(rulesListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE))))
.addGap(18, 18, 18))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(rulesListScrollPane, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(setDescScrollPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addGap(8, 8, 8))))
);
jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteSetButton, editSetButton, newSetButton});
jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {copySetButton, deleteSetButton, editSetButton, newSetButton});
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -888,75 +958,77 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel6)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(setsListLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(setsListScrollPane)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newSetButton)
.addComponent(editSetButton)
.addComponent(deleteSetButton)))
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel6)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel5)
.addGap(1, 1, 1))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addComponent(ingestWarningLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)))
.addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(6, 6, 6)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ignoreKnownFilesCheckbox)
.addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(rulesListLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rulesListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 64, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newRuleButton)
.addComponent(editRuleButton)
.addComponent(deleteRuleButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)
.addGap(8, 8, 8)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel2)
.addComponent(filesRadioButton)
.addComponent(dirsRadioButton)
.addComponent(allRadioButton))
.addGap(16, 16, 16)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel3)
.addComponent(fileNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(fileNameRadioButton)
.addComponent(fileNameExtensionRadioButton)
.addComponent(fileNameRegexCheckbox))
.addGap(16, 16, 16)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel4)
.addComponent(rulePathConditionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(7, 7, 7)
.addComponent(rulePathConditionRegexCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel7)
.addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel8)
.addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(5, 5, 5)))
.addGap(5, 5, 5))))
.addComponent(jLabel5)
.addGap(1, 1, 1))
.addComponent(ingestWarningLabel, javax.swing.GroupLayout.Alignment.TRAILING))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(6, 6, 6)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ignoreKnownFilesCheckbox)
.addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(rulesListLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rulesListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 82, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newRuleButton)
.addComponent(editRuleButton)
.addComponent(deleteRuleButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)
.addGap(8, 8, 8)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel2)
.addComponent(filesRadioButton)
.addComponent(dirsRadioButton)
.addComponent(allRadioButton))
.addGap(8, 8, 8)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel3)
.addComponent(fileNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(fileNameRadioButton)
.addComponent(fileNameExtensionRadioButton)
.addComponent(fileNameRegexCheckbox))
.addGap(8, 8, 8)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel4)
.addComponent(rulePathConditionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(6, 6, 6)
.addComponent(rulePathConditionRegexCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel7)
.addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel8)
.addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(5, 5, 5))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(setsListLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(setsListScrollPane)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newSetButton)
.addComponent(editSetButton)
.addComponent(deleteSetButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(copySetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(importSetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(exportSetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(6, 6, 6))))
);
jPanel1Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {deleteRuleButton, deleteSetButton, editRuleButton, editSetButton, newRuleButton, newSetButton});
@ -967,9 +1039,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1)
.addGap(0, 0, 0))
.addComponent(jScrollPane1)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -978,7 +1048,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
}// </editor-fold>//GEN-END:initComponents
private void newSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newSetButtonActionPerformed
this.doFileSetsDialog(null);
this.doFileSetsDialog(null, true);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_newSetButtonActionPerformed
@ -1026,7 +1096,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
}//GEN-LAST:event_deleteSetButtonActionPerformed
private void editSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editSetButtonActionPerformed
this.doFileSetsDialog(this.setsList.getSelectedValue());
this.doFileSetsDialog(this.setsList.getSelectedValue(), false);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_editSetButtonActionPerformed
@ -1040,14 +1110,166 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_newRuleButtonActionPerformed
private void copySetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copySetButtonActionPerformed
this.doFileSetsDialog(this.setsList.getSelectedValue(), true);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_copySetButtonActionPerformed
@NbBundle.Messages({
"FilesSetDefsPanel.yesOwMsg=Yes, overwrite",
"FilesSetDefsPanel.noSkipMsg=No, skip",
"FilesSetDefsPanel.cancelImportMsg=Cancel import",
"# {0} - FilesSet name",
"FilesSetDefsPanel.interesting.overwriteSetPrompt=Interesting files set <{0}> already exists locally, overwrite?",
"FilesSetDefsPanel.interesting.importOwConflict=Import Interesting files set conflict",
"FilesSetDefsPanel.interesting.failImportMsg=Interesting files set not imported",
"FilesSetDefsPanel.interesting.fileExtensionFilterLbl=Autopsy Interesting File Set File (xml)",
"FilesSetDefsPanel.interesting.importButtonAction.featureName=Interesting Files Set Import"
})
private void importSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importSetButtonActionPerformed
//save currently selected value as default value to select
FilesSet selectedSet = this.setsList.getSelectedValue();
JFileChooser chooser = new JFileChooser();
final String EXTENSION = "xml"; //NON-NLS
FileNameExtensionFilter autopsyFilter = new FileNameExtensionFilter(
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.fileExtensionFilterLbl"), EXTENSION);
chooser.addChoosableFileFilter(autopsyFilter);
chooser.setAcceptAllFileFilterUsed(false);
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
int returnVal = chooser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File selFile = chooser.getSelectedFile();
if (selFile == null) {
JOptionPane.showMessageDialog(this,
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.failImportMsg"),
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.importButtonAction.featureName"),
JOptionPane.WARNING_MESSAGE);
logger.warning("Selected file was null, when trying to import interesting files set definitions");
return;
}
Collection<FilesSet> importedSets;
try {
importedSets = InterestingItemsFilesSetSettings.readDefinitionsXML(selFile).values(); //read the xml from that path
if (importedSets.isEmpty()) {
throw new FilesSetsManager.FilesSetsManagerException("No Files Sets were read from the xml.");
}
} catch (FilesSetsManager.FilesSetsManagerException ex) {
JOptionPane.showMessageDialog(this,
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.failImportMsg"),
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.importButtonAction.featureName"),
JOptionPane.WARNING_MESSAGE);
logger.log(Level.WARNING, "No Interesting files set definitions were read from the selected file, exception", ex);
return;
}
for (FilesSet set : importedSets) {
int choice = JOptionPane.OK_OPTION;
if (filesSets.containsKey(set.getName())) {
Object[] options = {NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.yesOwMsg"),
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.noSkipMsg"),
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.cancelImportMsg")};
choice = JOptionPane.showOptionDialog(this,
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.overwriteSetPrompt", set.getName()),
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.importOwConflict"),
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
}
if (choice == JOptionPane.OK_OPTION) {
selectedSet = set;
this.filesSets.put(set.getName(), set);
} else if (choice == JOptionPane.CANCEL_OPTION) {
break;
}
}
// Redo the list model for the files set list component
FilesSetDefsPanel.this.setsListModel.clear();
for (FilesSet set : this.filesSets.values()) {
this.setsListModel.addElement(set);
}
// Select the new/edited files set definition in the set definitions
// list. This will cause the selection listeners to repopulate the
// subordinate components.
this.setsList.setSelectedValue(selectedSet, true);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}
}//GEN-LAST:event_importSetButtonActionPerformed
@NbBundle.Messages({"FilesSetDefsPanel.interesting.exportButtonAction.featureName=Interesting Files Set Export",
"# {0} - file name",
"FilesSetDefsPanel.exportButtonActionPerformed.fileExistPrompt=File {0} exists, overwrite?",
"FilesSetDefsPanel.interesting.ExportedMsg=Interesting files set exported",
"FilesSetDefsPanel.interesting.failExportMsg=Export of interesting files set failed"})
private void exportSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportSetButtonActionPerformed
//display warning that existing filessets with duplicate names will be overwritten
//create file chooser to get xml filefinal String FEATURE_NAME = NbBundle.getMessage(this.getClass(),
JFileChooser chooser = new JFileChooser();
final String EXTENSION = "xml"; //NON-NLS
FileNameExtensionFilter autopsyFilter = new FileNameExtensionFilter(
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.fileExtensionFilterLbl"), EXTENSION);
chooser.addChoosableFileFilter(autopsyFilter);
chooser.setSelectedFile(new File(this.setsList.getSelectedValue().getName()));
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
int returnVal = chooser.showSaveDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
final String FEATURE_NAME = NbBundle.getMessage(this.getClass(),
"FilesSetDefsPanel.interesting.exportButtonAction.featureName");
File selFile = chooser.getSelectedFile();
if (selFile == null) {
JOptionPane.showMessageDialog(this,
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.failExportMsg"),
FEATURE_NAME,
JOptionPane.WARNING_MESSAGE);
logger.warning("Selected file was null, when trying to export interesting files set definitions");
return;
}
//force append extension if not given
String fileAbs = selFile.getAbsolutePath();
if (!fileAbs.endsWith("." + EXTENSION)) {
fileAbs = fileAbs + "." + EXTENSION;
selFile = new File(fileAbs);
}
if (selFile.exists()) {
//if the file already exists ask the user how to proceed
final String FILE_EXISTS_MESSAGE = NbBundle.getMessage(this.getClass(),
"FilesSetDefsPanel.exportButtonActionPerformed.fileExistPrompt", selFile.getName());
boolean shouldWrite = JOptionPane.showConfirmDialog(null, FILE_EXISTS_MESSAGE, FEATURE_NAME, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION;
if (!shouldWrite) {
return;
}
}
List<FilesSet> exportSets;
exportSets = new ArrayList<>();
//currently only exports selectedValue
exportSets.add(this.setsList.getSelectedValue());
boolean written = InterestingItemsFilesSetSettings.exportXmlDefinitionsFile(selFile, exportSets);
if (written) {
JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.ExportedMsg"),
FEATURE_NAME,
JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(this.getClass(), "FilesSetDefsPanel.interesting.failExportMsg"),
FEATURE_NAME,
JOptionPane.WARNING_MESSAGE);
logger.warning("Export of interesting files set failed unable to write definitions xml file");
}
}
}//GEN-LAST:event_exportSetButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JRadioButton allRadioButton;
private javax.swing.JButton copySetButton;
private javax.swing.JButton deleteRuleButton;
private javax.swing.JButton deleteSetButton;
private javax.swing.JRadioButton dirsRadioButton;
private javax.swing.JButton editRuleButton;
private javax.swing.JButton editSetButton;
private javax.swing.JComboBox<String> equalitySignComboBox;
private javax.swing.JButton exportSetButton;
private javax.swing.ButtonGroup fileNameButtonGroup;
private javax.swing.JRadioButton fileNameExtensionRadioButton;
private javax.swing.JRadioButton fileNameRadioButton;
@ -1057,6 +1279,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
private javax.swing.JComboBox<String> fileSizeUnitComboBox;
private javax.swing.JRadioButton filesRadioButton;
private javax.swing.JCheckBox ignoreKnownFilesCheckbox;
private javax.swing.JButton importSetButton;
private javax.swing.JLabel ingestWarningLabel;
private javax.swing.JCheckBox ingoreUnallocCheckbox;
private javax.swing.JLabel jLabel1;

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -31,19 +31,23 @@ import java.util.Map;
import java.util.logging.Level;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.openide.util.io.NbObjectInputStream;
import org.openide.util.io.NbObjectOutputStream;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.FileNameCondition;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.FileSizeCondition;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.MetaTypeCondition;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.MimeTypeCondition;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.ParentPathCondition;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
*
* @author oliver
*/
class InterestingItemsFilesSetSettings implements Serializable {
private static final long serialVersionUID = 1L;
@ -51,9 +55,9 @@ class InterestingItemsFilesSetSettings implements Serializable {
// TSK Framework FilesSet definitions file schema.
private static final String FILE_SETS_ROOT_TAG = "INTERESTING_FILE_SETS"; //NON-NLS
private static final String DESC_ATTR = "description"; //NON-NLS
private static final String RULE_UUID_ATTR = "ruleUUID"; //NON-NLS
private static final String IGNORE_KNOWN_FILES_ATTR = "ignoreKnown"; //NON-NLS
private static final String PATH_REGEX_ATTR = "pathRegex"; //NON-NLS
private static final String TYPE_FILTER_VALUE_ALL = "all";
private static final String TYPE_FILTER_VALUE_FILES_AND_DIRS = "files_and_dirs"; //NON-NLS
private static final String IGNORE_UNALLOCATED_SPACE = "ingoreUnallocated"; //NON-NLS
private static final String PATH_FILTER_ATTR = "pathFilter"; //NON-NLS
@ -62,12 +66,14 @@ class InterestingItemsFilesSetSettings implements Serializable {
private static final List<String> illegalFileNameChars = FilesSetsManager.getIllegalFileNameChars();
private static final String FILE_SET_TAG = "INTERESTING_FILE_SET"; //NON-NLS
private static final String NAME_RULE_TAG = "NAME"; //NON-NLS
private static final String UNNAMED_LEGACY_RULE_PREFIX = "Unnamed Rule "; // NON-NLS
private static final String NAME_ATTR = "name"; //NON-NLS
private static final String MIME_ATTR = "mimeType";
private static final String FS_COMPARATOR_ATTR = "comparatorSymbol";
private static final String FS_SIZE_ATTR = "sizeValue";
private static final String FS_UNITS_ATTR = "sizeUnits";
private static final String TYPE_FILTER_VALUE_FILES = "file"; //NON-NLS
private static final String XML_ENCODING = "UTF-8"; //NON-NLS
private static final Logger logger = Logger.getLogger(InterestingItemsFilesSetSettings.class.getName());
private static int unnamedLegacyRuleCounter;
private static final String TYPE_FILTER_ATTR = "typeFilter"; //NON-NLS
private static final String EXTENSION_RULE_TAG = "EXTENSION"; //NON-NLS
@ -93,7 +99,7 @@ class InterestingItemsFilesSetSettings implements Serializable {
*/
private static String readRuleName(Element elem) {
// The rule must have a name.
String ruleName = elem.getAttribute(InterestingItemsFilesSetSettings.NAME_ATTR);
String ruleName = elem.getAttribute(NAME_ATTR);
return ruleName;
}
@ -130,22 +136,34 @@ class InterestingItemsFilesSetSettings implements Serializable {
* @param ruleElement The XML element.
*
* @return The path condition, or null if there is an error (logged).
*
* @throws
* org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
*/
private static FilesSet.Rule.ParentPathCondition readPathCondition(Element ruleElement) {
FilesSet.Rule.ParentPathCondition condition = null;
String path = ruleElement.getAttribute(InterestingItemsFilesSetSettings.PATH_FILTER_ATTR);
String pathRegex = ruleElement.getAttribute(InterestingItemsFilesSetSettings.PATH_REGEX_ATTR);
if (!pathRegex.isEmpty() && path.isEmpty()) {
try {
Pattern pattern = Pattern.compile(pathRegex);
condition = new FilesSet.Rule.ParentPathCondition(pattern);
} catch (PatternSyntaxException ex) {
logger.log(Level.SEVERE, "Error compiling " + InterestingItemsFilesSetSettings.PATH_REGEX_ATTR + " regex, ignoring malformed path condition definition", ex); // NON-NLS
private static ParentPathCondition readPathCondition(Element ruleElement) throws FilesSetsManager.FilesSetsManagerException {
// Read in the optional path condition. Null is o.k., but if the attribute
// is there, be sure it is not malformed.
ParentPathCondition pathCondition = null;
if (!ruleElement.getAttribute(PATH_FILTER_ATTR).isEmpty() || !ruleElement.getAttribute(PATH_REGEX_ATTR).isEmpty()) {
String path = ruleElement.getAttribute(PATH_FILTER_ATTR);
String pathRegex = ruleElement.getAttribute(PATH_REGEX_ATTR);
if (!pathRegex.isEmpty() && path.isEmpty()) {
try {
Pattern pattern = Pattern.compile(pathRegex);
pathCondition = new ParentPathCondition(pattern);
} catch (PatternSyntaxException ex) {
logger.log(Level.SEVERE, "Error compiling " + PATH_REGEX_ATTR + " regex, ignoring malformed path condition definition", ex); // NON-NLS
throw new FilesSetsManager.FilesSetsManagerException(String.format("error compiling %s regex", PATH_REGEX_ATTR), ex);
}
} else if (!path.isEmpty() && pathRegex.isEmpty()) {
pathCondition = new ParentPathCondition(path);
}
if (pathCondition == null) {
// Malformed attribute.
throw new FilesSetsManager.FilesSetsManagerException(String.format("Error creating path condition for rule %s", readRuleName(ruleElement)));
}
} else if (!path.isEmpty() && pathRegex.isEmpty()) {
condition = new FilesSet.Rule.ParentPathCondition(path);
}
return condition;
return pathCondition;
}
/**
@ -165,116 +183,129 @@ class InterestingItemsFilesSetSettings implements Serializable {
}
/**
* Construct a FilesSet file name extension rule from the data in an XML
* element.
* Construct a fileset membership rule from the data in an xml element for
* use in a FilesSet.
*
* @param elem The file name extension rule XML element.
* @param elem The XML element.
*
* @return A file name extension rule, or null if there is an error (the
* error is logged).
* @return A file set constructed from the conditions available in the XML element
*
* @throws
* org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
*/
private static FilesSet.Rule readFileExtensionRule(Element elem) {
String ruleName = InterestingItemsFilesSetSettings.readRuleName(elem);
// The content of the rule tag is a file name extension condition. It may
// be a regex, or it may be from a TSK Framework rule definition
// with a "*" globbing char.
String content = elem.getTextContent();
FilesSet.Rule.ExtensionCondition extCondition;
String regex = elem.getAttribute(InterestingItemsFilesSetSettings.REGEX_ATTR);
if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) {
// NON-NLS
Pattern pattern = compileRegex(content);
if (pattern != null) {
extCondition = new FilesSet.Rule.ExtensionCondition(pattern);
} else {
logger.log(Level.SEVERE, "Error compiling " + InterestingItemsFilesSetSettings.EXTENSION_RULE_TAG + " regex, ignoring malformed {0} rule definition", ruleName); // NON-NLS
return null;
}
} else {
for (String illegalChar : illegalFileNameChars) {
if (content.contains(illegalChar)) {
logger.log(Level.SEVERE, "{0} content has illegal chars, ignoring malformed {1} rule definition", ruleName); // NON-NLS
return null;
}
}
extCondition = new FilesSet.Rule.ExtensionCondition(content);
private static FilesSet.Rule readRule(Element elem) throws FilesSetsManager.FilesSetsManagerException {
String ruleName = readRuleName(elem);
FileNameCondition nameCondition = readNameCondition(elem);
MetaTypeCondition metaCondition = readMetaTypeCondition(elem);
ParentPathCondition pathCondition = readPathCondition(elem);
MimeTypeCondition mimeCondition = readMimeCondition(elem);
FileSizeCondition sizeCondition = readSizeCondition(elem);
//if meta type condition or all four types of conditions the user can create are all null then don't make the rule
if (metaCondition == null || (nameCondition == null && pathCondition == null && mimeCondition == null && sizeCondition == null)) {
logger.log(Level.WARNING, "Error Reading Rule, " + ruleName + " was either missing a meta condition or contained only a meta condition. No rule was imported."); // NON-NLS
throw new FilesSetsManager.FilesSetsManagerException(String.format("Invalid Rule in FilesSet xml, missing necessary conditions for %s", ruleName));
}
// The rule must have a meta-type condition, unless a TSK Framework
// definitions file is being read.
FilesSet.Rule.MetaTypeCondition metaTypeCondition = null;
if (!elem.getAttribute(InterestingItemsFilesSetSettings.TYPE_FILTER_ATTR).isEmpty()) {
metaTypeCondition = InterestingItemsFilesSetSettings.readMetaTypeCondition(elem);
if (metaTypeCondition == null) {
// Malformed attribute.
return null;
}
} else {
metaTypeCondition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES);
}
// The rule may have a path condition. Null is o.k., but if the attribute
// is there, it must not be malformed.
FilesSet.Rule.ParentPathCondition pathCondition = null;
if (!elem.getAttribute(InterestingItemsFilesSetSettings.PATH_FILTER_ATTR).isEmpty() || !elem.getAttribute(InterestingItemsFilesSetSettings.PATH_REGEX_ATTR).isEmpty()) {
pathCondition = InterestingItemsFilesSetSettings.readPathCondition(elem);
if (pathCondition == null) {
// Malformed attribute.
return null;
}
}
return new FilesSet.Rule(ruleName, extCondition, metaTypeCondition, pathCondition, null, null);
return new FilesSet.Rule(ruleName, nameCondition, metaCondition, pathCondition, mimeCondition, sizeCondition);
}
/**
* Construct a FilesSet file name rule from the data in an XML element.
* Construct a file name condition for a FilesSet membership rule from data in an
* XML element.
*
* @param elem The file name rule XML element.
* @param ruleElement The XML element.
*
* @return A file name rule, or null if there is an error (the error is
* logged).
* @return The file name condition, or null if none existed
*
* @throws
* org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
*/
private static FilesSet.Rule readFileNameRule(Element elem) {
String ruleName = InterestingItemsFilesSetSettings.readRuleName(elem);
// The content of the rule tag is a file name condition. It may be a
// regex, or it may be from a TSK Framework rule definition with a
// "*" globbing char, or it may be simple text.
private static FileNameCondition readNameCondition(Element elem) throws FilesSetsManager.FilesSetsManagerException {
FileNameCondition nameCondition = null;
String content = elem.getTextContent();
FilesSet.Rule.FullNameCondition nameCondition;
String regex = elem.getAttribute(InterestingItemsFilesSetSettings.REGEX_ATTR);
if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) {
// NON-NLS
Pattern pattern = compileRegex(content);
if (pattern != null) {
nameCondition = new FilesSet.Rule.FullNameCondition(pattern);
String regex = elem.getAttribute(REGEX_ATTR);
if (content != null && !content.isEmpty()) { //if there isn't content this is not a valid name condition
if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { // NON-NLS
Pattern pattern = compileRegex(content);
if (pattern != null) {
if (elem.getTagName().equals(NAME_RULE_TAG)) {
nameCondition = new FilesSet.Rule.FullNameCondition(pattern);
} else if (elem.getTagName().equals(EXTENSION_RULE_TAG)) {
nameCondition = new FilesSet.Rule.ExtensionCondition(pattern);
} else {
throw new FilesSetsManager.FilesSetsManagerException(String.format("Name condition has invalid tag name of %s for rule %s", elem.getTagName(), readRuleName(elem)));
}
} else {
logger.log(Level.SEVERE, "Error compiling " + elem.getTagName() + " regex, ignoring malformed '{0}' rule definition", readRuleName(elem)); // NON-NLS
throw new FilesSetsManager.FilesSetsManagerException(String.format("error compiling %s regex in rule %s", REGEX_ATTR, readRuleName(elem)));
}
} else {
logger.log(Level.SEVERE, "Error compiling " + InterestingItemsFilesSetSettings.NAME_RULE_TAG + " regex, ignoring malformed '{0}' rule definition", ruleName); // NON-NLS
return null;
}
} else {
for (String illegalChar : illegalFileNameChars) {
if (content.contains(illegalChar)) {
logger.log(Level.SEVERE, InterestingItemsFilesSetSettings.NAME_RULE_TAG + " content has illegal chars, ignoring malformed '{0}' rule definition", new Object[]{InterestingItemsFilesSetSettings.NAME_RULE_TAG, ruleName}); // NON-NLS
return null;
for (String illegalChar : illegalFileNameChars) {
if (content.contains(illegalChar)) {
logger.log(Level.SEVERE, elem.getTagName() + " content has illegal chars, ignoring malformed '{0}' rule definition", new Object[]{elem.getTagName(), readRuleName(elem)}); // NON-NLS
throw new FilesSetsManager.FilesSetsManagerException(String.format("File name has illegal character of %s in rule %s", illegalChar, readRuleName(elem)));
}
}
if (elem.getTagName().equals(NAME_RULE_TAG)) {
nameCondition = new FilesSet.Rule.FullNameCondition(content);
} else if (elem.getTagName().equals(EXTENSION_RULE_TAG)) {
nameCondition = new FilesSet.Rule.ExtensionCondition(content);
}
}
nameCondition = new FilesSet.Rule.FullNameCondition(content);
}
// Read in the type condition.
FilesSet.Rule.MetaTypeCondition metaTypeCondition = InterestingItemsFilesSetSettings.readMetaTypeCondition(elem);
if (metaTypeCondition == null) {
// Malformed attribute.
return null;
return nameCondition;
}
/**
* Construct a MIME type condition for a FilesSet membership rule from data in an
* XML element.
*
* @param ruleElement The XML element.
*
* @return The mime TYPE condition, or null if none existed
*/
private static MimeTypeCondition readMimeCondition(Element elem) {
MimeTypeCondition mimeCondition = null;
if (!elem.getAttribute(MIME_ATTR).isEmpty()) {
mimeCondition = new MimeTypeCondition(elem.getAttribute(MIME_ATTR));
//no checks on mime type here which means
//if they import a rule with a custom MIME type they don't have
//the rule will not get any hits
}
// Read in the optional path condition. Null is o.k., but if the attribute
// is there, be sure it is not malformed.
FilesSet.Rule.ParentPathCondition pathCondition = null;
if (!elem.getAttribute(InterestingItemsFilesSetSettings.PATH_FILTER_ATTR).isEmpty() || !elem.getAttribute(InterestingItemsFilesSetSettings.PATH_REGEX_ATTR).isEmpty()) {
pathCondition = InterestingItemsFilesSetSettings.readPathCondition(elem);
if (pathCondition == null) {
// Malformed attribute.
return null;
return mimeCondition;
}
/**
* Construct a file size condition for a FilesSet membership rule from data in an
* XML element.
*
* @param ruleElement The XML element.
*
* @return The file size condition, or null if none existed
*
* @throws
* org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
*/
private static FileSizeCondition readSizeCondition(Element elem) throws FilesSetsManager.FilesSetsManagerException {
FileSizeCondition sizeCondition = null;
if (!elem.getAttribute(FS_COMPARATOR_ATTR).isEmpty() && !elem.getAttribute(FS_SIZE_ATTR).isEmpty() && !elem.getAttribute(FS_UNITS_ATTR).isEmpty()) {
try { //incase they modified the xml manually to invalid comparator, size unit, or non integer string for size
FileSizeCondition.COMPARATOR comparator = FileSizeCondition.COMPARATOR.fromSymbol(elem.getAttribute(FS_COMPARATOR_ATTR));
FileSizeCondition.SIZE_UNIT sizeUnit = FileSizeCondition.SIZE_UNIT.fromName(elem.getAttribute(FS_UNITS_ATTR));
int size = Integer.parseInt(elem.getAttribute(FS_SIZE_ATTR));
sizeCondition = new FileSizeCondition(comparator, sizeUnit, size);
} catch (NumberFormatException nfEx) {
logger.log(Level.SEVERE, "Value in file size attribute was not an integer, unable to create FileSizeCondition for rule: " + readRuleName(elem), nfEx);
throw new FilesSetsManager.FilesSetsManagerException(String.format("Non integer size in FilesSet XML for rule %s", readRuleName(elem)), nfEx);
} catch (IllegalArgumentException iaEx) {
logger.log(Level.SEVERE, "Invalid Comparator symbol or Size Unit set in FilesSet xml, unable to create FileSizeCondition for rule: " + readRuleName(elem), iaEx);
throw new FilesSetsManager.FilesSetsManagerException(String.format("Invalid Comparator or Size unit in FilesSet XML for rule %s", readRuleName(elem)), iaEx);
}
} //if all of them aren't populated but some of them are this is a malformed xml
else if (!elem.getAttribute(FS_COMPARATOR_ATTR).isEmpty() || !elem.getAttribute(FS_SIZE_ATTR).isEmpty() || !elem.getAttribute(FS_UNITS_ATTR).isEmpty()) {
logger.log(Level.SEVERE, "Invalid Comparator symbol or Size Unit set in FilesSet xml, unable to create FileSizeCondition for rule: " + readRuleName(elem));
throw new FilesSetsManager.FilesSetsManagerException(String.format("XML malformed missing at least one fileSize attribute for rule %s", readRuleName(elem)));
}
return new FilesSet.Rule(ruleName, nameCondition, metaTypeCondition, pathCondition, null, null);
return sizeCondition;
}
/**
@ -283,12 +314,15 @@ class InterestingItemsFilesSetSettings implements Serializable {
* @param setElem A FilesSet XML element
* @param filesSets A collection to which the set is to be added.
* @param filePath The source file, used for error reporting.
*
* @throws
* org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
*/
private static void readFilesSet(Element setElem, Map<String, FilesSet> filesSets, String filePath) {
private static void readFilesSet(Element setElem, Map<String, FilesSet> filesSets, String filePath) throws FilesSetsManager.FilesSetsManagerException {
// The file set must have a unique name.
String setName = setElem.getAttribute(InterestingItemsFilesSetSettings.NAME_ATTR);
String setName = setElem.getAttribute(NAME_ATTR);
if (setName.isEmpty()) {
logger.log(Level.SEVERE, "Found {0} element without required {1} attribute, ignoring malformed file set definition in FilesSet definition file at {2}", new Object[]{InterestingItemsFilesSetSettings.FILE_SET_TAG, InterestingItemsFilesSetSettings.NAME_ATTR, filePath}); // NON-NLS
logger.log(Level.SEVERE, "Found {0} element without required {1} attribute, ignoring malformed file set definition in FilesSet definition file at {2}", new Object[]{FILE_SET_TAG, NAME_ATTR, filePath}); // NON-NLS
return;
}
if (filesSets.containsKey(setName)) {
@ -296,55 +330,39 @@ class InterestingItemsFilesSetSettings implements Serializable {
return;
}
// The file set may have a description. The empty string is o.k.
String description = setElem.getAttribute(InterestingItemsFilesSetSettings.DESC_ATTR);
String description = setElem.getAttribute(DESC_ATTR);
// The file set may or may not ignore known files. The default behavior
// is to not ignore them.
String ignoreKnown = setElem.getAttribute(InterestingItemsFilesSetSettings.IGNORE_KNOWN_FILES_ATTR);
String ignoreKnown = setElem.getAttribute(IGNORE_KNOWN_FILES_ATTR);
boolean ignoreKnownFiles = false;
if (!ignoreKnown.isEmpty()) {
ignoreKnownFiles = Boolean.parseBoolean(ignoreKnown);
}
// The file set may or may not skip unallocated space. The default behavior
// is not to skip it.
String ignoreUnallocated = setElem.getAttribute(InterestingItemsFilesSetSettings.IGNORE_UNALLOCATED_SPACE);
String ignoreUnallocated = setElem.getAttribute(IGNORE_UNALLOCATED_SPACE);
boolean ignoreUnallocatedSpace = false;
if (!ignoreUnallocated.isEmpty()) {
ignoreUnallocatedSpace = Boolean.parseBoolean(ignoreUnallocated);
}
// Read file name set membership rules, if any.
InterestingItemsFilesSetSettings.unnamedLegacyRuleCounter = 1;
// Read the set membership rules, if any.
Map<String, FilesSet.Rule> rules = new HashMap<>();
NodeList nameRuleElems = setElem.getElementsByTagName(InterestingItemsFilesSetSettings.NAME_RULE_TAG);
for (int j = 0; j < nameRuleElems.getLength(); ++j) {
Element elem = (Element) nameRuleElems.item(j);
FilesSet.Rule rule = InterestingItemsFilesSetSettings.readFileNameRule(elem);
if (rule != null) {
if (!rules.containsKey(rule.getUuid())) {
rules.put(rule.getUuid(), rule);
NodeList allRuleElems = setElem.getChildNodes();
for (int j = 0; j < allRuleElems.getLength(); ++j) {
if (allRuleElems.item(j) instanceof Element) { //All the children we need to parse here are elements
Element elem = (Element) allRuleElems.item(j);
FilesSet.Rule rule = readRule(elem);
if (rule != null) {
if (!rules.containsKey(rule.getUuid())) {
rules.put(rule.getUuid(), rule);
} else {
logger.log(Level.SEVERE, "Found duplicate rule {0} for set named {1} in FilesSet definition file at {2}, discarding malformed set", new Object[]{rule.getUuid(), setName, filePath}); // NON-NLS
return;
}
} else {
logger.log(Level.SEVERE, "Found duplicate rule {0} for set named {1} in FilesSet definition file at {2}, discarding malformed set", new Object[]{rule.getUuid(), setName, filePath}); // NON-NLS
logger.log(Level.SEVERE, "Found malformed rule for set named {0} in FilesSet definition file at {1}, discarding malformed set", new Object[]{setName, filePath}); // NON-NLS
return;
}
} else {
logger.log(Level.SEVERE, "Found malformed rule for set named {0} in FilesSet definition file at {1}, discarding malformed set", new Object[]{setName, filePath}); // NON-NLS
return;
}
}
// Read file extension set membership rules, if any.
NodeList extRuleElems = setElem.getElementsByTagName(InterestingItemsFilesSetSettings.EXTENSION_RULE_TAG);
for (int j = 0; j < extRuleElems.getLength(); ++j) {
Element elem = (Element) extRuleElems.item(j);
FilesSet.Rule rule = InterestingItemsFilesSetSettings.readFileExtensionRule(elem);
if (rule != null) {
if (!rules.containsKey(rule.getUuid())) {
rules.put(rule.getUuid(), rule);
} else {
logger.log(Level.SEVERE, "Found duplicate rule {0} for set named {1} in FilesSet definition file at {2}, discarding malformed set", new Object[]{rule.getUuid(), setName, filePath}); //NOI18N NON-NLS
return;
}
} else {
logger.log(Level.SEVERE, "Found malformed rule for set named {0} in FilesSet definition file at {1}, discarding malformed set", new Object[]{setName, filePath}); //NOI18N NON-NLS
return;
}
}
// Make the files set. Note that degenerate sets with no rules are
@ -353,18 +371,21 @@ class InterestingItemsFilesSetSettings implements Serializable {
FilesSet set = new FilesSet(setName, description, ignoreKnownFiles, ignoreUnallocatedSpace, rules);
filesSets.put(set.getName(), set);
}
// Note: This method takes a file path to support the possibility of
// multiple intersting files set definition files, e.g., one for
// definitions that ship with Autopsy and one for user definitions.
/**
* Reads FilesSet definitions from an XML file.
* Reads FilesSet definitions from Serialized file or XML file.
*
* @param fileName The name of the file which is expected to store the
* serialized definitions
* @param legacyFilePath Path of the set definitions file as a string.
* @param legacyFileName Name of the xml set definitions file as a string.
*
* @return The set definitions in a map of set names to sets.
*
* @throws
* org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
*/
static Map<String, FilesSet> readDefinitionsFile(String fileName, String legacyFileName) throws FilesSetsManager.FilesSetsManagerException {
Map<String, FilesSet> filesSets = readSerializedDefinitions(fileName);
@ -373,32 +394,50 @@ class InterestingItemsFilesSetSettings implements Serializable {
}
// Check if the legacy xml file exists.
if (!legacyFileName.isEmpty()) {
File defsFile = Paths.get(PlatformUtil.getUserConfigDirectory(), legacyFileName).toFile();
if (!defsFile.exists()) {
return filesSets;
}
// Check if the file can be read.
if (!defsFile.canRead()) {
logger.log(Level.SEVERE, "FilesSet definition file at {0} exists, but cannot be read", defsFile.getPath()); // NON-NLS
return filesSets;
}
// Parse the XML in the file.
Document doc = XMLUtil.loadDoc(InterestingItemsFilesSetSettings.class, defsFile.getPath());
if (doc == null) {
logger.log(Level.SEVERE, "FilesSet definition file at {0}", defsFile.getPath()); // NON-NLS
return filesSets;
}
// Get the root element.
Element root = doc.getDocumentElement();
if (root == null) {
logger.log(Level.SEVERE, "Failed to get root {0} element tag of FilesSet definition file at {1}", new Object[]{InterestingItemsFilesSetSettings.FILE_SETS_ROOT_TAG, defsFile.getPath()}); // NON-NLS
return filesSets;
}
// Read in the files set definitions.
NodeList setElems = root.getElementsByTagName(FILE_SET_TAG);
for (int i = 0; i < setElems.getLength(); ++i) {
readFilesSet((Element) setElems.item(i), filesSets, defsFile.getPath());
}
return readDefinitionsXML(Paths.get(PlatformUtil.getUserConfigDirectory(), legacyFileName).toFile());
}
return filesSets;
}
/**
* Reads an XML file and returns a map of fileSets. Allows for legacy XML
* support as well as importing of file sets to XMLs.
*
* @param xmlFilePath - The Path to the xml file containing the
* definition(s).
*
* @return fileSets - a Map<String, Filesset> of the definition(s) found in
* the xml file.
*
* @throws
* org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
*/
static Map<String, FilesSet> readDefinitionsXML(File xmlFile) throws FilesSetsManager.FilesSetsManagerException {
Map<String, FilesSet> filesSets = new HashMap<>();
if (!xmlFile.exists()) {
return filesSets;
}
// Check if the file can be read.
if (!xmlFile.canRead()) {
logger.log(Level.SEVERE, "FilesSet definition file at {0} exists, but cannot be read", xmlFile.getPath()); // NON-NLS
return filesSets;
}
// Parse the XML in the file.
Document doc = XMLUtil.loadDoc(InterestingItemsFilesSetSettings.class, xmlFile.getPath());
if (doc == null) {
logger.log(Level.SEVERE, "FilesSet definition file at {0}", xmlFile.getPath()); // NON-NLS
return filesSets;
}
// Get the root element.
Element root = doc.getDocumentElement();
if (root == null) {
logger.log(Level.SEVERE, "Failed to get root {0} element tag of FilesSet definition file at {1}", new Object[]{FILE_SETS_ROOT_TAG, xmlFile.getPath()}); // NON-NLS
return filesSets;
}
// Read in the files set definitions.
NodeList setElems = root.getElementsByTagName(FILE_SET_TAG);
for (int i = 0; i < setElems.getLength(); ++i) {
readFilesSet((Element) setElems.item(i), filesSets, xmlFile.getPath());
}
return filesSets;
}
@ -422,6 +461,102 @@ class InterestingItemsFilesSetSettings implements Serializable {
return true;
}
/**
* Write the FilesSets to a file as an xml.
*
* @param xmlFile the file you will be writing the FilesSets to
* @param interestingFilesSets a map of the file sets you wish to write to
* the xml file
*
* @return true for successfully writing, false for a failure
*/
static boolean exportXmlDefinitionsFile(File xmlFile, List<FilesSet> interestingFilesSets) {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
try {
// Create the new XML document.
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement(FILE_SETS_ROOT_TAG);
doc.appendChild(rootElement);
// Add the interesting files sets to the document.
for (FilesSet set : interestingFilesSets) {
// Add the files set element and its attributes.
Element setElement = doc.createElement(FILE_SET_TAG);
setElement.setAttribute(NAME_ATTR, set.getName());
setElement.setAttribute(DESC_ATTR, set.getDescription());
setElement.setAttribute(IGNORE_KNOWN_FILES_ATTR, Boolean.toString(set.ignoresKnownFiles()));
// Add the child elements for the set membership rules.
// All conditions of a rule will be written as a single element in the xml
for (FilesSet.Rule rule : set.getRules().values()) {
// Add a rule element with the appropriate name Condition
// type tag.
Element ruleElement;
FileNameCondition nameCondition = rule.getFileNameCondition();
//The element type is just being used as another attribute for
//the name condition in legacy xmls.
//For rules which don't contain a name condition it doesn't matter
//what type of element it is
if (nameCondition instanceof FilesSet.Rule.FullNameCondition) {
ruleElement = doc.createElement(NAME_RULE_TAG);
} else {
ruleElement = doc.createElement(EXTENSION_RULE_TAG);
}
// Add the optional rule name attribute.
ruleElement.setAttribute(NAME_ATTR, rule.getName());
if (nameCondition != null) {
// Add the name Condition regex attribute
ruleElement.setAttribute(REGEX_ATTR, Boolean.toString(nameCondition.isRegex()));
// Add the name Condition text as the rule element content.
ruleElement.setTextContent(nameCondition.getTextToMatch());
}
// Add the type Condition attribute.
MetaTypeCondition typeCondition = rule.getMetaTypeCondition();
switch (typeCondition.getMetaType()) {
case FILES:
ruleElement.setAttribute(TYPE_FILTER_ATTR, TYPE_FILTER_VALUE_FILES);
break;
case DIRECTORIES:
ruleElement.setAttribute(TYPE_FILTER_ATTR, TYPE_FILTER_VALUE_DIRS);
break;
default:
ruleElement.setAttribute(TYPE_FILTER_ATTR, TYPE_FILTER_VALUE_ALL);
break;
}
// Add the optional path Condition.
ParentPathCondition pathCondition = rule.getPathCondition();
if (pathCondition != null) {
if (pathCondition.isRegex()) {
ruleElement.setAttribute(PATH_REGEX_ATTR, pathCondition.getTextToMatch());
} else {
ruleElement.setAttribute(PATH_FILTER_ATTR, pathCondition.getTextToMatch());
}
}
//Add the optional MIME type condition
MimeTypeCondition mimeCondition = rule.getMimeTypeCondition();
if (mimeCondition != null) {
ruleElement.setAttribute(MIME_ATTR, mimeCondition.getMimeType());
}
//Add the optional file size condition
FileSizeCondition sizeCondition = rule.getFileSizeCondition();
if (sizeCondition != null) {
ruleElement.setAttribute(FS_COMPARATOR_ATTR, sizeCondition.getComparator().getSymbol());
ruleElement.setAttribute(FS_SIZE_ATTR, Integer.toString(sizeCondition.getSizeValue()));
ruleElement.setAttribute(FS_UNITS_ATTR, sizeCondition.getUnit().getName());
}
setElement.appendChild(ruleElement);
}
rootElement.appendChild(setElement);
}
// Overwrite the previous definitions file. Note that the utility
// method logs an error on failure.
return XMLUtil.saveDoc(InterestingItemsFilesSetSettings.class, xmlFile.getPath(), XML_ENCODING, doc);
} catch (ParserConfigurationException ex) {
logger.log(Level.SEVERE, "Error writing interesting files definition file to " + xmlFile.getPath(), ex); // NON-NLS
return false;
}
}
/**
* Construct a meta-type condition for a FilesSet membership rule from data
* in an XML element.
@ -429,30 +564,40 @@ class InterestingItemsFilesSetSettings implements Serializable {
* @param ruleElement The XML element.
*
* @return The meta-type condition, or null if there is an error (logged).
*
* @throws
* org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
*/
private static FilesSet.Rule.MetaTypeCondition readMetaTypeCondition(Element ruleElement) {
FilesSet.Rule.MetaTypeCondition condition = null;
String conditionAttribute = ruleElement.getAttribute(InterestingItemsFilesSetSettings.TYPE_FILTER_ATTR);
if (!conditionAttribute.isEmpty()) {
switch (conditionAttribute) {
case InterestingItemsFilesSetSettings.TYPE_FILTER_VALUE_FILES:
condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES);
break;
case InterestingItemsFilesSetSettings.TYPE_FILTER_VALUE_DIRS:
condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.DIRECTORIES);
break;
case InterestingItemsFilesSetSettings.TYPE_FILTER_VALUE_FILES_AND_DIRS:
condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES_AND_DIRECTORIES);
break;
default:
logger.log(Level.SEVERE, "Found {0} " + InterestingItemsFilesSetSettings.TYPE_FILTER_ATTR + " attribute with unrecognized value ''{0}'', ignoring malformed rule definition", conditionAttribute); // NON-NLS
break;
private static MetaTypeCondition readMetaTypeCondition(Element ruleElement) throws FilesSetsManager.FilesSetsManagerException {
MetaTypeCondition metaCondition = null;
// The rule must have a meta-type condition, unless a TSK Framework
// definitions file is being read.
if (!ruleElement.getAttribute(TYPE_FILTER_ATTR).isEmpty()) {
String conditionAttribute = ruleElement.getAttribute(TYPE_FILTER_ATTR);
if (!conditionAttribute.isEmpty()) {
switch (conditionAttribute) {
case TYPE_FILTER_VALUE_FILES:
metaCondition = new MetaTypeCondition(MetaTypeCondition.Type.FILES);
break;
case TYPE_FILTER_VALUE_DIRS:
metaCondition = new MetaTypeCondition(MetaTypeCondition.Type.DIRECTORIES);
break;
case TYPE_FILTER_VALUE_ALL:
case TYPE_FILTER_VALUE_FILES_AND_DIRS: //converts legacy xmls to current metaCondition terms
metaCondition = new MetaTypeCondition(MetaTypeCondition.Type.ALL);
break;
default:
logger.log(Level.SEVERE, "Found {0} " + TYPE_FILTER_ATTR + " attribute with unrecognized value ''{0}'', ignoring malformed rule definition", conditionAttribute); // NON-NLS
// Malformed attribute.
throw new FilesSetsManager.FilesSetsManagerException(String.format("Malformed XML for Metatype condition, %s, in rule %s", conditionAttribute, readRuleName(ruleElement)));
}
}
} else {
}
if (metaCondition == null) {
// Accept TSK Framework FilesSet definitions,
// default to files.
condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES);
metaCondition = new MetaTypeCondition(MetaTypeCondition.Type.FILES);
}
return condition;
return metaCondition;
}
}

View File

@ -86,6 +86,7 @@ final class VMExtractorIngestModule extends DataSourceIngestModuleAdapter {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
String timeStamp = dateFormat.format(Calendar.getInstance().getTime());
String ingestJobOutputDirName = context.getDataSource().getName() + "_" + context.getDataSource().getId() + "_" + timeStamp;
ingestJobOutputDirName = ingestJobOutputDirName.replace(':', '_');
ingestJobOutputDir = Paths.get(Case.getCurrentCase().getModuleDirectory(), VMExtractorIngestModuleFactory.getModuleName(), ingestJobOutputDirName);
// create module output folder to write extracted virtual machine files to
Files.createDirectories(ingestJobOutputDir);

View File

@ -855,6 +855,8 @@ class ReportHTML implements TableReportModule {
if (iconPath == null) {
// use default Autopsy icon if custom icon is not set
iconPath = "favicon.ico";
} else {
iconPath = "agency_logo"; //ref to writeNav() for agency_logo
}
index.append("<head>\n<title>").append(reportTitle).append(" ").append(
NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getDisplayName())).append(

View File

@ -28,17 +28,18 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
import org.sleuthkit.autopsy.coreutils.Logger;
@ -280,24 +281,37 @@ public final class AutoIngestCasePanel extends JPanel {
*/
private void openCase(Path caseMetadataFilePath) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
AutoIngestCaseManager.getInstance().openCase(caseMetadataFilePath);
stopCasesTableRefreshes();
StartupWindowProvider.getInstance().close();
} catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error while opening case with case metadata file path %s", caseMetadataFilePath), ex);
/*
* ReviewModeCaseManagerExceptions have user-friendly error
* messages.
*/
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
ex.getMessage(),
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.cannotOpenCase"),
JOptionPane.ERROR_MESSAGE);
new SwingWorker<Void, Void>() {
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
@Override
protected Void doInBackground() throws Exception {
AutoIngestCaseManager.getInstance().openCase(caseMetadataFilePath);
stopCasesTableRefreshes();
StartupWindowProvider.getInstance().close();
return null;
}
@Override
protected void done() {
try {
get();
} catch (InterruptedException ex) {
logger.log(Level.SEVERE, String.format("Error while opening case with case metadata file path %s", caseMetadataFilePath), ex);
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
ex.getMessage(),
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.cannotOpenCase"),
JOptionPane.ERROR_MESSAGE);
} catch (ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error while opening case with case metadata file path %s", caseMetadataFilePath), ex);
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
ex.getCause().getMessage(),
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.cannotOpenCase"),
JOptionPane.ERROR_MESSAGE);
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}.execute();
}
/**

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2011 - 2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,7 +18,6 @@
*/
package org.sleuthkit.autopsy.experimental.autoingest;
import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
@ -29,15 +28,12 @@ import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import java.util.concurrent.TimeUnit;
import java.util.List;
import javax.annotation.concurrent.Immutable;
import org.sleuthkit.autopsy.ingest.IngestModuleError;
import org.sleuthkit.autopsy.ingest.IngestManager.IngestManagerException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
/**
* A logger for the processing of an auto ingest job by an auto ingest node. An
@ -107,8 +103,10 @@ final class AutoIngestJobLogger {
* Advanced users doing troubleshooting of an automated ingest cluster
* should also consult the Autopsy and system logs as needed.
*
* @param manifestPath The manifest for the auto ingest job.
* @param caseDirectoryPath The case directory.
* @param manifestPath The manifest for the auto ingest job.
* @param dataSourceFileName The file name of the data source for the auto
* ingest job.
* @param caseDirectoryPath The absolute path to the case directory.
*/
AutoIngestJobLogger(Path manifestPath, String dataSourceFileName, Path caseDirectoryPath) {
this.manifestPath = manifestPath;
@ -198,27 +196,31 @@ final class AutoIngestJobLogger {
/**
* Logs selection of a data source processor
* @param dsp Name of the data source processor
*
* @param dsp Name of the data source processor
*
* @throws AutoIngestJobLoggerException if there is an error writing the log
* message.
* @throws InterruptedException if interrupted while blocked waiting
* to acquire an exclusive lock on the
* log file.
*/
void logDataSourceProcessorSelected(String dsp) throws AutoIngestJobLoggerException, InterruptedException{
void logDataSourceProcessorSelected(String dsp) throws AutoIngestJobLoggerException, InterruptedException {
log(MessageCategory.INFO, "Using data source processor: " + dsp);
}
/**
* Logs the failure of the selected data source processor.
* @param dsp Name of the data source processor
*
* @param dsp Name of the data source processor
*
* @throws AutoIngestJobLoggerException if there is an error writing the log
* message.
* @throws InterruptedException if interrupted while blocked waiting
* to acquire an exclusive lock on the
* log file.
*/
void logDataSourceProcessorError(String dsp) throws AutoIngestJobLoggerException, InterruptedException{
void logDataSourceProcessorError(String dsp) throws AutoIngestJobLoggerException, InterruptedException {
log(MessageCategory.ERROR, "Error processing with data source processor: " + dsp);
}
@ -431,9 +433,10 @@ final class AutoIngestJobLogger {
* log file.
*/
private void log(MessageCategory category, String message) throws AutoIngestJobLoggerException, InterruptedException {
try (Lock lock = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, getLogPath(caseDirectoryPath).toString(), LOCK_TIME_OUT, LOCK_TIME_OUT_UNIT)) {
Path logPath = getLogPath(caseDirectoryPath);
try (Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, logPath.toString(), LOCK_TIME_OUT, LOCK_TIME_OUT_UNIT)) {
if (null != lock) {
File logFile = getLogPath(caseDirectoryPath).toFile();
File logFile = logPath.toFile();
try (PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(logFile, logFile.exists())), true)) {
writer.println(String.format("%s %s: %s: %s: %-8s: %s", logDateFormat.format((Date.from(Instant.now()).getTime())), hostName, manifestFileName, dataSourceFileName, category.toString(), message));
} catch (IOException ex) {

View File

@ -73,14 +73,11 @@ import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.core.ServicesMonitor.ServicesMonitorException;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.core.UserPreferencesException;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
@ -100,6 +97,8 @@ import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.Pro
import org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences;
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration;
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.SharedConfigurationException;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
@ -212,7 +211,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
void startUp() throws AutoIngestManagerStartupException {
SYS_LOGGER.log(Level.INFO, "Auto ingest starting");
try {
coordinationService = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot());
coordinationService = CoordinationService.getInstance();
} catch (CoordinationServiceException ex) {
throw new AutoIngestManagerStartupException("Failed to get coordination service", ex);
}

View File

@ -50,6 +50,7 @@ import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.experimental.configuration.AutoIngestSettingsPanel.UpdateConfigSwingWorker;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CategoryNode;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
@ -86,7 +87,6 @@ public class SharedConfiguration {
private static final String PREFERENCES_FOLDER = "Preferences"; //NON-NLS
public static final String FILE_EXPORTER_FOLDER = "Automated File Exporter"; //NON-NLS
private static final String LOCK_ROOT = "/autopsy"; // NON-NLS
private static final String UPLOAD_IN_PROGRESS_FILE = "uploadInProgress"; // NON-NLS
private static final String moduleDirPath = PlatformUtil.getUserConfigDirectory();
private static final Logger logger = Logger.getLogger(SharedConfiguration.class.getName());
@ -160,7 +160,7 @@ public class SharedConfiguration {
File remoteFolder = getSharedFolder();
try (Lock writeLock = CoordinationService.getServiceForNamespace(LOCK_ROOT).tryGetExclusiveLock(CoordinationService.CategoryNode.CONFIG, remoteFolder.getAbsolutePath(), 30, TimeUnit.MINUTES)) {
try (Lock writeLock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CONFIG, remoteFolder.getAbsolutePath(), 30, TimeUnit.MINUTES)) {
if (writeLock == null) {
logger.log(Level.INFO, String.format("Failed to lock %s - another node is currently uploading or downloading configuration", remoteFolder.getAbsolutePath()));
return SharedConfigResult.LOCKED;
@ -230,7 +230,7 @@ public class SharedConfiguration {
File remoteFolder = getSharedFolder();
try (Lock readLock = CoordinationService.getServiceForNamespace(LOCK_ROOT).tryGetSharedLock(CoordinationService.CategoryNode.CONFIG, remoteFolder.getAbsolutePath(), 30, TimeUnit.MINUTES)) {
try (Lock readLock = CoordinationService.getInstance().tryGetSharedLock(CategoryNode.CONFIG, remoteFolder.getAbsolutePath(), 30, TimeUnit.MINUTES)) {
if (readLock == null) {
return SharedConfigResult.LOCKED;
}

View File

@ -19,7 +19,7 @@
<dependency conf="autopsy->*" org="org.apache.solr" name="solr-solrj" rev="6.2.1"/>
<dependency conf="autopsy->*" org="commons-lang" name="commons-lang" rev="2.4"/>
<dependency conf="autopsy->*" org="commons-validator" name="commons-validator" rev="1.5.1"/>
<dependency conf="autopsy->*" org="org.apache.tika" name="tika-parsers" rev="1.5"/>
<dependency conf="autopsy->*" org="org.apache.tika" name="tika-parsers" rev="1.14"/>
<!-- metadata-extractor is required by Tika but it depends on version 2.6.2 which suffers
from an XMP library issue. -->
@ -38,5 +38,9 @@
<dependency conf="slf4j-libs->default" org="org.slf4j" name="jcl-over-slf4j" rev="1.7.10"/>
<dependency conf="slf4j-libs->default" org="org.slf4j" name="jul-to-slf4j" rev="1.7.10"/>
<!-- Tika 1.4 seems to declare a (transitive?) dependency on cleartk-util 3.2.2, but the most recent
version available is 2.0.0 Overriding the version worked-->
<override org="org.cleartk" module="cleartk-util" rev="2.0.0"/>
</dependencies>
</ivy-module>

View File

@ -1,63 +1,173 @@
file.reference.aopalliance-1.0.jar=release/modules/ext/aopalliance-1.0.jar
file.reference.apache-mime4j-core-0.7.2.jar=release/modules/ext/apache-mime4j-core-0.7.2.jar
file.reference.apache-mime4j-dom-0.7.2.jar=release/modules/ext/apache-mime4j-dom-0.7.2.jar
file.reference.asm-5.0.4.jar=release/modules/ext/asm-5.0.4.jar
file.reference.asm-all-3.1.jar=release/modules/ext/asm-all-3.1.jar
file.reference.aspectjrt-1.6.11.jar=release/modules/ext/aspectjrt-1.6.11.jar
file.reference.bcmail-jdk15-1.45.jar=release/modules/ext/bcmail-jdk15-1.45.jar
file.reference.bcprov-jdk15-1.45.jar=release/modules/ext/bcprov-jdk15-1.45.jar
file.reference.commons-compress-1.5.jar=release/modules/ext/commons-compress-1.5.jar
file.reference.bcmail-jdk15on-1.54.jar=release/modules/ext/bcmail-jdk15on-1.54.jar
file.reference.bcpkix-jdk15on-1.54.jar=release/modules/ext/bcpkix-jdk15on-1.54.jar
file.reference.bcprov-jdk15on-1.54.jar=release/modules/ext/bcprov-jdk15on-1.54.jar
file.reference.boilerpipe-1.1.0.jar=release/modules/ext/boilerpipe-1.1.0.jar
file.reference.bzip2-0.9.1.jar=release/modules/ext/bzip2-0.9.1.jar
file.reference.c3p0-0.9.1.1.jar=release/modules/ext/c3p0-0.9.1.1.jar
file.reference.cdm-4.5.5.jar=release/modules/ext/cdm-4.5.5.jar
file.reference.cleartk-util-2.0.0.jar=release/modules/ext/cleartk-util-2.0.0.jar
file.reference.commons-beanutils-1.9.2.jar=release/modules/ext/commons-beanutils-1.9.2.jar
file.reference.commons-codec-1.10.jar=release/modules/ext/commons-codec-1.10.jar
file.reference.commons-collections-3.2.2.jar=release/modules/ext/commons-collections-3.2.2.jar
file.reference.commons-collections4-4.1.jar=release/modules/ext/commons-collections4-4.1.jar
file.reference.commons-compress-1.12.jar=release/modules/ext/commons-compress-1.12.jar
file.reference.commons-csv-1.0.jar=release/modules/ext/commons-csv-1.0.jar
file.reference.commons-digester-1.8.1.jar=release/modules/ext/commons-digester-1.8.1.jar
file.reference.commons-exec-1.3.jar=release/modules/ext/commons-exec-1.3.jar
file.reference.commons-io-2.3.jar=release/modules/ext/commons-io-2.3.jar
file.reference.commons-lang-2.4-javadoc.jar=release/modules/ext/commons-lang-2.4-javadoc.jar
file.reference.commons-lang-2.4-sources.jar=release/modules/ext/commons-lang-2.4-sources.jar
file.reference.commons-lang-2.4.jar=release/modules/ext/commons-lang-2.4.jar
file.reference.commons-io-2.5.jar=release/modules/ext/commons-io-2.5.jar
file.reference.commons-lang-2.6.jar=release/modules/ext/commons-lang-2.6.jar
file.reference.commons-logging-1.2.jar=release/modules/ext/commons-logging-1.2.jar
file.reference.commons-logging-api-1.1.jar=release/modules/ext/commons-logging-api-1.1.jar
file.reference.dom4j-1.6.1.jar=release/modules/ext/dom4j-1.6.1.jar
file.reference.fontbox-1.8.4.jar=release/modules/ext/fontbox-1.8.4.jar
file.reference.geronimo-stax-api_1.0_spec-1.0.1.jar=release/modules/ext/geronimo-stax-api_1.0_spec-1.0.1.jar
file.reference.commons-validator-1.5.1-javadoc.jar=release/modules/ext/commons-validator-1.5.1-javadoc.jar
file.reference.commons-validator-1.5.1-sources.jar=release/modules/ext/commons-validator-1.5.1-sources.jar
file.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1.jar
file.reference.commons-vfs2-2.0.jar=release/modules/ext/commons-vfs2-2.0.jar
file.reference.ctakes-core-3.2.2.jar=release/modules/ext/ctakes-core-3.2.2.jar
file.reference.ctakes-core-res-3.2.2.jar=release/modules/ext/ctakes-core-res-3.2.2.jar
file.reference.ctakes-type-system-3.2.2.jar=release/modules/ext/ctakes-type-system-3.2.2.jar
file.reference.ctakes-utils-3.2.2.jar=release/modules/ext/ctakes-utils-3.2.2.jar
file.reference.curvesapi-1.04.jar=release/modules/ext/curvesapi-1.04.jar
file.reference.cxf-core-3.0.3.jar=release/modules/ext/cxf-core-3.0.3.jar
file.reference.cxf-rt-frontend-jaxrs-3.0.3.jar=release/modules/ext/cxf-rt-frontend-jaxrs-3.0.3.jar
file.reference.cxf-rt-rs-client-3.0.3.jar=release/modules/ext/cxf-rt-rs-client-3.0.3.jar
file.reference.cxf-rt-transports-http-3.0.3.jar=release/modules/ext/cxf-rt-transports-http-3.0.3.jar
file.reference.ehcache-core-2.6.2.jar=release/modules/ext/ehcache-core-2.6.2.jar
file.reference.findstructapi-0.0.1.jar=release/modules/ext/findstructapi-0.0.1.jar
file.reference.fontbox-2.0.3.jar=release/modules/ext/fontbox-2.0.3.jar
file.reference.geoapi-3.0.0.jar=release/modules/ext/geoapi-3.0.0.jar
file.reference.grib-4.5.5.jar=release/modules/ext/grib-4.5.5.jar
file.reference.gson-2.2.4.jar=release/modules/ext/gson-2.2.4.jar
file.reference.guava-17.0.jar=release/modules/ext/guava-17.0.jar
file.reference.hamcrest-core-1.3.jar=release/modules/ext/hamcrest-core-1.3.jar
file.reference.httpclient-4.3.1.jar=release/modules/ext/httpclient-4.3.1.jar
file.reference.httpclient-4.4.1.jar=release/modules/ext/httpclient-4.4.1.jar
file.reference.httpcore-4.3.jar=release/modules/ext/httpcore-4.3.jar
file.reference.httpcore-4.4.1.jar=release/modules/ext/httpcore-4.4.1.jar
file.reference.httpmime-4.3.1.jar=release/modules/ext/httpmime-4.3.1.jar
file.reference.httpmime-4.4.1.jar=release/modules/ext/httpmime-4.4.1.jar
file.reference.httpservices-4.5.5.jar=release/modules/ext/httpservices-4.5.5.jar
file.reference.icu4j-3.8.jar=release/modules/ext/icu4j-3.8.jar
file.reference.isoparser-1.0-RC-1.jar=release/modules/ext/isoparser-1.0-RC-1.jar
file.reference.isoparser-1.1.18.jar=release/modules/ext/isoparser-1.1.18.jar
file.reference.jackcess-2.1.4.jar=release/modules/ext/jackcess-2.1.4.jar
file.reference.jackcess-encrypt-2.1.1.jar=release/modules/ext/jackcess-encrypt-2.1.1.jar
file.reference.jackson-annotations-2.5.4.jar=release/modules/ext/jackson-annotations-2.5.4.jar
file.reference.jackson-core-2.8.1.jar=release/modules/ext/jackson-core-2.8.1.jar
file.reference.jackson-databind-2.5.4.jar=release/modules/ext/jackson-databind-2.5.4.jar
file.reference.jakarta-regexp-1.4.jar=release/modules/ext/jakarta-regexp-1.4.jar
file.reference.java-libpst-0.8.1.jar=release/modules/ext/java-libpst-0.8.1.jar
file.reference.javax.annotation-api-1.2.jar=release/modules/ext/javax.annotation-api-1.2.jar
file.reference.javax.ws.rs-api-2.0.1.jar=release/modules/ext/javax.ws.rs-api-2.0.1.jar
file.reference.jcip-annotations-1.0.jar=release/modules/ext/jcip-annotations-1.0.jar
file.reference.jcl-over-slf4j-1.7.7.jar=release/modules/ext/jcl-over-slf4j-1.7.7.jar
file.reference.jcommander-1.35.jar=release/modules/ext/jcommander-1.35.jar
file.reference.jdom-1.0.jar=release/modules/ext/jdom-1.0.jar
file.reference.jempbox-1.8.4.jar=release/modules/ext/jempbox-1.8.4.jar
file.reference.jdom2-2.0.4.jar=release/modules/ext/jdom2-2.0.4.jar
file.reference.jempbox-1.8.12.jar=release/modules/ext/jempbox-1.8.12.jar
file.reference.jericho-html-3.3-javadoc.jar=release/modules/ext/jericho-html-3.3-javadoc.jar
file.reference.jericho-html-3.3-sources.jar=release/modules/ext/jericho-html-3.3-sources.jar
file.reference.jericho-html-3.3.jar=release/modules/ext/jericho-html-3.3.jar
file.reference.jhighlight-1.0.2.jar=release/modules/ext/jhighlight-1.0.2.jar
file.reference.jj2000-5.2.jar=release/modules/ext/jj2000-5.2.jar
file.reference.jmatio-1.2.jar=release/modules/ext/jmatio-1.2.jar
file.reference.jna-4.1.0.jar=release/modules/ext/jna-4.1.0.jar
file.reference.joda-time-2.2.jar=release/modules/ext/joda-time-2.2.jar
file.reference.json-20140107.jar=release/modules/ext/json-20140107.jar
file.reference.json-simple-1.1.1.jar=release/modules/ext/json-simple-1.1.1.jar
file.reference.jsoup-1.7.2.jar=release/modules/ext/jsoup-1.7.2.jar
file.reference.jsr-275-0.9.3.jar=release/modules/ext/jsr-275-0.9.3.jar
file.reference.junit-4.11.jar=release/modules/ext/junit-4.11.jar
file.reference.juniversalchardet-1.0.3.jar=release/modules/ext/juniversalchardet-1.0.3.jar
file.reference.junrar-0.7.jar=release/modules/ext/junrar-0.7.jar
file.reference.jVinci-2.6.0.jar=release/modules/ext/jVinci-2.6.0.jar
file.reference.jwnl-1.3.3.jar=release/modules/ext/jwnl-1.3.3.jar
file.reference.libsvm-3.1.jar=release/modules/ext/libsvm-3.1.jar
file.reference.log4j-1.2.17.jar=release/modules/ext/log4j-1.2.17.jar
file.reference.metadata-extractor-2.7.2.jar=release/modules/ext/metadata-extractor-2.7.2.jar
file.reference.netcdf-4.2-min.jar=release/modules/ext/netcdf-4.2-min.jar
file.reference.lucene-analyzers-common-4.0.0.jar=release/modules/ext/lucene-analyzers-common-4.0.0.jar
file.reference.lucene-core-4.0.0.jar=release/modules/ext/lucene-core-4.0.0.jar
file.reference.lucene-queries-4.0.0.jar=release/modules/ext/lucene-queries-4.0.0.jar
file.reference.lucene-queryparser-4.0.0.jar=release/modules/ext/lucene-queryparser-4.0.0.jar
file.reference.lucene-sandbox-4.0.0.jar=release/modules/ext/lucene-sandbox-4.0.0.jar
file.reference.maven-scm-api-1.4.jar=release/modules/ext/maven-scm-api-1.4.jar
file.reference.maven-scm-provider-svn-commons-1.4.jar=release/modules/ext/maven-scm-provider-svn-commons-1.4.jar
file.reference.maven-scm-provider-svnexe-1.4.jar=release/modules/ext/maven-scm-provider-svnexe-1.4.jar
file.reference.metadata-extractor-2.9.1.jar=release/modules/ext/metadata-extractor-2.9.1.jar
file.reference.netcdf4-4.5.5.jar=release/modules/ext/netcdf4-4.5.5.jar
file.reference.noggit-0.5.jar=release/modules/ext/noggit-0.5.jar
file.reference.noggit-0.6.jar=release/modules/ext/noggit-0.6.jar
file.reference.openaifsm-0.0.1.jar=release/modules/ext/openaifsm-0.0.1.jar
file.reference.opennlp-maxent-3.0.3.jar=release/modules/ext/opennlp-maxent-3.0.3.jar
file.reference.opennlp-tools-1.5.3.jar=release/modules/ext/opennlp-tools-1.5.3.jar
file.reference.org.apache.felix.scr.annotations-1.6.0.jar=release/modules/ext/org.apache.felix.scr.annotations-1.6.0.jar
file.reference.org.apache.felix.scr.generator-1.1.2.jar=release/modules/ext/org.apache.felix.scr.generator-1.1.2.jar
file.reference.org.osgi.compendium-4.0.0.jar=release/modules/ext/org.osgi.compendium-4.0.0.jar
file.reference.org.osgi.core-4.0.0.jar=release/modules/ext/org.osgi.core-4.0.0.jar
file.reference.pdfbox-1.8.4.jar=release/modules/ext/pdfbox-1.8.4.jar
file.reference.poi-3.10-beta2.jar=release/modules/ext/poi-3.10-beta2.jar
file.reference.poi-ooxml-3.10-beta2.jar=release/modules/ext/poi-ooxml-3.10-beta2.jar
file.reference.poi-ooxml-schemas-3.10-beta2.jar=release/modules/ext/poi-ooxml-schemas-3.10-beta2.jar
file.reference.poi-scratchpad-3.10-beta2.jar=release/modules/ext/poi-scratchpad-3.10-beta2.jar
file.reference.pdfbox-2.0.3.jar=release/modules/ext/pdfbox-2.0.3.jar
file.reference.pdfbox-debugger-2.0.3.jar=release/modules/ext/pdfbox-debugger-2.0.3.jar
file.reference.pdfbox-tools-2.0.3.jar=release/modules/ext/pdfbox-tools-2.0.3.jar
file.reference.plexus-utils-1.5.6.jar=release/modules/ext/plexus-utils-1.5.6.jar
file.reference.poi-3.15.jar=release/modules/ext/poi-3.15.jar
file.reference.poi-ooxml-3.15.jar=release/modules/ext/poi-ooxml-3.15.jar
file.reference.poi-ooxml-schemas-3.15.jar=release/modules/ext/poi-ooxml-schemas-3.15.jar
file.reference.poi-scratchpad-3.15.jar=release/modules/ext/poi-scratchpad-3.15.jar
file.reference.protobuf-java-2.5.0.jar=release/modules/ext/protobuf-java-2.5.0.jar
file.reference.qdox-1.12.jar=release/modules/ext/qdox-1.12.jar
file.reference.rome-0.9.jar=release/modules/ext/rome-0.9.jar
file.reference.slf4j-api-1.7.6.jar=release/modules/ext/slf4j-api-1.7.6.jar
file.reference.quartz-2.2.0.jar=release/modules/ext/quartz-2.2.0.jar
file.reference.regexp-1.3.jar=release/modules/ext/regexp-1.3.jar
file.reference.rome-1.5.1.jar=release/modules/ext/rome-1.5.1.jar
file.reference.rome-utils-1.5.1.jar=release/modules/ext/rome-utils-1.5.1.jar
file.reference.sis-metadata-0.6.jar=release/modules/ext/sis-metadata-0.6.jar
file.reference.sis-netcdf-0.6.jar=release/modules/ext/sis-netcdf-0.6.jar
file.reference.sis-referencing-0.6.jar=release/modules/ext/sis-referencing-0.6.jar
file.reference.sis-storage-0.6.jar=release/modules/ext/sis-storage-0.6.jar
file.reference.sis-utility-0.6.jar=release/modules/ext/sis-utility-0.6.jar
file.reference.slf4j-api-1.7.12.jar=release/modules/ext/slf4j-api-1.7.12.jar
file.reference.solr-solrj-4.9.1-javadoc.jar=release/modules/ext/solr-solrj-4.9.1-javadoc.jar
file.reference.solr-solrj-4.9.1-sources.jar=release/modules/ext/solr-solrj-4.9.1-sources.jar
file.reference.solr-solrj-4.9.1.jar=release/modules/ext/solr-solrj-4.9.1.jar
file.reference.solr-solrj-6.2.1-javadoc.jar=release/modules/ext/solr-solrj-6.2.1-javadoc.jar
file.reference.solr-solrj-6.2.1-sources.jar=release/modules/ext/solr-solrj-6.2.1-sources.jar
file.reference.solr-solrj-6.2.1.jar=release/modules/ext/solr-solrj-6.2.1.jar
file.reference.spring-aop-3.1.2.RELEASE.jar=release/modules/ext/spring-aop-3.1.2.RELEASE.jar
file.reference.spring-asm-3.1.2.RELEASE.jar=release/modules/ext/spring-asm-3.1.2.RELEASE.jar
file.reference.spring-beans-3.1.2.RELEASE.jar=release/modules/ext/spring-beans-3.1.2.RELEASE.jar
file.reference.spring-context-3.1.2.RELEASE.jar=release/modules/ext/spring-context-3.1.2.RELEASE.jar
file.reference.spring-core-3.1.2.RELEASE.jar=release/modules/ext/spring-core-3.1.2.RELEASE.jar
file.reference.spring-expression-3.1.2.RELEASE.jar=release/modules/ext/spring-expression-3.1.2.RELEASE.jar
file.reference.sqlite-jdbc-3.8.11.2.jar=release/modules/ext/sqlite-jdbc-3.8.11.2.jar
file.reference.sqlwrapper-0.0.1.jar=release/modules/ext/sqlwrapper-0.0.1.jar
file.reference.stax2-api-3.1.4.jar=release/modules/ext/stax2-api-3.1.4.jar
file.reference.tagsoup-1.2.1.jar=release/modules/ext/tagsoup-1.2.1.jar
file.reference.tika-core-1.5.jar=release/modules/ext/tika-core-1.5.jar
file.reference.tika-parsers-1.5.jar=release/modules/ext/tika-parsers-1.5.jar
file.reference.vorbis-java-core-0.1-tests.jar=release/modules/ext/vorbis-java-core-0.1-tests.jar
file.reference.vorbis-java-tika-0.1.jar=release/modules/ext/vorbis-java-tika-0.1.jar
file.reference.wstx-asl-3.2.7.jar=release/modules/ext/wstx-asl-3.2.7.jar
file.reference.xmlbeans-2.3.0.jar=release/modules/ext/xmlbeans-2.3.0.jar
file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.jar
file.reference.tika-core-1.14.jar=release/modules/ext/tika-core-1.14.jar
file.reference.tika-parsers-1.14-javadoc.jar=release/modules/ext/tika-parsers-1.14-javadoc.jar
file.reference.tika-parsers-1.14-sources.jar=release/modules/ext/tika-parsers-1.14-sources.jar
file.reference.tika-parsers-1.14.jar=release/modules/ext/tika-parsers-1.14.jar
file.reference.udunits-4.5.5.jar=release/modules/ext/udunits-4.5.5.jar
file.reference.uimafit-core-2.1.0.jar=release/modules/ext/uimafit-core-2.1.0.jar
file.reference.uimaj-adapter-vinci-2.6.0.jar=release/modules/ext/uimaj-adapter-vinci-2.6.0.jar
file.reference.uimaj-core-2.5.0.jar=release/modules/ext/uimaj-core-2.5.0.jar
file.reference.uimaj-cpe-2.6.0.jar=release/modules/ext/uimaj-cpe-2.6.0.jar
file.reference.uimaj-document-annotation-2.5.0.jar=release/modules/ext/uimaj-document-annotation-2.5.0.jar
file.reference.uimaj-examples-2.4.0.jar=release/modules/ext/uimaj-examples-2.4.0.jar
file.reference.uimaj-tools-2.6.0.jar=release/modules/ext/uimaj-tools-2.6.0.jar
file.reference.vorbis-java-core-0.8.jar=release/modules/ext/vorbis-java-core-0.8.jar
file.reference.vorbis-java-tika-0.8.jar=release/modules/ext/vorbis-java-tika-0.8.jar
file.reference.woodstox-core-asl-4.4.1.jar=release/modules/ext/woodstox-core-asl-4.4.1.jar
file.reference.xmlbeans-2.6.0.jar=release/modules/ext/xmlbeans-2.6.0.jar
file.reference.xmlschema-core-2.1.0.jar=release/modules/ext/xmlschema-core-2.1.0.jar
file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.jar
file.reference.xz-1.5.jar=release/modules/ext/xz-1.5.jar
file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
javadoc.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1-javadoc.jar
license.file=../LICENSE-2.0.txt
nbm.homepage=http://www.sleuthkit.org/autopsy/
nbm.needs.restart=true
spec.version.base=6.3
javadoc.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1-javadoc.jar
file.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1.jar
source.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1-sources.jar
spec.version.base=6.3

View File

@ -133,214 +133,522 @@
</dependency>
</module-dependencies>
<public-packages>
<package>org.apache.commons.lang</package>
<package>org.apache.commons.lang.builder</package>
<package>org.apache.commons.lang.enums</package>
<package>org.apache.commons.lang.exception</package>
<package>org.apache.commons.lang.math</package>
<package>org.apache.commons.lang.mutable</package>
<package>org.apache.commons.lang.text</package>
<package>org.apache.commons.lang.time</package>
<package>org.apache.commons.logging.impl</package>
<package>org.apache.tika</package>
<package>org.apache.tika.config</package>
<package>org.apache.tika.detect</package>
<package>org.apache.tika.exception</package>
<package>org.apache.tika.extractor</package>
<package>org.apache.tika.fork</package>
<package>org.apache.tika.io</package>
<package>org.apache.tika.language</package>
<package>org.apache.tika.metadata</package>
<package>org.apache.tika.mime</package>
<package>org.apache.tika.parser</package>
<package>org.apache.tika.parser.asm</package>
<package>org.apache.tika.parser.audio</package>
<package>org.apache.tika.parser.chm</package>
<package>org.apache.tika.parser.chm.accessor</package>
<package>org.apache.tika.parser.chm.assertion</package>
<package>org.apache.tika.parser.chm.core</package>
<package>org.apache.tika.parser.chm.exception</package>
<package>org.apache.tika.parser.chm.lzx</package>
<package>org.apache.tika.parser.crypto</package>
<package>org.apache.tika.parser.dwg</package>
<package>org.apache.tika.parser.epub</package>
<package>org.apache.tika.parser.executable</package>
<package>org.apache.tika.parser.external</package>
<package>org.apache.tika.parser.feed</package>
<package>org.apache.tika.parser.font</package>
<package>org.apache.tika.parser.hdf</package>
<package>org.apache.tika.parser.html</package>
<package>org.apache.tika.parser.image</package>
<package>org.apache.tika.parser.image.xmp</package>
<package>org.apache.tika.parser.internal</package>
<package>org.apache.tika.parser.iptc</package>
<package>org.apache.tika.parser.iwork</package>
<package>org.apache.tika.parser.jpeg</package>
<package>org.apache.tika.parser.mail</package>
<package>org.apache.tika.parser.mbox</package>
<package>org.apache.tika.parser.microsoft</package>
<package>org.apache.tika.parser.microsoft.ooxml</package>
<package>org.apache.tika.parser.mp3</package>
<package>org.apache.tika.parser.mp4</package>
<package>org.apache.tika.parser.netcdf</package>
<package>org.apache.tika.parser.odf</package>
<package>org.apache.tika.parser.opendocument</package>
<package>org.apache.tika.parser.pdf</package>
<package>org.apache.tika.parser.pkg</package>
<package>org.apache.tika.parser.prt</package>
<package>org.apache.tika.parser.rtf</package>
<package>org.apache.tika.parser.txt</package>
<package>org.apache.tika.parser.video</package>
<package>org.apache.tika.parser.xml</package>
<package>org.apache.tika.sax</package>
<package>org.apache.tika.sax.xpath</package>
<package>org.apache.tika.utils</package>
<package>org.sleuthkit.autopsy.keywordsearch</package>
</public-packages>
<class-path-extension>
<runtime-relative-path>ext/bcmail-jdk15-1.45.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bcmail-jdk15-1.45.jar</binary-origin>
<runtime-relative-path>ext/commons-validator-1.5.1-sources.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-validator-1.5.1-sources.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tika-parsers-1.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tika-parsers-1.5.jar</binary-origin>
<runtime-relative-path>ext/commons-digester-1.8.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-digester-1.8.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jericho-html-3.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jericho-html-3.3.jar</binary-origin>
<runtime-relative-path>ext/jwnl-1.3.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jwnl-1.3.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tika-core-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tika-core-1.14.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/httpmime-4.4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/httpmime-4.4.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/lucene-queryparser-4.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/lucene-queryparser-4.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/uimaj-examples-2.4.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/uimaj-examples-2.4.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/cdm-4.5.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/cdm-4.5.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/gson-2.2.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/gson-2.2.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/org.osgi.compendium-4.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/org.osgi.compendium-4.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/slf4j-api-1.7.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/slf4j-api-1.7.6.jar</binary-origin>
<runtime-relative-path>ext/geoapi-3.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/geoapi-3.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmlbeans-2.3.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmlbeans-2.3.0.jar</binary-origin>
<runtime-relative-path>ext/hamcrest-core-1.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/hamcrest-core-1.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jempbox-1.8.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jempbox-1.8.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-ooxml-3.10-beta2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-3.10-beta2.jar</binary-origin>
<runtime-relative-path>ext/boilerpipe-1.1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/boilerpipe-1.1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-logging-api-1.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-logging-api-1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/asm-all-3.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/asm-all-3.1.jar</binary-origin>
<runtime-relative-path>ext/jakarta-regexp-1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jakarta-regexp-1.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/solr-solrj-6.2.1-javadoc.jar</runtime-relative-path>
<binary-origin>release/modules/ext/solr-solrj-6.2.1-javadoc.jar</binary-origin>
<runtime-relative-path>ext/xmlbeans-2.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmlbeans-2.6.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-3.10-beta2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-3.10-beta2.jar</binary-origin>
<runtime-relative-path>ext/maven-scm-api-1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/maven-scm-api-1.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/icu4j-3.8.jar</runtime-relative-path>
<binary-origin>release/modules/ext/icu4j-3.8.jar</binary-origin>
<runtime-relative-path>ext/quartz-2.2.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/quartz-2.2.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/fontbox-1.8.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/fontbox-1.8.4.jar</binary-origin>
<runtime-relative-path>ext/jackcess-2.1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jackcess-2.1.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmpcore-5.1.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmpcore-5.1.2.jar</binary-origin>
<runtime-relative-path>ext/slf4j-api-1.7.12.jar</runtime-relative-path>
<binary-origin>release/modules/ext/slf4j-api-1.7.12.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/metadata-extractor-2.7.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/metadata-extractor-2.7.2.jar</binary-origin>
<runtime-relative-path>ext/guava-17.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/guava-17.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tagsoup-1.2.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tagsoup-1.2.1.jar</binary-origin>
<runtime-relative-path>ext/opennlp-maxent-3.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/opennlp-maxent-3.0.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-compress-1.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-compress-1.5.jar</binary-origin>
<runtime-relative-path>ext/jVinci-2.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jVinci-2.6.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-lang-2.4-javadoc.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-lang-2.4-javadoc.jar</binary-origin>
<runtime-relative-path>ext/json-simple-1.1.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/json-simple-1.1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/org.osgi.core-4.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/org.osgi.core-4.0.0.jar</binary-origin>
<runtime-relative-path>ext/sis-utility-0.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sis-utility-0.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/httpclient-4.4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/httpclient-4.4.1.jar</binary-origin>
<runtime-relative-path>ext/jj2000-5.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jj2000-5.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/isoparser-1.0-RC-1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/isoparser-1.0-RC-1.jar</binary-origin>
<runtime-relative-path>ext/jhighlight-1.0.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jhighlight-1.0.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/uimaj-cpe-2.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/uimaj-cpe-2.6.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/log4j-1.2.17.jar</runtime-relative-path>
<binary-origin>release/modules/ext/log4j-1.2.17.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-lang-2.4-sources.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-lang-2.4-sources.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tika-core-1.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tika-core-1.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jericho-html-3.3-javadoc.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jericho-html-3.3-javadoc.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/apache-mime4j-dom-0.7.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/apache-mime4j-dom-0.7.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/org.apache.felix.scr.generator-1.1.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/org.apache.felix.scr.generator-1.1.2.jar</binary-origin>
<runtime-relative-path>ext/ctakes-utils-3.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/ctakes-utils-3.2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/solr-solrj-6.2.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/solr-solrj-6.2.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-scratchpad-3.10-beta2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-scratchpad-3.10-beta2.jar</binary-origin>
<runtime-relative-path>ext/apache-mime4j-dom-0.7.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/apache-mime4j-dom-0.7.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/netcdf-4.2-min.jar</runtime-relative-path>
<binary-origin>release/modules/ext/netcdf-4.2-min.jar</binary-origin>
<runtime-relative-path>ext/commons-compress-1.12.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-compress-1.12.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/vorbis-java-core-0.1-tests.jar</runtime-relative-path>
<binary-origin>release/modules/ext/vorbis-java-core-0.1-tests.jar</binary-origin>
<runtime-relative-path>ext/openaifsm-0.0.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/openaifsm-0.0.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/stax2-api-3.1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/stax2-api-3.1.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-collections4-4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-collections4-4.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/cxf-rt-rs-client-3.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/cxf-rt-rs-client-3.0.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-annotations-2.5.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jackson-annotations-2.5.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/findstructapi-0.0.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/findstructapi-0.0.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jcommander-1.35.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jcommander-1.35.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sis-metadata-0.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sis-metadata-0.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/isoparser-1.1.18.jar</runtime-relative-path>
<binary-origin>release/modules/ext/isoparser-1.1.18.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/vorbis-java-core-0.8.jar</runtime-relative-path>
<binary-origin>release/modules/ext/vorbis-java-core-0.8.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jdom2-2.0.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jdom2-2.0.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/java-libpst-0.8.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/java-libpst-0.8.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-codec-1.10.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-codec-1.10.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/lucene-queries-4.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/lucene-queries-4.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcprov-jdk15on-1.54.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bcprov-jdk15on-1.54.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-ooxml-schemas-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-schemas-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-scratchpad-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-scratchpad-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-vfs2-2.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-vfs2-2.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jcl-over-slf4j-1.7.7.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jcl-over-slf4j-1.7.7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tika-parsers-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tika-parsers-1.14.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackcess-encrypt-2.1.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jackcess-encrypt-2.1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/spring-expression-3.1.2.RELEASE.jar</runtime-relative-path>
<binary-origin>release/modules/ext/spring-expression-3.1.2.RELEASE.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/lucene-analyzers-common-4.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/lucene-analyzers-common-4.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tika-parsers-1.14-sources.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tika-parsers-1.14-sources.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/javax.ws.rs-api-2.0.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/javax.ws.rs-api-2.0.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/junrar-0.7.jar</runtime-relative-path>
<binary-origin>release/modules/ext/junrar-0.7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/libsvm-3.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/libsvm-3.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmlschema-core-2.1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmlschema-core-2.1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jna-4.1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jna-4.1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xz-1.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xz-1.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/qdox-1.12.jar</runtime-relative-path>
<binary-origin>release/modules/ext/qdox-1.12.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcpkix-jdk15on-1.54.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bcpkix-jdk15on-1.54.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bzip2-0.9.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bzip2-0.9.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/grib-4.5.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/grib-4.5.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/maven-scm-provider-svn-commons-1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/maven-scm-provider-svn-commons-1.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/spring-aop-3.1.2.RELEASE.jar</runtime-relative-path>
<binary-origin>release/modules/ext/spring-aop-3.1.2.RELEASE.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/json-20140107.jar</runtime-relative-path>
<binary-origin>release/modules/ext/json-20140107.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/uimaj-core-2.5.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/uimaj-core-2.5.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/pdfbox-2.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/pdfbox-2.0.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jmatio-1.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jmatio-1.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/metadata-extractor-2.9.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/metadata-extractor-2.9.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-csv-1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-csv-1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-validator-1.5.1-javadoc.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-validator-1.5.1-javadoc.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/solr-solrj-6.2.1-javadoc.jar</runtime-relative-path>
<binary-origin>release/modules/ext/solr-solrj-6.2.1-javadoc.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/lucene-sandbox-4.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/lucene-sandbox-4.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jericho-html-3.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jericho-html-3.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jsr-275-0.9.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jsr-275-0.9.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/httpservices-4.5.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/httpservices-4.5.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/plexus-utils-1.5.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/plexus-utils-1.5.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/fontbox-2.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/fontbox-2.0.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcmail-jdk15on-1.54.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bcmail-jdk15on-1.54.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/spring-beans-3.1.2.RELEASE.jar</runtime-relative-path>
<binary-origin>release/modules/ext/spring-beans-3.1.2.RELEASE.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/asm-all-3.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/asm-all-3.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tika-parsers-1.14-javadoc.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tika-parsers-1.14-javadoc.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/icu4j-3.8.jar</runtime-relative-path>
<binary-origin>release/modules/ext/icu4j-3.8.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/curvesapi-1.04.jar</runtime-relative-path>
<binary-origin>release/modules/ext/curvesapi-1.04.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmpcore-5.1.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmpcore-5.1.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sis-referencing-0.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sis-referencing-0.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/ctakes-core-res-3.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/ctakes-core-res-3.2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/joda-time-2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/joda-time-2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tagsoup-1.2.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tagsoup-1.2.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/lucene-core-4.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/lucene-core-4.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/asm-5.0.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/asm-5.0.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-logging-1.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-logging-1.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-core-2.8.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jackson-core-2.8.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/org.osgi.core-4.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/org.osgi.core-4.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/c3p0-0.9.1.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/c3p0-0.9.1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sqlwrapper-0.0.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sqlwrapper-0.0.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jericho-html-3.3-javadoc.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jericho-html-3.3-javadoc.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/udunits-4.5.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/udunits-4.5.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/aopalliance-1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/aopalliance-1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-collections-3.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-collections-3.2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/cxf-rt-frontend-jaxrs-3.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/cxf-rt-frontend-jaxrs-3.0.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/uimaj-document-annotation-2.5.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/uimaj-document-annotation-2.5.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/woodstox-core-asl-4.4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/woodstox-core-asl-4.4.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-ooxml-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/org.apache.felix.scr.generator-1.1.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/org.apache.felix.scr.generator-1.1.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/zookeeper-3.4.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/zookeeper-3.4.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/cxf-rt-transports-http-3.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/cxf-rt-transports-http-3.0.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/pdfbox-debugger-2.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/pdfbox-debugger-2.0.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-databind-2.5.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jackson-databind-2.5.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/spring-core-3.1.2.RELEASE.jar</runtime-relative-path>
<binary-origin>release/modules/ext/spring-core-3.1.2.RELEASE.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/netcdf4-4.5.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/netcdf4-4.5.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/httpclient-4.4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/httpclient-4.4.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/noggit-0.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/noggit-0.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/solr-solrj-6.2.1-sources.jar</runtime-relative-path>
<binary-origin>release/modules/ext/solr-solrj-6.2.1-sources.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/spring-asm-3.1.2.RELEASE.jar</runtime-relative-path>
<binary-origin>release/modules/ext/spring-asm-3.1.2.RELEASE.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-io-2.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-io-2.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-codec-1.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-codec-1.5.jar</binary-origin>
<runtime-relative-path>ext/junit-4.11.jar</runtime-relative-path>
<binary-origin>release/modules/ext/junit-4.11.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/protobuf-java-2.5.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/protobuf-java-2.5.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sis-netcdf-0.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sis-netcdf-0.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/javax.annotation-api-1.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/javax.annotation-api-1.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/httpcore-4.4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/httpcore-4.4.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jericho-html-3.3-sources.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jericho-html-3.3-sources.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/solr-solrj-6.2.1-sources.jar</runtime-relative-path>
<binary-origin>release/modules/ext/solr-solrj-6.2.1-sources.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/juniversalchardet-1.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/juniversalchardet-1.0.3.jar</binary-origin>
@ -350,76 +658,112 @@
<binary-origin>release/modules/ext/org.apache.felix.scr.annotations-1.6.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/noggit-0.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/noggit-0.6.jar</binary-origin>
<runtime-relative-path>ext/commons-lang-2.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-lang-2.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sqlite-jdbc-3.8.11.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sqlite-jdbc-3.8.11.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jempbox-1.8.12.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jempbox-1.8.12.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/maven-scm-provider-svnexe-1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/maven-scm-provider-svnexe-1.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/opennlp-tools-1.5.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/opennlp-tools-1.5.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/apache-mime4j-core-0.7.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/apache-mime4j-core-0.7.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/httpmime-4.4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/httpmime-4.4.1.jar</binary-origin>
<runtime-relative-path>ext/rome-utils-1.5.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/rome-utils-1.5.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/qdox-1.12.jar</runtime-relative-path>
<binary-origin>release/modules/ext/qdox-1.12.jar</binary-origin>
<runtime-relative-path>ext/pdfbox-tools-2.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/pdfbox-tools-2.0.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/httpcore-4.4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/httpcore-4.4.1.jar</binary-origin>
<runtime-relative-path>ext/sis-storage-0.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sis-storage-0.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jcip-annotations-1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jcip-annotations-1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-validator-1.5.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-validator-1.5.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-validator-1.5.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-validator-1.5.1.jar</binary-origin>
<runtime-relative-path>ext/uimafit-core-2.1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/uimafit-core-2.1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-lang-2.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-lang-2.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/rome-0.9.jar</runtime-relative-path>
<binary-origin>release/modules/ext/rome-0.9.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/geronimo-stax-api_1.0_spec-1.0.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/geronimo-stax-api_1.0_spec-1.0.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/vorbis-java-tika-0.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/vorbis-java-tika-0.1.jar</binary-origin>
<runtime-relative-path>ext/cleartk-util-2.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/cleartk-util-2.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jdom-1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jdom-1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-ooxml-schemas-3.10-beta2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-schemas-3.10-beta2.jar</binary-origin>
<runtime-relative-path>ext/cxf-core-3.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/cxf-core-3.0.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/pdfbox-1.8.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/pdfbox-1.8.4.jar</binary-origin>
<runtime-relative-path>ext/regexp-1.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/regexp-1.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/wstx-asl-3.2.7.jar</runtime-relative-path>
<binary-origin>release/modules/ext/wstx-asl-3.2.7.jar</binary-origin>
<runtime-relative-path>ext/commons-beanutils-1.9.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-beanutils-1.9.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/aspectjrt-1.6.11.jar</runtime-relative-path>
<binary-origin>release/modules/ext/aspectjrt-1.6.11.jar</binary-origin>
<runtime-relative-path>ext/ehcache-core-2.6.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/ehcache-core-2.6.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/dom4j-1.6.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/dom4j-1.6.1.jar</binary-origin>
<runtime-relative-path>ext/spring-context-3.1.2.RELEASE.jar</runtime-relative-path>
<binary-origin>release/modules/ext/spring-context-3.1.2.RELEASE.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcprov-jdk15-1.45.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bcprov-jdk15-1.45.jar</binary-origin>
<runtime-relative-path>ext/ctakes-type-system-3.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/ctakes-type-system-3.2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/rome-1.5.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/rome-1.5.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/uimaj-adapter-vinci-2.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/uimaj-adapter-vinci-2.6.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/ctakes-core-3.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/ctakes-core-3.2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jsoup-1.7.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jsoup-1.7.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-exec-1.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-exec-1.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/uimaj-tools-2.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/uimaj-tools-2.6.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/vorbis-java-tika-0.8.jar</runtime-relative-path>
<binary-origin>release/modules/ext/vorbis-java-tika-0.8.jar</binary-origin>
</class-path-extension>
</data>
</configuration>

View File

@ -89,8 +89,17 @@ class AddKeywordsDialog extends javax.swing.JDialog {
* Intended to be used to redisplay any keywords that contained errors
* @param initialKeywords
*/
void setInitialKeywordList(String initialKeywords){
void setInitialKeywordList(String initialKeywords, boolean isLiteral, boolean isWholeWord){
keywordTextArea.setText(initialKeywords);
if (!isLiteral){
regexRadioButton.setSelected(true);
}
else if (isWholeWord){
exactRadioButton.setSelected(true);
}
else {
substringRadioButton.setSelected(true);
}
}

View File

@ -309,8 +309,14 @@ GlobalEditListPanel.keywordDupesSkipped.text={0} keyword was already in the list
GlobalEditListPanel.keywordDupesSkippedPlural.text={0} keywords were already in the list.
GlobalEditListPanel.keywordErrors.text={0} keyword could not be parsed. Please review and try again.
GlobalEditListPanel.keywordErrorsPlural.text={0} keywords could not be parsed. Please review and try again.
GlobalListsManagementPanel.exportButton.text=Export List
GlobalListsManagementPanel.deleteListButton.text=Delete List
GlobalListsManagementPanel.copyListButton.text=Copy List
GlobalListsManagementPanel.renameListButton.text=Rename List
GlobalEditListPanel.editWordButton.text=Edit keyword
SolrSearchService.ServiceName=Solr Keyword Search Service
SolrSearchService.IndexUpgradeDialog.title=Text Index Upgrade Required In Order To Open Case
SolrSearchService.IndexUpgradeDialog.msg=<html>The text index upgrade can take some time. <br />When completed, you will be able to see existing keyword search results and perform literal keyword searches,<br />but you will not be able to add new text to the index or perform regex searches. You may instead open the case<br /> with your previous version of this application. Do you wish to proceed with the index upgrade?</html>
SolrSearchService.IndexReadOnlyDialog.title=Text Index Is Read-Only
SolrSearchService.IndexReadOnlyDialog.msg=<html>The text index for this case is read-only. <br />You will be able to see existing keyword search results and perform literal keyword searches,<br />but you will not be able to add new text to the index or perform regex searches. You may instead open the case<br /> with your previous version of this application.</html>

View File

@ -278,3 +278,6 @@ SolrConnectionCheck.Hostname=hostname\u304c\u7121\u52b9\u3067\u3059\u3002
SolrConnectionCheck.Port=\u30dd\u30fc\u30c8\u756a\u53f7\u304c\u7121\u52b9\u3067\u3059\u3002
SolrConnectionCheck.MissingHostname=hostname\u304c\u6b20\u3051\u3066\u307e\u3059\u3002
RawText.getText.error.msg=\u30c6\u30ad\u30b9\u30c8\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
GlobalListsManagementPanel.exportButton.text=\u30ea\u30b9\u30c8\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
GlobalListsManagementPanel.deleteListButton.text=\u30ea\u30b9\u30c8\u3092\u524a\u9664
GlobalListsManagementPanel.copyListButton.text=\u30ea\u30b9\u30c8\u3092\u30b3\u30d4\u30fc

View File

@ -155,26 +155,50 @@ class DropdownToolbar extends javax.swing.JPanel {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String changed = evt.getPropertyName();
if (changed.equals(Case.Events.CURRENT_CASE.toString())) {
dropPanel.clearSearchBox();
if (RuntimeProperties.runningWithGUI() || null == evt.getNewValue()) {
try {
Server server = KeywordSearch.getServer();
Index indexInfo = server.getIndexInfo();
if (server.coreIsOpen() && IndexFinder.getCurrentSolrVersion().equals(indexInfo.getSolrVersion())) {
boolean schemaIsCurrent = IndexFinder.getCurrentSchemaVersion().equals(indexInfo.getSchemaVersion());
listsButton.setEnabled(schemaIsCurrent);
searchDropButton.setEnabled(true);
dropPanel.setRegexSearchEnabled(schemaIsCurrent);
active = true;
} else {
if (RuntimeProperties.runningWithGUI()) {
String changed = evt.getPropertyName();
if (changed.equals(Case.Events.CURRENT_CASE.toString())) {
if (null != evt.getNewValue()) {
/*
* A case has been opened.
*/
try {
Server server = KeywordSearch.getServer();
Index indexInfo = server.getIndexInfo();
if (server.coreIsOpen() && IndexFinder.getCurrentSolrVersion().equals(indexInfo.getSolrVersion())) {
/*
* Solr version is current, so check the Solr
* schema version and selectively enable the ad
* hoc search UI components.
*/
boolean schemaIsCurrent = IndexFinder.getCurrentSchemaVersion().equals(indexInfo.getSchemaVersion());
listsButton.setEnabled(schemaIsCurrent);
searchDropButton.setEnabled(true);
dropPanel.setRegexSearchEnabled(schemaIsCurrent);
active = true;
} else {
/*
* Unsupported Solr version, disable the ad hoc
* search UI components.
*/
searchDropButton.setEnabled(false);
listsButton.setEnabled(false);
active = false;
}
} catch (KeywordSearchModuleException ex) {
/*
* Error, disable the ad hoc search UI components.
*/
logger.log(Level.SEVERE, "Error getting text index info", ex); //NON-NLS
searchDropButton.setEnabled(false);
listsButton.setEnabled(false);
active = false;
}
} catch (KeywordSearchModuleException ex) {
logger.log(Level.SEVERE, "Error getting text index info", ex); //NON-NLS
} else {
/*
* A case has been closed.
*/
dropPanel.clearSearchBox();
searchDropButton.setEnabled(false);
listsButton.setEnabled(false);
active = false;

View File

@ -44,52 +44,34 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Component id="addKeywordPanel" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="keywordsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="listOptionsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="listOptionsSeparator" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="keywordOptionsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="keywordOptionsSeparator" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="482" max="32767" attributes="0"/>
</Group>
<Component id="jScrollPane1" pref="483" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="keywordsLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ingestMessagesCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="exportButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="saveListButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="deleteListButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Component id="ingestMessagesCheckbox" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="newKeywordsButton" linkSize="3" min="-2" pref="133" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
<Component id="editWordButton" linkSize="3" min="-2" pref="132" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
<Component id="deleteWordButton" linkSize="3" min="-2" pref="144" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -98,34 +80,17 @@
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="keywordsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="117" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="keywordOptionsSeparator" min="-2" pref="7" max="-2" attributes="0"/>
<Component id="keywordOptionsLabel" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
<Component id="addKeywordPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="listOptionsLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="123" max="-2" attributes="0"/>
<Component id="listOptionsSeparator" min="-2" pref="6" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="ingestMessagesCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="257" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="exportButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="saveListButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteListButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="newKeywordsButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="editWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="ingestMessagesCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -162,61 +127,6 @@
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="addKeywordPanel">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="newKeywordsButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deleteWordButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="deleteWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="newKeywordsButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="72" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="deleteWordButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/delete16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchEditListPanel.deleteWordButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteWordButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="newKeywordsButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/new16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="GlobalEditListPanel.newKeywordsButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newKeywordsButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JCheckBox" name="ingestMessagesCheckbox">
<Properties>
<Property name="selected" type="boolean" value="true"/>
@ -238,58 +148,43 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="keywordOptionsLabel">
<Component class="javax.swing.JButton" name="newKeywordsButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/new16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchEditListPanel.keywordOptionsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="GlobalEditListPanel.newKeywordsButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newKeywordsButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="listOptionsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchEditListPanel.listOptionsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSeparator" name="keywordOptionsSeparator">
</Component>
<Component class="javax.swing.JSeparator" name="listOptionsSeparator">
</Component>
<Component class="javax.swing.JButton" name="deleteListButton">
<Component class="javax.swing.JButton" name="deleteWordButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/delete16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchEditListPanel.deleteListButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchEditListPanel.deleteWordButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteListButtonActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteWordButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="saveListButton">
<Component class="javax.swing.JButton" name="editWordButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/save16.png"/>
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/edit16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchEditListPanel.saveListButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="exportButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/export16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchEditListPanel.exportButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="GlobalEditListPanel.editWordButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="exportButtonActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editWordButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,22 +19,17 @@
package org.sleuthkit.autopsy.keywordsearch;
import java.awt.EventQueue;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.JFileChooser;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import org.netbeans.spi.options.OptionsPanelController;
@ -64,8 +59,6 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
private void customizeComponents() {
newKeywordsButton.setToolTipText((NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.addWordToolTip")));
exportButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.exportToFile"));
saveListButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.saveCurrentWIthNewNameToolTip"));
deleteWordButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.removeSelectedMsg"));
keywordTable.getParent().setBackground(keywordTable.getBackground());
@ -87,11 +80,10 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
lsm.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if (lsm.isSelectionEmpty() || currentKeywordList.isEditable() || IngestManager.getInstance().isIngestRunning()) {
deleteWordButton.setEnabled(false);
} else {
deleteWordButton.setEnabled(true);
}
boolean canDelete = !(lsm.isSelectionEmpty() || currentKeywordList.isEditable() || IngestManager.getInstance().isIngestRunning());
boolean canEdit = canDelete && (lsm.getMaxSelectionIndex() == lsm.getMinSelectionIndex()); //edit only enabled with single selection
deleteWordButton.setEnabled(canDelete);
editWordButton.setEnabled(canEdit);
}
});
@ -110,310 +102,45 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
});
}
/**
* Enables and disables buttons on this panel based on the current state.
*/
void setButtonStates() {
boolean isIngestRunning = IngestManager.getInstance().isIngestRunning();
boolean isListSelected = currentKeywordList != null;
// items that only need a selected list
boolean canEditList = ((isListSelected == true) && (isIngestRunning == false));
boolean canEditList = isListSelected && !isIngestRunning;
ingestMessagesCheckbox.setEnabled(canEditList);
ingestMessagesCheckbox.setSelected(currentKeywordList != null && currentKeywordList.getIngestMessages());
listOptionsLabel.setEnabled(canEditList);
listOptionsSeparator.setEnabled(canEditList);
// items that need an unlocked list w/out ingest running
boolean isListLocked = ((isListSelected == false) || (currentKeywordList.isEditable()));
boolean canAddWord = isListSelected && !isIngestRunning && !isListLocked;
boolean canAddWord = canEditList && !currentKeywordList.isEditable();
newKeywordsButton.setEnabled(canAddWord);
keywordOptionsLabel.setEnabled(canAddWord);
keywordOptionsSeparator.setEnabled(canAddWord);
deleteListButton.setEnabled(canAddWord);
// items that need a non-empty list
if ((currentKeywordList == null) || (currentKeywordList.getKeywords().isEmpty())) {
saveListButton.setEnabled(false);
exportButton.setEnabled(false);
deleteWordButton.setEnabled(false);
} else {
saveListButton.setEnabled(true);
exportButton.setEnabled(true);
// We do not set deleteWordButton because it will be set by the list select model code when a word is selected.
editWordButton.setEnabled(false);
}
}
/**
* 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.
* Adds keywords to a keyword list, returns true if at least one keyword was successfully added and no
* duplicates were found.
*
* @return - true or false
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
listEditorPanel = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
keywordTable = new javax.swing.JTable();
addKeywordPanel = new javax.swing.JPanel();
deleteWordButton = new javax.swing.JButton();
newKeywordsButton = new javax.swing.JButton();
ingestMessagesCheckbox = new javax.swing.JCheckBox();
keywordsLabel = new javax.swing.JLabel();
keywordOptionsLabel = new javax.swing.JLabel();
listOptionsLabel = new javax.swing.JLabel();
keywordOptionsSeparator = new javax.swing.JSeparator();
listOptionsSeparator = new javax.swing.JSeparator();
deleteListButton = new javax.swing.JButton();
saveListButton = new javax.swing.JButton();
exportButton = new javax.swing.JButton();
setMinimumSize(new java.awt.Dimension(0, 0));
listEditorPanel.setMinimumSize(new java.awt.Dimension(0, 0));
jScrollPane1.setPreferredSize(new java.awt.Dimension(340, 300));
keywordTable.setModel(tableModel);
keywordTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
keywordTable.setGridColor(new java.awt.Color(153, 153, 153));
keywordTable.setMaximumSize(new java.awt.Dimension(30000, 30000));
keywordTable.getTableHeader().setReorderingAllowed(false);
jScrollPane1.setViewportView(keywordTable);
deleteWordButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N
deleteWordButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.deleteWordButton.text")); // NOI18N
deleteWordButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteWordButtonActionPerformed(evt);
}
});
newKeywordsButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/new16.png"))); // NOI18N
newKeywordsButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.newKeywordsButton.text")); // NOI18N
newKeywordsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
newKeywordsButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout addKeywordPanelLayout = new javax.swing.GroupLayout(addKeywordPanel);
addKeywordPanel.setLayout(addKeywordPanelLayout);
addKeywordPanelLayout.setHorizontalGroup(
addKeywordPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(addKeywordPanelLayout.createSequentialGroup()
.addComponent(newKeywordsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteWordButton)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
addKeywordPanelLayout.setVerticalGroup(
addKeywordPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(addKeywordPanelLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addGroup(addKeywordPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(deleteWordButton)
.addComponent(newKeywordsButton))
.addGap(72, 72, 72))
);
ingestMessagesCheckbox.setSelected(true);
ingestMessagesCheckbox.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.ingestMessagesCheckbox.text")); // NOI18N
ingestMessagesCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.ingestMessagesCheckbox.toolTipText")); // NOI18N
ingestMessagesCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
ingestMessagesCheckboxActionPerformed(evt);
}
});
keywordsLabel.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.keywordsLabel.text")); // NOI18N
keywordOptionsLabel.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.keywordOptionsLabel.text")); // NOI18N
listOptionsLabel.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.listOptionsLabel.text")); // NOI18N
deleteListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N
deleteListButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.deleteListButton.text")); // NOI18N
deleteListButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteListButtonActionPerformed(evt);
}
});
saveListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/save16.png"))); // NOI18N
saveListButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.saveListButton.text")); // NOI18N
exportButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/export16.png"))); // NOI18N
exportButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.exportButton.text")); // NOI18N
exportButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
exportButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout listEditorPanelLayout = new javax.swing.GroupLayout(listEditorPanel);
listEditorPanel.setLayout(listEditorPanelLayout);
listEditorPanelLayout.setHorizontalGroup(
listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addGap(10, 10, 10)
.addComponent(addKeywordPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addComponent(listOptionsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(listOptionsSeparator))
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addComponent(keywordOptionsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(keywordOptionsSeparator))
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addGap(10, 10, 10)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 482, Short.MAX_VALUE))
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(keywordsLabel)
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ingestMessagesCheckbox)
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addComponent(exportButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(saveListButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(deleteListButton)))))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())))
);
listEditorPanelLayout.setVerticalGroup(
listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, listEditorPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(keywordsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
.addGap(10, 10, 10)
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(keywordOptionsSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 7, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(keywordOptionsLabel))
.addGap(7, 7, 7)
.addComponent(addKeywordPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
.addComponent(listOptionsLabel))
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addGap(123, 123, 123)
.addComponent(listOptionsSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 6, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ingestMessagesCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(exportButton)
.addComponent(saveListButton)
.addComponent(deleteListButton))
.addContainerGap())
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(5, 5, 5))
);
}// </editor-fold>//GEN-END:initComponents
private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteWordButtonActionPerformed
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.removeKwMsg"), NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.deleteWordButtonActionPerformed.delConfirmMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
tableModel.deleteSelected(keywordTable.getSelectedRows());
XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
setButtonStates();
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}
}//GEN-LAST:event_deleteWordButtonActionPerformed
private void exportButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportButtonActionPerformed
final String FEATURE_NAME = NbBundle.getMessage(this.getClass(),
"KeywordSearchEditListPanel.exportButtonAction.featureName.text");
JFileChooser chooser = new JFileChooser();
final String EXTENSION = "xml"; //NON-NLS
FileNameExtensionFilter filter = new FileNameExtensionFilter(
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.fileFilterLabel"), EXTENSION);
chooser.setFileFilter(filter);
chooser.setSelectedFile(new File(currentKeywordList.getName()));
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
int returnVal = chooser.showSaveDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File selFile = chooser.getSelectedFile();
if (selFile == null) {
return;
}
//force append extension if not given
String fileAbs = selFile.getAbsolutePath();
if (!fileAbs.endsWith("." + EXTENSION)) {
fileAbs = fileAbs + "." + EXTENSION;
selFile = new File(fileAbs);
}
boolean shouldWrite = true;
if (selFile.exists()) {
shouldWrite = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME,
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.fileExistPrompt",
selFile.getName()), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
}
if (!shouldWrite) {
return;
}
XmlKeywordSearchList reader = XmlKeywordSearchList.getCurrent();
List<KeywordList> toWrite = new ArrayList<>();
toWrite.add(reader.getList(currentKeywordList.getName()));
final XmlKeywordSearchList exporter = new XmlKeywordSearchList(fileAbs);
boolean written = exporter.saveLists(toWrite);
if (written) {
KeywordSearchUtil.displayDialog(FEATURE_NAME,
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.kwListExportedMsg"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
}
}
}//GEN-LAST:event_exportButtonActionPerformed
private void ingestMessagesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ingestMessagesCheckboxActionPerformed
currentKeywordList.setIngestMessages(ingestMessagesCheckbox.isSelected());
XmlKeywordSearchList updater = XmlKeywordSearchList.getCurrent();
updater.addList(currentKeywordList);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_ingestMessagesCheckboxActionPerformed
private void deleteListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteListButtonActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_deleteListButtonActionPerformed
private void newKeywordsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newKeywordsButtonActionPerformed
String keywordsToRedisplay = "";
private boolean addKeywordsAction(String existingKeywords, boolean isLiteral, boolean isWholeWord) {
String keywordsToRedisplay = existingKeywords;
AddKeywordsDialog dialog = new AddKeywordsDialog();
int goodCount;
int dupeCount;
int goodCount = 0;
int dupeCount = 0;
int badCount = 1; // Default to 1 so we enter the loop the first time
while(badCount > 0){
dialog.setInitialKeywordList(keywordsToRedisplay);
while (badCount > 0) {
dialog.setInitialKeywordList(keywordsToRedisplay, isLiteral, isWholeWord);
dialog.display();
goodCount = 0;
@ -421,10 +148,9 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
badCount = 0;
keywordsToRedisplay = "";
if(!dialog.getKeywords().isEmpty()){
if (!dialog.getKeywords().isEmpty()) {
for(String newWord:dialog.getKeywords()){
for (String newWord : dialog.getKeywords()) {
if (newWord.isEmpty()) {
continue;
}
@ -459,30 +185,30 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
if((badCount > 0) || (dupeCount > 0)){
if ((badCount > 0) || (dupeCount > 0)) {
// Display the error counts to the user
// The add keywords dialog will pop up again if any were invalid with any
// invalid entries (valid entries and dupes will disappear)
String summary = "";
KeywordSearchUtil.DIALOG_MESSAGE_TYPE level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO;
if(goodCount > 0){
if(goodCount > 1){
if (goodCount > 0) {
if (goodCount > 1) {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordsAddedPlural.text", goodCount) + "\n";
} else {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordsAdded.text", goodCount) + "\n";
}
}
if(dupeCount > 0){
if(dupeCount > 1){
if (dupeCount > 0) {
if (dupeCount > 1) {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordDupesSkippedPlural.text", dupeCount) + "\n";
} else {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordDupesSkipped.text", dupeCount) + "\n";
}
level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN;
}
if(badCount > 0){
if(badCount > 1){
if (badCount > 0) {
if (badCount > 1) {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordErrorsPlural.text", badCount) + "\n";
} else {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordErrors.text", badCount) + "\n";
@ -496,24 +222,185 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
}
setFocusOnKeywordTextBox();
setButtonStates();
return (goodCount >= 1 && dupeCount == 0);
}
/**
* Remove one or more keywords from a keyword list.
*
* @param selectedKeywords the indices of the keywords you would like to delete
*/
private void deleteKeywordAction(int[] selectedKeywords) {
tableModel.deleteSelected(selectedKeywords);
XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
setButtonStates();
}
/**
* 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() {
listEditorPanel = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
keywordTable = new javax.swing.JTable();
ingestMessagesCheckbox = new javax.swing.JCheckBox();
keywordsLabel = new javax.swing.JLabel();
newKeywordsButton = new javax.swing.JButton();
deleteWordButton = new javax.swing.JButton();
editWordButton = new javax.swing.JButton();
setMinimumSize(new java.awt.Dimension(0, 0));
listEditorPanel.setMinimumSize(new java.awt.Dimension(0, 0));
jScrollPane1.setPreferredSize(new java.awt.Dimension(340, 300));
keywordTable.setModel(tableModel);
keywordTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
keywordTable.setGridColor(new java.awt.Color(153, 153, 153));
keywordTable.setMaximumSize(new java.awt.Dimension(30000, 30000));
keywordTable.getTableHeader().setReorderingAllowed(false);
jScrollPane1.setViewportView(keywordTable);
ingestMessagesCheckbox.setSelected(true);
ingestMessagesCheckbox.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.ingestMessagesCheckbox.text")); // NOI18N
ingestMessagesCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.ingestMessagesCheckbox.toolTipText")); // NOI18N
ingestMessagesCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
ingestMessagesCheckboxActionPerformed(evt);
}
});
keywordsLabel.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.keywordsLabel.text")); // NOI18N
newKeywordsButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/new16.png"))); // NOI18N
newKeywordsButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.newKeywordsButton.text")); // NOI18N
newKeywordsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
newKeywordsButtonActionPerformed(evt);
}
});
deleteWordButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N
deleteWordButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.deleteWordButton.text")); // NOI18N
deleteWordButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteWordButtonActionPerformed(evt);
}
});
editWordButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/edit16.png"))); // NOI18N
editWordButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.editWordButton.text")); // NOI18N
editWordButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
editWordButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout listEditorPanelLayout = new javax.swing.GroupLayout(listEditorPanel);
listEditorPanel.setLayout(listEditorPanelLayout);
listEditorPanelLayout.setHorizontalGroup(
listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addComponent(keywordsLabel)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 483, Short.MAX_VALUE)
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ingestMessagesCheckbox)
.addGroup(listEditorPanelLayout.createSequentialGroup()
.addComponent(newKeywordsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(14, 14, 14)
.addComponent(editWordButton, javax.swing.GroupLayout.PREFERRED_SIZE, 132, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(14, 14, 14)
.addComponent(deleteWordButton, javax.swing.GroupLayout.PREFERRED_SIZE, 144, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, Short.MAX_VALUE)))))
.addContainerGap())
);
listEditorPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteWordButton, editWordButton, newKeywordsButton});
listEditorPanelLayout.setVerticalGroup(
listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, listEditorPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(keywordsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 257, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(deleteWordButton)
.addComponent(newKeywordsButton)
.addComponent(editWordButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ingestMessagesCheckbox)
.addGap(9, 9, 9))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(5, 5, 5))
);
}// </editor-fold>//GEN-END:initComponents
private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteWordButtonActionPerformed
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.removeKwMsg"),
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.deleteWordButtonActionPerformed.delConfirmMsg"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
deleteKeywordAction(keywordTable.getSelectedRows());
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}
}//GEN-LAST:event_deleteWordButtonActionPerformed
private void ingestMessagesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ingestMessagesCheckboxActionPerformed
currentKeywordList.setIngestMessages(ingestMessagesCheckbox.isSelected());
XmlKeywordSearchList updater = XmlKeywordSearchList.getCurrent();
updater.addList(currentKeywordList);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_ingestMessagesCheckboxActionPerformed
private void newKeywordsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newKeywordsButtonActionPerformed
addKeywordsAction("", true, true);
}//GEN-LAST:event_newKeywordsButtonActionPerformed
private void editWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editWordButtonActionPerformed
int[] selectedKeywords = keywordTable.getSelectedRows();
if (selectedKeywords.length == 1) {
Keyword currentKeyword = currentKeywordList.getKeywords().get(selectedKeywords[0]);
if (addKeywordsAction(currentKeyword.getSearchTerm(), currentKeyword.searchTermIsLiteral(), currentKeyword.searchTermIsWholeWord())) {
deleteKeywordAction(selectedKeywords);
}
}
}//GEN-LAST:event_editWordButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel addKeywordPanel;
private javax.swing.JButton deleteListButton;
private javax.swing.JButton deleteWordButton;
private javax.swing.JButton exportButton;
private javax.swing.JButton editWordButton;
private javax.swing.JCheckBox ingestMessagesCheckbox;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel keywordOptionsLabel;
private javax.swing.JSeparator keywordOptionsSeparator;
private javax.swing.JTable keywordTable;
private javax.swing.JLabel keywordsLabel;
private javax.swing.JPanel listEditorPanel;
private javax.swing.JLabel listOptionsLabel;
private javax.swing.JSeparator listOptionsSeparator;
private javax.swing.JButton newKeywordsButton;
private javax.swing.JButton saveListButton;
// End of variables declaration//GEN-END:variables
@Override
@ -554,14 +441,6 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
currentKeywordList = list;
}
void addDeleteButtonActionPerformed(ActionListener l) {
deleteListButton.addActionListener(l);
}
void addSaveButtonActionPerformed(ActionListener l) {
saveListButton.addActionListener(l);
}
private class KeywordTableModel extends AbstractTableModel {
@Override

View File

@ -41,13 +41,18 @@
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
<Property name="dividerLocation" type="int" value="275"/>
<Property name="dividerLocation" type="int" value="300"/>
<Property name="dividerSize" type="int" value="1"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="leftPanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[287, 327]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/>
@ -57,7 +62,7 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="275" max="32767" attributes="0"/>
<EmptySpace min="0" pref="300" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
@ -82,7 +87,7 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="397" max="32767" attributes="0"/>
<EmptySpace min="0" pref="372" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import org.openide.util.NbBundle;
@ -41,68 +42,32 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
private void customizeComponents() {
listsManagementPanel.addListSelectionListener(editListPanel);
editListPanel.addDeleteButtonActionPerformed(new ActionListener() {
listsManagementPanel.addDeleteButtonActionPerformed(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.title"), NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.body"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
String toDelete = editListPanel.getCurrentKeywordList().getName();
editListPanel.setCurrentKeywordList(null);
editListPanel.setButtonStates();
XmlKeywordSearchList deleter = XmlKeywordSearchList.getCurrent();
deleter.deleteList(toDelete);
deleteAction(toDelete);
listsManagementPanel.resync();
}
}
});
editListPanel.addSaveButtonActionPerformed(new ActionListener() {
listsManagementPanel.addRenameButtonActionPerformed(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final String FEATURE_NAME = NbBundle.getMessage(this.getClass(),
"KeywordSearchGlobalListSettingsPanel.component.featureName.text");
KeywordList currentKeywordList = editListPanel.getCurrentKeywordList();
List<Keyword> keywords = currentKeywordList.getKeywords();
if (keywords.isEmpty()) {
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.keywordListEmptyErr"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
return;
}
String listName = (String) JOptionPane.showInputDialog(
null,
NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"),
FEATURE_NAME,
JOptionPane.PLAIN_MESSAGE,
null,
null,
currentKeywordList.getName());
if (listName == null || listName.trim().equals("")) {
return;
}
XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent();
if (writer.listExists(listName) && writer.getList(listName).isEditable()) {
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.noOwDefaultMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
return;
}
boolean shouldAdd = false;
if (writer.listExists(listName)) {
boolean replace = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.kwListExistMsg", listName),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
if (replace) {
shouldAdd = true;
}
} else {
shouldAdd = true;
}
if (shouldAdd) {
writer.addList(listName, keywords);
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.kwListSavedMsg", listName), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
String toDelete = editListPanel.getCurrentKeywordList().getName();
if (copyAction()) {
deleteAction(toDelete);
listsManagementPanel.resync();
}
}
});
listsManagementPanel.addCopyButtonActionPerformed(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
copyAction();
listsManagementPanel.resync();
}
});
@ -113,6 +78,69 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
mainSplitPane.repaint();
}
/**
* Delete the specified Keyword List
*
* @param toDelete - the list to delete
*/
private void deleteAction(String toDelete) {
XmlKeywordSearchList deleter = XmlKeywordSearchList.getCurrent();
deleter.deleteList(toDelete);
editListPanel.setCurrentKeywordList(null);
editListPanel.setButtonStates();
listsManagementPanel.setButtonStates();
}
/**
* Duplicates the selected keyword list, returns whether or not the keyword
* list was duplicated.
*
* @return true or false
*/
private boolean copyAction() {
boolean shouldAdd = false;
final String FEATURE_NAME = NbBundle.getMessage(this.getClass(),
"KeywordSearchGlobalListSettingsPanel.component.featureName.text");
KeywordList currentKeywordList = editListPanel.getCurrentKeywordList();
List<Keyword> keywords = new ArrayList<>();
keywords.addAll(currentKeywordList.getKeywords());
String listName = (String) JOptionPane.showInputDialog(
null,
NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"),
FEATURE_NAME,
JOptionPane.PLAIN_MESSAGE,
null,
null,
currentKeywordList.getName());
if (listName == null || listName.trim().equals("")) {
return shouldAdd;
}
XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent();
if (writer.listExists(listName) && writer.getList(listName).isEditable()) {
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.noOwDefaultMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
return shouldAdd;
}
if (writer.listExists(listName)) {
boolean replace = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.kwListExistMsg", listName),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
if (replace) {
shouldAdd = true;
}
} else {
shouldAdd = true;
}
if (shouldAdd) {
writer.addList(listName, keywords);
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.kwListSavedMsg", listName), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
}
return shouldAdd;
}
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
listsManagementPanel.addPropertyChangeListener(l);
@ -159,14 +187,16 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
rightPanel = new javax.swing.JPanel();
mainSplitPane.setBorder(null);
mainSplitPane.setDividerLocation(275);
mainSplitPane.setDividerLocation(300);
mainSplitPane.setDividerSize(1);
leftPanel.setPreferredSize(new java.awt.Dimension(287, 327));
javax.swing.GroupLayout leftPanelLayout = new javax.swing.GroupLayout(leftPanel);
leftPanel.setLayout(leftPanelLayout);
leftPanelLayout.setHorizontalGroup(
leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 275, Short.MAX_VALUE)
.addGap(0, 300, Short.MAX_VALUE)
);
leftPanelLayout.setVerticalGroup(
leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -181,7 +211,7 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
rightPanel.setLayout(rightPanelLayout);
rightPanelLayout.setHorizontalGroup(
rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 397, Short.MAX_VALUE)
.addGap(0, 372, Short.MAX_VALUE)
);
rightPanelLayout.setVerticalGroup(
rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

View File

@ -21,20 +21,32 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="1" pref="0" max="32767" attributes="1"/>
<Group type="102" attributes="0">
<Component id="jScrollPane1" pref="0" max="32767" attributes="1"/>
<Component id="keywordListsLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="keywordListsLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="newListButton" min="-2" pref="114" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="importButton" min="-2" pref="126" max="-2" attributes="0"/>
<Component id="newListButton" linkSize="4" min="-2" pref="85" max="-2" attributes="0"/>
<Component id="deleteListButton" linkSize="4" alignment="0" pref="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="renameListButton" linkSize="4" pref="75" max="32767" attributes="0"/>
<Component id="importButton" linkSize="4" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="copyListButton" linkSize="4" pref="0" max="32767" attributes="0"/>
<EmptySpace min="0" pref="1" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="exportButton" linkSize="4" min="-2" pref="79" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
@ -44,14 +56,21 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="keywordListsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="355" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="316" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="newListButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="importButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="newListButton" linkSize="5" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="renameListButton" linkSize="5" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="copyListButton" linkSize="5" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="importButton" linkSize="5" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="exportButton" linkSize="5" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteListButton" linkSize="5" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
@ -94,6 +113,10 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="GlobalListsManagementPanel.newListButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="iconTextGap" type="int" value="2"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newListButtonActionPerformed"/>
@ -107,6 +130,10 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="GlobalListsManagementPanel.importButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="iconTextGap" type="int" value="2"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="importButtonActionPerformed"/>
@ -119,5 +146,73 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="exportButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/export16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="GlobalListsManagementPanel.exportButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="iconTextGap" type="int" value="2"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="exportButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="copyListButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/add16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="GlobalListsManagementPanel.copyListButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="iconTextGap" type="int" value="2"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="copyListButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="deleteListButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/delete16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="GlobalListsManagementPanel.deleteListButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="iconTextGap" type="int" value="2"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteListButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="renameListButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/edit16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="GlobalListsManagementPanel.renameListButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="iconTextGap" type="int" value="2"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="renameListButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,7 +18,11 @@
*/
package org.sleuthkit.autopsy.keywordsearch;
import java.awt.EventQueue;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@ -31,7 +35,7 @@ import javax.swing.table.AbstractTableModel;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
/**
* A panel to manage all keyword lists created/imported in Autopsy.
@ -39,8 +43,6 @@ import org.sleuthkit.autopsy.coreutils.Logger;
class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPanel {
private static final long serialVersionUID = 1L;
private final Logger logger = Logger.getLogger(GlobalListsManagementPanel.class.getName());
private final KeywordListTableModel tableModel;
private final org.sleuthkit.autopsy.keywordsearch.GlobalListSettingsPanel globalListSettingsPanel;
@ -56,122 +58,61 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
listsTable.setTableHeader(null);
listsTable.setShowHorizontalLines(false);
listsTable.setShowVerticalLines(false);
exportButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.exportToFile"));
copyListButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.saveCurrentWIthNewNameToolTip"));
listsTable.getParent().setBackground(listsTable.getBackground());
listsTable.setCellSelectionEnabled(false);
listsTable.setRowSelectionAllowed(true);
tableModel.resync();
setButtonStates();
listsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
globalListSettingsPanel.setFocusOnKeywordTextBox();
setButtonStates();
}
});
/*
* XmlKeywordSearchList.getCurrent().addPropertyChangeListener(new
* PropertyChangeListener() {
*
* @Override public void propertyChange(PropertyChangeEvent evt) { if
* (evt.getPropertyName().equals(XmlKeywordSearchList.ListsEvt.LIST_ADDED.toString()))
* { tableModel.resync(); for(int i = 0; i<listsTable.getRowCount();
* i++) { String name = (String) listsTable.getValueAt(i, 0);
* if(((String) evt.getNewValue()).equals(name)) {
* listsTable.getSelectionModel().setSelectionInterval(i, i); } } } else
* if
* (evt.getPropertyName().equals(XmlKeywordSearchList.ListsEvt.LIST_DELETED.toString()))
* { tableModel.resync(); if(listsTable.getRowCount() > 0) {
* listsTable.getSelectionModel().setSelectionInterval(0, 0); } else {
* listsTable.getSelectionModel().clearSelection(); } } } });
*/
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(() -> {
globalListSettingsPanel.setFocusOnKeywordTextBox();
setButtonStates();
});
}
}
});
}
void addDeleteButtonActionPerformed(ActionListener l) {
deleteListButton.addActionListener(l);
}
void addRenameButtonActionPerformed(ActionListener l) {
renameListButton.addActionListener(l);
}
void addCopyButtonActionPerformed(ActionListener l) {
copyListButton.addActionListener(l);
}
/**
* 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.
* Opens the dialogue for creating a new keyword list and adds it to the table.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
listsTable = new javax.swing.JTable();
newListButton = new javax.swing.JButton();
importButton = new javax.swing.JButton();
keywordListsLabel = new javax.swing.JLabel();
setMinimumSize(new java.awt.Dimension(250, 0));
listsTable.setModel(tableModel);
listsTable.setMaximumSize(new java.awt.Dimension(30000, 30000));
listsTable.setShowHorizontalLines(false);
listsTable.setShowVerticalLines(false);
listsTable.getTableHeader().setReorderingAllowed(false);
listsTable.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
listsTableKeyPressed(evt);
}
});
jScrollPane1.setViewportView(listsTable);
newListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/new16.png"))); // NOI18N
newListButton.setText(org.openide.util.NbBundle.getMessage(GlobalListsManagementPanel.class, "GlobalListsManagementPanel.newListButton.text")); // NOI18N
newListButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
newListButtonActionPerformed(evt);
}
});
importButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/import16.png"))); // NOI18N
importButton.setText(org.openide.util.NbBundle.getMessage(GlobalListsManagementPanel.class, "GlobalListsManagementPanel.importButton.text")); // NOI18N
importButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
importButtonActionPerformed(evt);
}
});
keywordListsLabel.setText(org.openide.util.NbBundle.getMessage(GlobalListsManagementPanel.class, "GlobalListsManagementPanel.keywordListsLabel.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)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(keywordListsLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(newListButton, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(importButton, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(keywordListsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 355, Short.MAX_VALUE)
.addGap(5, 5, 5)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newListButton)
.addComponent(importButton))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void newListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newListButtonActionPerformed
private void newKeywordListAction() {
XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent();
String listName = (String) JOptionPane.showInputDialog(null, NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"),
NbBundle.getMessage(this.getClass(), "KeywordSearch.newKeywordListMsg"), JOptionPane.PLAIN_MESSAGE, null, null, "");
if (listName == null || listName.trim().equals("")) {
String listName = "";
listName = (String) JOptionPane.showInputDialog(null, NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"),
NbBundle.getMessage(this.getClass(), "KeywordSearch.newKeywordListMsg"), JOptionPane.PLAIN_MESSAGE, null, null, listName);
if (listName == null || listName.trim().isEmpty()) {
return;
}
boolean shouldAdd = false;
@ -197,8 +138,9 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
shouldAdd = true;
}
if (shouldAdd) {
writer.addList(listName, new ArrayList<Keyword>());
writer.addList(listName, new ArrayList<>());
}
tableModel.resync();
//This loop selects the recently ADDED keywordslist in the JTable
@ -207,6 +149,178 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
listsTable.getSelectionModel().addSelectionInterval(i, i);
}
}
}
/**
* Enables and disables buttons on this panel based on the current state.
*/
void setButtonStates() {
boolean isIngestRunning = IngestManager.getInstance().isIngestRunning();
boolean isListSelected = !listsTable.getSelectionModel().isSelectionEmpty();
boolean canEditList = isListSelected && !isIngestRunning;
// items that only need ingest to not be running
importButton.setEnabled(!isIngestRunning);
// items that need an unlocked list w/out ingest running
deleteListButton.setEnabled(canEditList);
renameListButton.setEnabled(canEditList);
// items that only need a selected list
copyListButton.setEnabled(isListSelected);
exportButton.setEnabled(isListSelected);
}
/**
* 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();
listsTable = new javax.swing.JTable();
newListButton = new javax.swing.JButton();
importButton = new javax.swing.JButton();
keywordListsLabel = new javax.swing.JLabel();
exportButton = new javax.swing.JButton();
copyListButton = new javax.swing.JButton();
deleteListButton = new javax.swing.JButton();
renameListButton = new javax.swing.JButton();
setMinimumSize(new java.awt.Dimension(250, 0));
listsTable.setModel(tableModel);
listsTable.setMaximumSize(new java.awt.Dimension(30000, 30000));
listsTable.setShowHorizontalLines(false);
listsTable.setShowVerticalLines(false);
listsTable.getTableHeader().setReorderingAllowed(false);
listsTable.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
listsTableKeyPressed(evt);
}
});
jScrollPane1.setViewportView(listsTable);
newListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/new16.png"))); // NOI18N
newListButton.setText(org.openide.util.NbBundle.getMessage(GlobalListsManagementPanel.class, "GlobalListsManagementPanel.newListButton.text")); // NOI18N
newListButton.setIconTextGap(2);
newListButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
newListButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
newListButtonActionPerformed(evt);
}
});
importButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/import16.png"))); // NOI18N
importButton.setText(org.openide.util.NbBundle.getMessage(GlobalListsManagementPanel.class, "GlobalListsManagementPanel.importButton.text")); // NOI18N
importButton.setIconTextGap(2);
importButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
importButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
importButtonActionPerformed(evt);
}
});
keywordListsLabel.setText(org.openide.util.NbBundle.getMessage(GlobalListsManagementPanel.class, "GlobalListsManagementPanel.keywordListsLabel.text")); // NOI18N
exportButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/export16.png"))); // NOI18N
exportButton.setText(org.openide.util.NbBundle.getMessage(GlobalListsManagementPanel.class, "GlobalListsManagementPanel.exportButton.text")); // NOI18N
exportButton.setIconTextGap(2);
exportButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
exportButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
exportButtonActionPerformed(evt);
}
});
copyListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/add16.png"))); // NOI18N
copyListButton.setText(org.openide.util.NbBundle.getMessage(GlobalListsManagementPanel.class, "GlobalListsManagementPanel.copyListButton.text")); // NOI18N
copyListButton.setIconTextGap(2);
copyListButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
copyListButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
copyListButtonActionPerformed(evt);
}
});
deleteListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N
deleteListButton.setText(org.openide.util.NbBundle.getMessage(GlobalListsManagementPanel.class, "GlobalListsManagementPanel.deleteListButton.text")); // NOI18N
deleteListButton.setIconTextGap(2);
deleteListButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
deleteListButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteListButtonActionPerformed(evt);
}
});
renameListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/edit16.png"))); // NOI18N
renameListButton.setText(org.openide.util.NbBundle.getMessage(GlobalListsManagementPanel.class, "GlobalListsManagementPanel.renameListButton.text")); // NOI18N
renameListButton.setIconTextGap(2);
renameListButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
renameListButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
renameListButtonActionPerformed(evt);
}
});
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)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(keywordListsLabel)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(newListButton, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(deleteListButton, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE))
.addGap(12, 12, 12)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(renameListButton, javax.swing.GroupLayout.PREFERRED_SIZE, 75, Short.MAX_VALUE)
.addComponent(importButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(12, 12, 12)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(copyListButton, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE)
.addGap(0, 1, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(exportButton, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)))))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {copyListButton, deleteListButton, exportButton, importButton, newListButton, renameListButton});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(keywordListsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 316, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newListButton)
.addComponent(renameListButton)
.addComponent(copyListButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(importButton)
.addComponent(exportButton)
.addComponent(deleteListButton))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {copyListButton, deleteListButton, exportButton, importButton, newListButton, renameListButton});
}// </editor-fold>//GEN-END:initComponents
private void newListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newListButtonActionPerformed
newKeywordListAction();
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
globalListSettingsPanel.setFocusOnKeywordTextBox();
}//GEN-LAST:event_newListButtonActionPerformed
@ -251,7 +365,7 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
}
List<KeywordList> toImport = reader.getListsL();
List<KeywordList> toImportConfirmed = new ArrayList<KeywordList>();
List<KeywordList> toImportConfirmed = new ArrayList<>();
final XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent();
@ -321,12 +435,81 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
tableModel.resync();
}//GEN-LAST:event_listsTableKeyPressed
private void exportButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportButtonActionPerformed
final String FEATURE_NAME = NbBundle.getMessage(this.getClass(),
"KeywordSearchEditListPanel.exportButtonAction.featureName.text");
JFileChooser chooser = new JFileChooser();
final String EXTENSION = "xml"; //NON-NLS
FileNameExtensionFilter filter = new FileNameExtensionFilter(
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.fileFilterLabel"), EXTENSION);
chooser.setFileFilter(filter);
String listName = listsTable.getValueAt(listsTable.getSelectedRow(), 0).toString();
chooser.setSelectedFile(new File(listName));
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
int returnVal = chooser.showSaveDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File selFile = chooser.getSelectedFile();
if (selFile == null) {
return;
}
//force append extension if not given
String fileAbs = selFile.getAbsolutePath();
if (!fileAbs.endsWith("." + EXTENSION)) {
fileAbs = fileAbs + "." + EXTENSION;
selFile = new File(fileAbs);
}
boolean shouldWrite = true;
if (selFile.exists()) {
shouldWrite = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME,
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.fileExistPrompt",
selFile.getName()), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
}
if (!shouldWrite) {
return;
}
XmlKeywordSearchList reader = XmlKeywordSearchList.getCurrent();
List<KeywordList> toWrite = new ArrayList<>();
toWrite.add(reader.getList(listName));
final XmlKeywordSearchList exporter = new XmlKeywordSearchList(fileAbs);
boolean written = exporter.saveLists(toWrite);
if (written) {
KeywordSearchUtil.displayDialog(FEATURE_NAME,
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.kwListExportedMsg"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
}
}
}//GEN-LAST:event_exportButtonActionPerformed
private void copyListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyListButtonActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_copyListButtonActionPerformed
private void deleteListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteListButtonActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_deleteListButtonActionPerformed
private void renameListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_renameListButtonActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_renameListButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton copyListButton;
private javax.swing.JButton deleteListButton;
private javax.swing.JButton exportButton;
private javax.swing.JButton importButton;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel keywordListsLabel;
private javax.swing.JTable listsTable;
private javax.swing.JButton newListButton;
private javax.swing.JButton renameListButton;
// End of variables declaration//GEN-END:variables
@Override
@ -345,6 +528,8 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
private class KeywordListTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private final XmlKeywordSearchList listsHandle = XmlKeywordSearchList.getCurrent();
@Override

View File

@ -27,7 +27,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.stream.Collectors;
import javax.annotation.concurrent.GuardedBy;
@ -244,7 +243,6 @@ class HighlightedText implements IndexedText {
@Override
public boolean hasNextPage() {
return getIndexOfCurrentPage() < pages.size() - 1;
}
@Override
@ -255,7 +253,7 @@ class HighlightedText implements IndexedText {
@Override
public int nextPage() {
if (hasNextPage()) {
currentPage = Iterators.get(pages.iterator(),getIndexOfCurrentPage() + 1);
currentPage = Iterators.get(pages.iterator(), getIndexOfCurrentPage() + 1);
return currentPage;
} else {
throw new IllegalStateException("No next page.");
@ -265,7 +263,7 @@ class HighlightedText implements IndexedText {
@Override
public int previousPage() {
if (hasPreviousPage()) {
currentPage = Iterators.get(pages.iterator(),getIndexOfCurrentPage()-1);
currentPage = Iterators.get(pages.iterator(), getIndexOfCurrentPage() - 1);
return currentPage;
} else {
throw new IllegalStateException("No previous page.");
@ -387,7 +385,7 @@ class HighlightedText implements IndexedText {
highlightedContent = insertAnchors(highlightedContent);
return "<html><pre>" + highlightedContent + "</pre></html>"; //NON-NLS
} catch (Exception ex) {
} catch (TskCoreException | KeywordSearchModuleException | NoOpenCoreException ex) {
logger.log(Level.SEVERE, "Error getting highlighted text for " + objectId, ex); //NON-NLS
return NbBundle.getMessage(this.getClass(), "HighlightedMatchesSource.getMarkup.queryFailedMsg");
}
@ -453,8 +451,8 @@ class HighlightedText implements IndexedText {
//we also need to escape the keyword so that it matches the escpared text
final String escapedKeyword = StringEscapeUtils.escapeHtml(keyword);
int textOffset = 0;
int hitOffset;
while ((hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset)) != -1) {
int hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset);
while (hitOffset != -1) {
// Append the portion of text up to (but not including) the hit.
highlightedText.append(text.substring(textOffset, hitOffset));
// Add in the highlighting around the keyword.
@ -464,6 +462,8 @@ class HighlightedText implements IndexedText {
// Advance the text offset past the keyword.
textOffset = hitOffset + escapedKeyword.length();
hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset);
}
// Append the remainder of text field
highlightedText.append(text.substring(textOffset, text.length()));
@ -487,22 +487,21 @@ class HighlightedText implements IndexedText {
* @return
*/
private String insertAnchors(String searchableContent) {
int searchOffset = 0;
int index = -1;
StringBuilder buf = new StringBuilder(searchableContent);
final String searchToken = HIGHLIGHT_PRE;
final int indexSearchTokLen = searchToken.length();
final String insertPre = "<a name='" + ANCHOR_PREFIX; //NON-NLS
final String insertPost = "'></a>"; //NON-NLS
int count = 0;
while ((index = buf.indexOf(searchToken, searchOffset)) >= 0) {
int searchOffset = 0;
int index = buf.indexOf(searchToken, searchOffset);
while (index >= 0) {
String insertString = insertPre + Integer.toString(count + 1) + insertPost;
int insertStringLen = insertString.length();
buf.insert(index, insertString);
searchOffset = index + indexSearchTokLen + insertStringLen; //next offset past this anchor
++count;
index = buf.indexOf(searchToken, searchOffset);
}
//store total hits for this page, now that we know it

View File

@ -20,11 +20,13 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.sleuthkit.autopsy.casemodule.Case;
@ -101,8 +103,8 @@ class IndexFinder {
/**
* Creates a copy of an existing Solr index.
*
* @param indexToUpgrade Index object to create a copy of
* @param context AutopsyService.CaseContext object
* @param indexToUpgrade Index object to create a copy of
* @param context AutopsyService.CaseContext object
*
* @return The absolute path of the new Solr index directory
*
@ -120,20 +122,31 @@ class IndexFinder {
List<File> contents = getAllContentsInFolder(targetDirPath.getAbsolutePath());
if (!contents.isEmpty()) {
// target directory is not empty
throw new AutopsyService.AutopsyServiceException("Directory to store the upgraded index must be empty " + targetDirPath.getAbsolutePath());
try {
FileUtils.deleteDirectory(targetDirPath.getParentFile()); //We don't want partial copies
} catch (IOException | IllegalArgumentException deleteEx) {
throw new AutopsyService.AutopsyServiceException("Failed to delete existing directory to store the upgraded index " + targetDirPath.getAbsolutePath() + "which was not empty", deleteEx);
}
logger.log(Level.WARNING, String.format("Directory %s existed with contents and was deleted so the upgrade could proceed", indexFolderName));
}
}
targetDirPath.mkdirs();
FileUtils.copyDirectory(new File(indexToUpgrade.getIndexPath()), targetDirPath);
return targetDirPath.getAbsolutePath();
} catch (AutopsyService.AutopsyServiceException | IOException ex) {
try {
Path targetDirPath = Paths.get(context.getCase().getModuleDirectory(), KWS_OUTPUT_FOLDER_NAME, KWS_DATA_FOLDER_NAME, indexFolderName); //NON-NLS
FileUtils.deleteDirectory(targetDirPath.toFile()); //We don't want partial copies
} catch (IOException | IllegalArgumentException deleteEx) {
logger.log(Level.SEVERE, String.format("Failed to delete %s when upgrade cancelled", indexFolderName), deleteEx);
}
throw new AutopsyService.AutopsyServiceException("Error occurred while creating a copy of keyword search index", ex);
}
}
/**
* Find existing Solr 4 Schema 1.8 index directory location for the case. This is done via
* subdirectory search of all existing
* Find existing Solr 4 Schema 1.8 index directory location for the case.
* This is done via subdirectory search of all existing
* "ModuleOutput/node_name/keywordsearch/data/" folders.
*
* @param theCase the case to get index dir for
@ -146,8 +159,9 @@ class IndexFinder {
// multi user cases contain a subfolder for each node that participated in case ingest or review.
// Any one (but only one!) of those subfolders may contain the actual index.
/*
* NOTE: the following path is an example of valid Solr 4 Schema 1.8 multi-user index
* path: X:\Case\ingest1\ModuleOutput\keywordsearch\data\index
* NOTE: the following path is an example of valid Solr 4 Schema 1.8
* multi-user index path:
* X:\Case\ingest1\ModuleOutput\keywordsearch\data\index
*/
// get a list of all folder's contents
@ -169,8 +183,8 @@ class IndexFinder {
} else {
// single user case
/*
* NOTE: the following path is valid single user Solr 4 Schema 1.8 index
* path: X:\Case\ModuleOutput\keywordsearch\data\index
* NOTE: the following path is valid single user Solr 4 Schema 1.8
* index path: X:\Case\ModuleOutput\keywordsearch\data\index
*/
File path = Paths.get(theCase.getModuleDirectory(), KWS_OUTPUT_FOLDER_NAME, KWS_DATA_FOLDER_NAME, INDEX_FOLDER_NAME).toFile(); //NON-NLS
// must be a non-empty index directory

View File

@ -186,7 +186,7 @@ class IndexUpgrader {
*
* @return The new Solr index version.
*/
private int upgradeSolrIndexVersion5to6(int currentIndexVersion, String solr5IndexPath, String tempResultsDir, UserCancelledProcessTerminator terminatior) throws AutopsyService.AutopsyServiceException, SecurityException, IOException {
private int upgradeSolrIndexVersion5to6(int currentIndexVersion, String solr5IndexPath, String tempResultsDir, UserCancelledProcessTerminator terminator) throws AutopsyService.AutopsyServiceException, SecurityException, IOException {
if (currentIndexVersion != 5) {
return currentIndexVersion;
}
@ -218,7 +218,11 @@ class IndexUpgrader {
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
processBuilder.redirectOutput(new File(outputFileFullPath));
processBuilder.redirectError(new File(errFileFullPath));
ExecUtil.execute(processBuilder, terminatior);
try {
ExecUtil.execute(processBuilder, terminator);
} catch (SecurityException | IOException ex) {
throw new AutopsyService.AutopsyServiceException("Error executing Solr 4 to Solr 5 upgrade tool");
}
// alternatively can execute lucene upgrade command from the folder where lucene jars are located
// java -cp ".;lucene-core-6.2.1.jar;lucene-backward-codecs-6.2.1.jar;lucene-codecs-6.2.1.jar;lucene-analyzers-common-6.2.1.jar" org.apache.lucene.index.IndexUpgrader \path\to\index

View File

@ -47,9 +47,7 @@ class KeywordSearchUtil {
return query;
}
StringBuilder sb = new StringBuilder();
sb.append("\"").append(query).append("\"");
return sb.toString();
return "\""+query+"\"";
}
/**

View File

@ -27,10 +27,12 @@ import java.util.logging.Level;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrRequest.METHOD;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.CursorMarkParams;
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.Version;
@ -38,6 +40,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException;
/**
@ -47,14 +50,13 @@ import org.sleuthkit.datamodel.TskException;
class LuceneQuery implements KeywordSearchQuery {
private static final Logger logger = Logger.getLogger(LuceneQuery.class.getName());
private final String keywordString; //original unescaped query
private String keywordStringEscaped;
private boolean isEscaped;
private Keyword originalKeyword = null;
private KeywordList keywordList = null;
private final Keyword originalKeyword ;
private final KeywordList keywordList ;
private final List<KeywordQueryFilter> filters = new ArrayList<>();
private String field = null;
private static final int MAX_RESULTS = 20000;
private static final int MAX_RESULTS_PER_CURSOR_MARK = 512;
static final int SNIPPET_LENGTH = 50;
static final String HIGHLIGHT_FIELD = Server.Schema.TEXT.toString();
@ -65,14 +67,10 @@ class LuceneQuery implements KeywordSearchQuery {
*
* @param keyword
*/
public LuceneQuery(KeywordList keywordList, Keyword keyword) {
LuceneQuery(KeywordList keywordList, Keyword keyword) {
this.keywordList = keywordList;
this.originalKeyword = keyword;
// @@@ BC: Long-term, we should try to get rid of this string and use only the
// keyword object. Refactoring did not make its way through this yet.
this.keywordString = keyword.getSearchTerm();
this.keywordStringEscaped = this.keywordString;
this.keywordStringEscaped = this.originalKeyword.getSearchTerm();
}
@Override
@ -89,12 +87,12 @@ class LuceneQuery implements KeywordSearchQuery {
public void setSubstringQuery() {
// Note that this is not a full substring search. Normally substring
// searches will be done with TermComponentQuery objects instead.
keywordStringEscaped = keywordStringEscaped + "*";
keywordStringEscaped += "*";
}
@Override
public void escape() {
keywordStringEscaped = KeywordSearchUtil.escapeLuceneQuery(keywordString);
keywordStringEscaped = KeywordSearchUtil.escapeLuceneQuery(originalKeyword.getSearchTerm());
isEscaped = true;
}
@ -115,22 +113,82 @@ class LuceneQuery implements KeywordSearchQuery {
@Override
public String getQueryString() {
return this.keywordString;
return this.originalKeyword.getSearchTerm();
}
@Override
public KeywordList getKeywordList() {
return keywordList;
}
@Override
public QueryResults performQuery() throws KeywordSearchModuleException, NoOpenCoreException {
QueryResults results = new QueryResults(this, keywordList);
final Server solrServer = KeywordSearch.getServer();
double indexSchemaVersion = NumberUtils.toDouble(solrServer.getIndexInfo().getSchemaVersion());
SolrQuery solrQuery = createAndConfigureSolrQuery(KeywordSearchSettings.getShowSnippets());
final String strippedQueryString = StringUtils.strip(getQueryString(), "\"");
String cursorMark = CursorMarkParams.CURSOR_MARK_START;
boolean allResultsProcessed = false;
List<KeywordHit> matches = new ArrayList<>();
while (!allResultsProcessed) {
solrQuery.set(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);
QueryResponse response = solrServer.query(solrQuery, SolrRequest.METHOD.POST);
SolrDocumentList resultList = response.getResults();
// objectId_chunk -> "text" -> List of previews
Map<String, Map<String, List<String>>> highlightResponse = response.getHighlighting();
for (SolrDocument resultDoc : resultList) {
try {
/*
* for each result doc, check that the first occurence of
* that term is before the window. if all the ocurences
* start within the window, don't record them for this
* chunk, they will get picked up in the next one.
*/
final String docId = resultDoc.getFieldValue(Server.Schema.ID.toString()).toString();
final Integer chunkSize = (Integer) resultDoc.getFieldValue(Server.Schema.CHUNK_SIZE.toString());
final Collection<Object> content = resultDoc.getFieldValues(Server.Schema.CONTENT_STR.toString());
if (indexSchemaVersion < 2.0) {
//old schema versions don't support chunk_size or the content_str fields, so just accept hits
matches.add(createKeywordtHit(highlightResponse, docId));
} else {
//check against file name and actual content seperately.
for (Object content_obj : content) {
String content_str = (String) content_obj;
//for new schemas, check that the hit is before the chunk/window boundary.
int firstOccurence = StringUtils.indexOfIgnoreCase(content_str, strippedQueryString);
//there is no chunksize field for "parent" entries in the index
if (chunkSize == null || chunkSize == 0 || (firstOccurence > -1 && firstOccurence < chunkSize)) {
matches.add(createKeywordtHit(highlightResponse, docId));
}
}
}
} catch (TskException ex) {
throw new KeywordSearchModuleException(ex);
}
}
String nextCursorMark = response.getNextCursorMark();
if (cursorMark.equals(nextCursorMark)) {
allResultsProcessed = true;
}
cursorMark = nextCursorMark;
}
QueryResults results = new QueryResults(this);
//in case of single term literal query there is only 1 term
boolean showSnippets = KeywordSearchSettings.getShowSnippets();
results.addResult(new Keyword(keywordString, true), performLuceneQuery(showSnippets));
results.addResult(new Keyword(originalKeyword.getSearchTerm(), true), matches);
return results;
}
@Override
public boolean validate() {
return keywordString != null && !keywordString.equals("");
return StringUtils.isNotBlank(originalKeyword.getSearchTerm());
}
@Override
@ -143,7 +201,7 @@ class LuceneQuery implements KeywordSearchQuery {
try {
bba = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
writeResult = new KeywordCachedArtifact(bba);
} catch (Exception e) {
} catch (TskCoreException e) {
logger.log(Level.WARNING, "Error adding bb artifact for keyword hit", e); //NON-NLS
return null;
}
@ -152,13 +210,10 @@ class LuceneQuery implements KeywordSearchQuery {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW, MODULE_NAME, snippet));
}
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, foundKeyword.getSearchTerm()));
if ((listName != null) && (listName.equals("") == false)) {
if (StringUtils.isNotBlank(listName)) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, listName));
}
//bogus - workaround the dir tree table issue
//attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID(), MODULE_NAME, "", ""));
//selector
if (originalKeyword != null) {
BlackboardAttribute.ATTRIBUTE_TYPE selType = originalKeyword.getArtifactAttributeType();
if (selType != null) {
@ -180,81 +235,14 @@ class LuceneQuery implements KeywordSearchQuery {
bba.addAttributes(attributes); //write out to bb
writeResult.add(attributes);
return writeResult;
} catch (TskException e) {
} catch (TskCoreException e) {
logger.log(Level.WARNING, "Error adding bb attributes to artifact", e); //NON-NLS
return null;
}
return null;
}
/**
* Perform the query and return results of unique files.
*
* @param snippets True if results should have a snippet
*
* @return list of ContentHit objects. One per file with hit (ignores
* multiple hits of the word in the same doc)
*
* @throws NoOpenCoreException
*/
private List<KeywordHit> performLuceneQuery(boolean snippets) throws KeywordSearchModuleException, NoOpenCoreException {
List<KeywordHit> matches = new ArrayList<>();
boolean allMatchesFetched = false;
final Server solrServer = KeywordSearch.getServer();
SolrQuery q = createAndConfigureSolrQuery(snippets);
QueryResponse response;
SolrDocumentList resultList;
Map<String, Map<String, List<String>>> highlightResponse;
response = solrServer.query(q, METHOD.POST);
resultList = response.getResults();
// objectId_chunk -> "text" -> List of previews
highlightResponse = response.getHighlighting();
final String strippedQueryString = StringUtils.strip(getQueryString(), "\"");
// cycle through results in sets of MAX_RESULTS
for (int start = 0; !allMatchesFetched; start = start + MAX_RESULTS) {
q.setStart(start);
allMatchesFetched = start + MAX_RESULTS >= resultList.getNumFound();
for (SolrDocument resultDoc : resultList) {
try {
/* for each result, check that the first occurence of that
* term is before the window. if all the ocurences start
* within the window, don't record them for this chunk, they
* will get picked up in the next one. */
final String docId = resultDoc.getFieldValue(Server.Schema.ID.toString()).toString();
final Integer chunkSize = (Integer) resultDoc.getFieldValue(Server.Schema.CHUNK_SIZE.toString());
final Collection<Object> content = resultDoc.getFieldValues(Server.Schema.CONTENT_STR.toString());
double indexSchemaVersion = NumberUtils.toDouble(KeywordSearch.getServer().getIndexInfo().getSchemaVersion());
if (indexSchemaVersion < 2.0) {
//old schema versions don't support chunk_size or the content_str fields, so just accept hits
matches.add(createKeywordtHit(highlightResponse, docId));
} else {
//check against file name and actual content seperately.
for (Object content_obj : content) {
String content_str = (String) content_obj;
//for new schemas, check that the hit is before the chunk/window boundary.
int firstOccurence = StringUtils.indexOfIgnoreCase(content_str, strippedQueryString);
//there is no chunksize field for "parent" entries in the index
if (chunkSize == null || chunkSize == 0 || (firstOccurence > -1 && firstOccurence < chunkSize)) {
matches.add(createKeywordtHit(highlightResponse, docId));
}
}
}
} catch (TskException ex) {
return matches;
}
}
}
return matches;
}
/**
/*
* Create the query object for the stored keyword
*
* @param snippets True if query should request snippets
@ -265,51 +253,59 @@ class LuceneQuery implements KeywordSearchQuery {
SolrQuery q = new SolrQuery();
q.setShowDebugInfo(DEBUG); //debug
// Wrap the query string in quotes if this is a literal search term.
String theQueryStr = originalKeyword.searchTermIsLiteral()
String queryStr = originalKeyword.searchTermIsLiteral()
? KeywordSearchUtil.quoteQuery(keywordStringEscaped) : keywordStringEscaped;
// Run the query against an optional alternative field.
if (field != null) {
//use the optional field
StringBuilder sb = new StringBuilder();
sb.append(field).append(":").append(theQueryStr);
theQueryStr = sb.toString();
queryStr = field + ":" + queryStr;
}
q.setQuery(theQueryStr);
q.setRows(MAX_RESULTS);
q.setQuery(queryStr);
q.setRows(MAX_RESULTS_PER_CURSOR_MARK);
// Setting the sort order is necessary for cursor based paging to work.
q.setSort(SolrQuery.SortClause.asc(Server.Schema.ID.toString()));
q.setFields(Server.Schema.ID.toString(),
Server.Schema.CHUNK_SIZE.toString(),
Server.Schema.CONTENT_STR.toString());
q.addSort(Server.Schema.ID.toString(), SolrQuery.ORDER.asc);
for (KeywordQueryFilter filter : filters) {
q.addFilterQuery(filter.toString());
}
if (snippets) {
q.addHighlightField(Server.Schema.TEXT.toString());
//q.setHighlightSimplePre("&laquo;"); //original highlighter only
//q.setHighlightSimplePost("&raquo;"); //original highlighter only
q.setHighlightSnippets(1);
q.setHighlightFragsize(SNIPPET_LENGTH);
//tune the highlighter
q.setParam("hl.useFastVectorHighlighter", "on"); //fast highlighter scales better than standard one NON-NLS
q.setParam("hl.tag.pre", "&laquo;"); //makes sense for FastVectorHighlighter only NON-NLS
q.setParam("hl.tag.post", "&laquo;"); //makes sense for FastVectorHighlighter only NON-NLS
q.setParam("hl.fragListBuilder", "simple"); //makes sense for FastVectorHighlighter only NON-NLS
//Solr bug if fragCharSize is smaller than Query string, StringIndexOutOfBoundsException is thrown.
q.setParam("hl.fragCharSize", Integer.toString(theQueryStr.length())); //makes sense for FastVectorHighlighter only NON-NLS
//docs says makes sense for the original Highlighter only, but not really
//analyze all content SLOW! consider lowering
q.setParam("hl.maxAnalyzedChars", Server.HL_ANALYZE_CHARS_UNLIMITED); //NON-NLS
configurwQueryForHighlighting(q);
}
return q;
}
/**
* Configure the given query to return highlighting information. Must be
* called after setQuery() has been invoked on q.
*
* @param q The SolrQuery to configure.
*/
private static void configurwQueryForHighlighting(SolrQuery q) {
q.addHighlightField(HIGHLIGHT_FIELD);
q.setHighlightSnippets(1);
q.setHighlightFragsize(SNIPPET_LENGTH);
//tune the highlighter
q.setParam("hl.useFastVectorHighlighter", "on"); //fast highlighter scales better than standard one NON-NLS
q.setParam("hl.tag.pre", "&laquo;"); //makes sense for FastVectorHighlighter only NON-NLS
q.setParam("hl.tag.post", "&laquo;"); //makes sense for FastVectorHighlighter only NON-NLS
q.setParam("hl.fragListBuilder", "simple"); //makes sense for FastVectorHighlighter only NON-NLS
//Solr bug if fragCharSize is smaller than Query string, StringIndexOutOfBoundsException is thrown.
q.setParam("hl.fragCharSize", Integer.toString(q.getQuery().length())); //makes sense for FastVectorHighlighter only NON-NLS
//docs says makes sense for the original Highlighter only, but not really
//analyze all content SLOW! consider lowering
q.setParam("hl.maxAnalyzedChars", Server.HL_ANALYZE_CHARS_UNLIMITED); //NON-NLS
}
private KeywordHit createKeywordtHit(Map<String, Map<String, List<String>>> highlightResponse, String docId) throws TskException {
/**
* Get the first snippet from the document if keyword search is
@ -324,7 +320,7 @@ class LuceneQuery implements KeywordSearchQuery {
}
}
return new KeywordHit(docId, snippet, keywordString);
return new KeywordHit(docId, snippet, originalKeyword.getSearchTerm());
}
/**
@ -341,7 +337,7 @@ class LuceneQuery implements KeywordSearchQuery {
*
* @return
*/
public static String querySnippet(String query, long solrObjectId, boolean isRegex, boolean group) throws NoOpenCoreException {
static String querySnippet(String query, long solrObjectId, boolean isRegex, boolean group) throws NoOpenCoreException {
return querySnippet(query, solrObjectId, 0, isRegex, group);
}
@ -360,62 +356,33 @@ class LuceneQuery implements KeywordSearchQuery {
*
* @return
*/
public static String querySnippet(String query, long solrObjectId, int chunkID, boolean isRegex, boolean group) throws NoOpenCoreException {
Server solrServer = KeywordSearch.getServer();
static String querySnippet(String query, long solrObjectId, int chunkID, boolean isRegex, boolean group) throws NoOpenCoreException {
SolrQuery q = new SolrQuery();
q.setShowDebugInfo(DEBUG); //debug
String queryStr;
if (isRegex) {
StringBuilder sb = new StringBuilder();
sb.append(LuceneQuery.HIGHLIGHT_FIELD).append(":");
if (group) {
sb.append("\"");
}
sb.append(query);
if (group) {
sb.append("\"");
}
queryStr = sb.toString();
queryStr = HIGHLIGHT_FIELD + ":"
+ (group ? KeywordSearchUtil.quoteQuery(query)
: query);
} else {
//simplify query/escaping and use default field
//always force grouping/quotes
/*
* simplify query/escaping and use default field always force
* grouping/quotes
*/
queryStr = KeywordSearchUtil.quoteQuery(query);
}
q.setQuery(queryStr);
String contentIDStr;
if (chunkID == 0) {
contentIDStr = Long.toString(solrObjectId);
} else {
contentIDStr = Server.getChunkIdString(solrObjectId, chunkID);
}
String contentIDStr = (chunkID == 0)
? Long.toString(solrObjectId)
: Server.getChunkIdString(solrObjectId, chunkID);
String idQuery = Server.Schema.ID.toString() + ":" + KeywordSearchUtil.escapeLuceneQuery(contentIDStr);
q.setShowDebugInfo(DEBUG); //debug
q.addFilterQuery(idQuery);
q.addHighlightField(LuceneQuery.HIGHLIGHT_FIELD);
//q.setHighlightSimplePre("&laquo;"); //original highlighter only
//q.setHighlightSimplePost("&raquo;"); //original highlighter only
q.setHighlightSnippets(1);
q.setHighlightFragsize(SNIPPET_LENGTH);
//tune the highlighter
q.setParam("hl.useFastVectorHighlighter", "on"); //fast highlighter scales better than standard one NON-NLS
q.setParam("hl.tag.pre", "&laquo;"); //makes sense for FastVectorHighlighter only NON-NLS
q.setParam("hl.tag.post", "&laquo;"); //makes sense for FastVectorHighlighter only NON-NLS
q.setParam("hl.fragListBuilder", "simple"); //makes sense for FastVectorHighlighter only NON-NLS
configurwQueryForHighlighting(q);
//Solr bug if fragCharSize is smaller than Query string, StringIndexOutOfBoundsException is thrown.
q.setParam("hl.fragCharSize", Integer.toString(queryStr.length())); //makes sense for FastVectorHighlighter only NON-NLS
//docs says makes sense for the original Highlighter only, but not really
//analyze all content SLOW! consider lowering
q.setParam("hl.maxAnalyzedChars", Server.HL_ANALYZE_CHARS_UNLIMITED); //NON-NLS
Server solrServer = KeywordSearch.getServer();
try {
QueryResponse response = solrServer.query(q, METHOD.POST);
@ -439,42 +406,4 @@ class LuceneQuery implements KeywordSearchQuery {
return "";
}
}
@Override
public KeywordList getKeywordList() {
return keywordList;
}
/**
* Compares SolrDocuments based on their ID's. Two SolrDocuments with
* different chunk numbers are considered equal.
*/
static class SolrDocumentComparatorIgnoresChunkId implements Comparator<SolrDocument> {
@Override
public int compare(SolrDocument left, SolrDocument right) {
// ID is in the form of ObjectId_Chunk
final String idName = Server.Schema.ID.toString();
// get object id of left doc
String leftID = left.getFieldValue(idName).toString();
int index = leftID.indexOf(Server.CHUNK_ID_SEPARATOR);
if (index != -1) {
leftID = leftID.substring(0, index);
}
// get object id of right doc
String rightID = right.getFieldValue(idName).toString();
index = rightID.indexOf(Server.CHUNK_ID_SEPARATOR);
if (index != -1) {
rightID = rightID.substring(0, index);
}
Long leftLong = new Long(leftID);
Long rightLong = new Long(rightID);
return leftLong.compareTo(rightLong);
}
}
}

View File

@ -60,25 +60,17 @@ class QueryResults {
*/
private final Map<Keyword, List<KeywordHit>> results = new HashMap<>();
/**
* The list of keywords
*/
// TODO: This is redundant. The keyword list is in the query.
private final KeywordList keywordList;
QueryResults(KeywordSearchQuery query, KeywordList keywordList) {
QueryResults(KeywordSearchQuery query) {
this.keywordSearchQuery = query;
this.keywordList = keywordList;
}
void addResult(Keyword keyword, List<KeywordHit> hits) {
results.put(keyword, hits);
}
// TODO: This is redundant. The keyword list is in the query.
KeywordList getKeywordList() {
return keywordList;
}
KeywordSearchQuery getQuery() {
return keywordSearchQuery;
@ -129,7 +121,7 @@ class QueryResults {
if (hitDisplayStr.length() > 50) {
hitDisplayStr = hitDisplayStr.substring(0, 49) + "...";
}
subProgress.progress(keywordList.getName() + ": " + hitDisplayStr, unitProgress);
subProgress.progress(keywordSearchQuery.getKeywordList().getName() + ": " + hitDisplayStr, unitProgress);
}
for (KeywordHit hit : getOneHitPerObject(keyword)) {
@ -138,7 +130,11 @@ class QueryResults {
if (StringUtils.isBlank(snippet)) {
final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(termString);
try {
//this doesn't work for regex queries...
/*
* this doesn't work for regex queries... But that is
* okay because regex queries always have snippets made
* from the content_str field we pull back from Solr
*/
snippet = LuceneQuery.querySnippet(snippetQuery, hit.getSolrObjectId(), hit.getChunkId(), !keywordSearchQuery.isLiteral(), true);
} catch (NoOpenCoreException e) {
logger.log(Level.WARNING, "Error querying snippet: " + snippetQuery, e); //NON-NLS
@ -149,16 +145,14 @@ class QueryResults {
continue;
}
}
if (snippet != null) {
KeywordCachedArtifact writeResult = keywordSearchQuery.writeSingleFileHitsToBlackBoard(keyword, hit, snippet, keywordList.getName());
if (writeResult != null) {
newArtifacts.add(writeResult.getArtifact());
if (notifyInbox) {
writeSingleFileInboxMessage(writeResult, hit.getContent());
}
} else {
logger.log(Level.WARNING, "BB artifact for keyword hit not written, file: {0}, hit: {1}", new Object[]{hit.getContent(), keyword.toString()}); //NON-NLS
KeywordCachedArtifact writeResult = keywordSearchQuery.writeSingleFileHitsToBlackBoard(keyword, hit, snippet, keywordSearchQuery.getKeywordList().getName());
if (writeResult != null) {
newArtifacts.add(writeResult.getArtifact());
if (notifyInbox) {
writeSingleFileInboxMessage(writeResult, hit.getContent());
}
} else {
logger.log(Level.WARNING, "BB artifact for keyword hit not written, file: {0}, hit: {1}", new Object[]{hit.getContent(), keyword.toString()}); //NON-NLS
}
}
++unitProgress;

View File

@ -81,7 +81,7 @@ final class RegexQuery implements KeywordSearchQuery {
private final Keyword originalKeyword; // The regular expression originalKeyword used to perform the search.
private String field = Server.Schema.CONTENT_STR.toString();
private final String keywordString;
static final private int MAX_RESULTS = 512;
static final private int MAX_RESULTS_PER_CURSOR_MARK = 512;
private boolean escaped;
private String escapedQuery;
@ -154,7 +154,6 @@ final class RegexQuery implements KeywordSearchQuery {
@Override
public QueryResults performQuery() throws NoOpenCoreException {
QueryResults results = new QueryResults(this, keywordList);
final Server solrServer = KeywordSearch.getServer();
SolrQuery solrQuery = new SolrQuery();
@ -187,12 +186,12 @@ final class RegexQuery implements KeywordSearchQuery {
.map(KeywordQueryFilter::toString)
.forEach(solrQuery::addFilterQuery);
solrQuery.setRows(MAX_RESULTS);
solrQuery.setRows(MAX_RESULTS_PER_CURSOR_MARK);
// Setting the sort order is necessary for cursor based paging to work.
solrQuery.setSort(SortClause.asc(Server.Schema.ID.toString()));
String cursorMark = CursorMarkParams.CURSOR_MARK_START;
SolrDocumentList resultList = null;
SolrDocumentList resultList ;
boolean allResultsProcessed = false;
while (!allResultsProcessed) {
@ -218,15 +217,14 @@ final class RegexQuery implements KeywordSearchQuery {
}
cursorMark = nextCursorMark;
} catch (KeywordSearchModuleException ex) {
LOGGER.log(Level.SEVERE, "Error executing Lucene Solr Query: " + keywordString, ex); //NON-NLS
LOGGER.log(Level.SEVERE, "Error executing Regex Solr Query: " + keywordString, ex); //NON-NLS
MessageNotifyUtil.Notify.error(NbBundle.getMessage(Server.class, "Server.query.exception.msg", keywordString), ex.getCause().getMessage());
}
}
QueryResults results = new QueryResults(this);
for (Keyword k : hitsMultiMap.keySet()) {
results.addResult(k, hitsMultiMap.get(k));
}
return results;
}

View File

@ -590,7 +590,7 @@ public final class SearchRunner {
// Create a new (empty) QueryResults object to hold the most recently
// found hits.
QueryResults newResults = new QueryResults(queryResult.getQuery(), queryResult.getKeywordList());
QueryResults newResults = new QueryResults(queryResult.getQuery());
// For each keyword represented in the results.
for (Keyword keyword : queryResult.getKeywords()) {

View File

@ -280,7 +280,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
/*
* Do a term query for each term that matched the regex.
*/
QueryResults results = new QueryResults(this, keywordList);
QueryResults results = new QueryResults(this);
for (Term term : terms) {
/*
* If searching for credit card account numbers, do a Luhn check on

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import com.google.common.io.CharSource;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.util.List;
import java.util.MissingResourceException;
@ -69,20 +70,29 @@ class TikaTextExtractor extends FileTextExtractor {
final Future<Reader> future = tikaParseExecutor.submit(() -> new Tika().parse(stream, metadata));
try {
final Reader tikaReader = future.get(getTimeout(sourceFile.getSize()), TimeUnit.SECONDS);
CharSource metaDataCharSource = getMetaDataCharSource(metadata);
//check if the reader is empty
PushbackReader pushbackReader = new PushbackReader(tikaReader);
int read = pushbackReader.read();
if (read == -1) {
throw new TextExtractorException("Tika returned empty reader for " + sourceFile);
}
pushbackReader.unread(read);
//concatenate parsed content and meta data into a single reader.
return CharSource.concat(new ReaderCharSource(tikaReader), metaDataCharSource).openStream();
CharSource metaDataCharSource = getMetaDataCharSource(metadata);
return CharSource.concat(new ReaderCharSource(pushbackReader), metaDataCharSource).openStream();
} catch (TimeoutException te) {
final String msg = NbBundle.getMessage(this.getClass(), "AbstractFileTikaTextExtract.index.tikaParseTimeout.text", sourceFile.getId(), sourceFile.getName());
logWarning(msg, te);
future.cancel(true);
throw new TextExtractorException(msg, te);
} catch (Exception ex) {
KeywordSearch.getTikaLogger().log(Level.WARNING, "Exception: Unable to Tika parse the content" + sourceFile.getId() + ": " + sourceFile.getName(), ex.getCause()); //NON-NLS
final String msg = NbBundle.getMessage(this.getClass(), "AbstractFileTikaTextExtract.index.exception.tikaParse.msg", sourceFile.getId(), sourceFile.getName());
logWarning(msg, ex);
future.cancel(true);
throw new TextExtractorException(msg, ex);
} finally {
future.cancel(true);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

View File

@ -1,4 +1,4 @@
/*
/*
*
* Autopsy Forensic Browser
*
@ -112,6 +112,7 @@ class Chrome extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
while (j < historyFiles.size()) {
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + historyFiles.get(j).getName().toString() + j + ".db"; //NON-NLS
@ -155,13 +156,18 @@ class Chrome extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
}
dbFile.delete();
}
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
}
/**
@ -185,6 +191,7 @@ class Chrome extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
while (j < bookmarkFiles.size()) {
@ -289,6 +296,7 @@ class Chrome extends Extract {
// index the artifact for keyword search
this.indexArtifact(bbart);
bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to insert Chrome bookmark artifact{0}", ex); //NON-NLS
this.addErrorMessage(
@ -299,7 +307,9 @@ class Chrome extends Extract {
dbFile.delete();
}
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts));
}
/**
@ -324,6 +334,7 @@ class Chrome extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
while (j < cookiesFiles.size()) {
AbstractFile cookiesFile = cookiesFiles.get(j++);
@ -370,13 +381,19 @@ class Chrome extends Extract {
domain = domain.replaceFirst("^\\.+(?!$)", "");
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), domain));
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
}
dbFile.delete();
}
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts));
}
/**
@ -400,6 +417,7 @@ class Chrome extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
while (j < downloadFiles.size()) {
AbstractFile downloadFile = downloadFiles.get(j++);
@ -456,14 +474,19 @@ class Chrome extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
NbBundle.getMessage(this.getClass(), "Chrome.moduleName")));
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
}
dbFile.delete();
}
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
}
/**
@ -487,6 +510,7 @@ class Chrome extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
while (j < signonFiles.size()) {
AbstractFile signonFile = signonFiles.get(j++);
@ -539,8 +563,13 @@ class Chrome extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
result.get("signon_realm").toString())); //NON-NLS
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, signonFile, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, signonFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
// Don't add TSK_OS_ACCOUNT artifacts to the ModuleDataEvent
Collection<BlackboardAttribute> osAcctAttributes = new ArrayList<>();
osAcctAttributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
@ -551,7 +580,9 @@ class Chrome extends Extract {
dbFile.delete();
}
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
}
private boolean isChromePreVersion30(String temps) {

View File

@ -86,16 +86,19 @@ abstract class Extract {
* @param bbattributes is the collection of blackboard attributes that need
* to be added to the artifact after the artifact has
* been created
* @return The newly-created artifact, or null on error
*/
protected void addArtifact(BlackboardArtifact.ARTIFACT_TYPE type, AbstractFile content, Collection<BlackboardAttribute> bbattributes) {
protected BlackboardArtifact addArtifact(BlackboardArtifact.ARTIFACT_TYPE type, AbstractFile content, Collection<BlackboardAttribute> bbattributes) {
try {
BlackboardArtifact bbart = content.newArtifact(type);
bbart.addAttributes(bbattributes);
// index the artifact for keyword search
this.indexArtifact(bbart);
return bbart;
} catch (TskException ex) {
logger.log(Level.SEVERE, "Error while trying to add an artifact", ex); //NON-NLS
}
return null;
}
/**

View File

@ -1,4 +1,4 @@
/*
/*
*
* Autopsy Forensic Browser
*
@ -41,6 +41,7 @@ import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.Collection;
import java.util.Scanner;
import java.util.stream.Collectors;
import org.openide.modules.InstalledFileLocator;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
@ -109,6 +110,7 @@ class ExtractIE extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
for (AbstractFile fav : favoritesFiles) {
if (fav.getSize() == 0) {
continue;
@ -143,10 +145,15 @@ class ExtractIE extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), domain));
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, fav, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, fav, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
}
services.fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts));
}
private String getURLFromIEBookmarkFile(AbstractFile fav) {
@ -205,6 +212,7 @@ class ExtractIE extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
for (AbstractFile cookiesFile : cookiesFiles) {
if (context.dataSourceIngestIsCancelled()) {
break;
@ -253,10 +261,14 @@ class ExtractIE extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), domain));
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
}
services.fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts));
}
/**
@ -302,6 +314,7 @@ class ExtractIE extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
String temps;
String indexFileName;
for (AbstractFile indexFile : indexFiles) {
@ -336,7 +349,10 @@ class ExtractIE extends Extract {
//At this point pasco2 proccessed the index files.
//Now fetch the results, parse them and the delete the files.
if (bPascProcSuccess) {
parsePascoOutput(indexFile, filename);
// Don't add TSK_OS_ACCOUNT artifacts to the ModuleDataEvent
bbartifacts.addAll(parsePascoOutput(indexFile, filename).stream()
.filter(bbart -> bbart.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID())
.collect(Collectors.toList()));
foundHistory = true;
//Delete index<n>.dat file since it was succcessfully by Pasco
@ -350,7 +366,8 @@ class ExtractIE extends Extract {
if (foundHistory) {
services.fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
}
}
@ -403,9 +420,12 @@ class ExtractIE extends Extract {
* @param origFile Original index.dat file that was analyzed to
* get this output
* @param pascoOutputFileName name of pasco output file
*
* @return A collection of created artifacts
*/
private void parsePascoOutput(AbstractFile origFile, String pascoOutputFileName) {
private Collection<BlackboardArtifact> parsePascoOutput(AbstractFile origFile, String pascoOutputFileName) {
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
String fnAbs = moduleTempResultsDir + File.separator + pascoOutputFileName;
File file = new File(fnAbs);
@ -414,13 +434,13 @@ class ExtractIE extends Extract {
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(),
file.getName()));
logger.log(Level.WARNING, "Pasco Output not found: {0}", file.getPath()); //NON-NLS
return;
return bbartifacts;
}
// Make sure the file the is not empty or the Scanner will
// throw a "No Line found" Exception
if (file.length() == 0) {
return;
return bbartifacts;
}
Scanner fileScanner;
@ -431,7 +451,7 @@ class ExtractIE extends Extract {
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(),
file.getName()));
logger.log(Level.WARNING, "Unable to find the Pasco file at " + file.getPath(), ex); //NON-NLS
return;
return bbartifacts;
}
// Keep a list of reported user accounts to avoid repeats
@ -521,6 +541,7 @@ class ExtractIE extends Extract {
// index the artifact for keyword search
this.indexArtifact(bbart);
bbartifacts.add(bbart);
if ((!user.isEmpty()) && (!reportedUserAccounts.contains(user))) {
BlackboardArtifact osAttr = origFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
@ -529,6 +550,7 @@ class ExtractIE extends Extract {
// index the artifact for keyword search
this.indexArtifact(osAttr);
bbartifacts.add(osAttr);
reportedUserAccounts.add(user);
}
@ -537,5 +559,6 @@ class ExtractIE extends Extract {
}
}
fileScanner.close();
return bbartifacts;
}
}

View File

@ -97,7 +97,7 @@ class Firefox extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
for (AbstractFile historyFile : historyFiles) {
if (historyFile.getSize() == 0) {
@ -148,14 +148,19 @@ class Firefox extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"), (Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
}
++j;
dbFile.delete();
}
services.fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
}
/**
@ -180,7 +185,7 @@ class Firefox extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
for (AbstractFile bookmarkFile : bookmarkFiles) {
if (bookmarkFile.getSize() == 0) {
@ -228,15 +233,19 @@ class Firefox extends Extract {
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
}
++j;
dbFile.delete();
}
services.fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts));
}
/**
@ -260,6 +269,7 @@ class Firefox extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
for (AbstractFile cookiesFile : cookiesFiles) {
if (cookiesFile.getSize() == 0) {
@ -326,14 +336,19 @@ class Firefox extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"), domain));
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
}
++j;
dbFile.delete();
}
services.fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts));
}
/**
@ -368,6 +383,7 @@ class Firefox extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
for (AbstractFile downloadsFile : downloadsFiles) {
if (downloadsFile.getSize() == 0) {
@ -436,8 +452,11 @@ class Firefox extends Extract {
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
(Util.extractDomain((result.get("source").toString() != null) ? result.get("source").toString() : "")))); //NON-NLS
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
}
if (errors > 0) {
this.addErrorMessage(
@ -450,7 +469,8 @@ class Firefox extends Extract {
}
services.fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
}
/**
@ -476,6 +496,7 @@ class Firefox extends Extract {
}
dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
for (AbstractFile downloadsFile : downloadsFiles) {
if (downloadsFile.getSize() == 0) {
@ -546,8 +567,11 @@ class Firefox extends Extract {
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart);
}
}
if (errors > 0) {
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
@ -559,6 +583,7 @@ class Firefox extends Extract {
}
services.fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
}
}

View File

@ -1,5 +1,5 @@
#Updated by build script
#Mon, 30 Jan 2017 13:39:12 -0500
#Mon, 06 Mar 2017 10:02:14 -0500
LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314
SPLASH_WIDTH=538

View File

@ -1,4 +1,4 @@
#Updated by build script
#Mon, 30 Jan 2017 13:39:12 -0500
#Mon, 06 Mar 2017 10:02:14 -0500
CTL_MainWindow_Title=Autopsy 4.3.0
CTL_MainWindow_Title_No_Project=Autopsy 4.3.0

View File

@ -8,7 +8,7 @@
<import file="nbproject/build-impl.xml"/>
<!-- IMPORTANT: nbproject/platform.properties has a netbeans-plat-version property that MUST be kept in sync (manually) -->
<property name="netbeans-plat-version" value="8.1" />
<property name="netbeans-plat-version" value="8.2" />
<property name="nbplatform.active.dir" value="${basedir}/netbeans-plat/${netbeans-plat-version}" />
<!-- Supported java versions.-->
<condition property="supported-java-versions">

View File

@ -8,4 +8,4 @@ nbproject/build-impl.xml.script.CRC32=b72261eb
nbproject/build-impl.xml.stylesheet.CRC32=0f381476@2.47.1
nbproject/platform.xml.data.CRC32=2e7964b0
nbproject/platform.xml.script.CRC32=6dcbd131
nbproject/platform.xml.stylesheet.CRC32=4e1f53d4@2.62.1
nbproject/platform.xml.stylesheet.CRC32=45ddf0e0@2.72.1

View File

@ -1,7 +1,7 @@
branding.token=autopsy
# Version of platform that is automatically downloaded
# IMPORTANT: autopsy/build.xml has a netbeans-plat-version property that MUST be kept in sync (manually)
netbeans-plat-version=8.1
netbeans-plat-version=8.2
suite.dir=${basedir}
nbplatform.active.dir=${suite.dir}/netbeans-plat/${netbeans-plat-version}
harness.dir=${nbplatform.active.dir}/harness

BIN
thirdparty/junit/8.2/junit.zip vendored Normal file

Binary file not shown.