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.DataSourceProcessorCallback.DataSourceProcessorResult;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger; 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.Content;
import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitJNI; import org.sleuthkit.datamodel.SleuthkitJNI;
@ -41,6 +43,7 @@ class AddImageTask implements Runnable {
private final String deviceId; private final String deviceId;
private final String imagePath; private final String imagePath;
private final String timeZone; private final String timeZone;
private final String imageWriterPath;
private final boolean ignoreFatOrphanFiles; private final boolean ignoreFatOrphanFiles;
private final DataSourceProcessorProgressMonitor progressMonitor; private final DataSourceProcessorProgressMonitor progressMonitor;
private final DataSourceProcessorCallback callback; private final DataSourceProcessorCallback callback;
@ -74,15 +77,19 @@ class AddImageTask implements Runnable {
* java.util.TimeZone.getID. * java.util.TimeZone.getID.
* @param ignoreFatOrphanFiles Whether to parse orphans if the image has a * @param ignoreFatOrphanFiles Whether to parse orphans if the image has a
* FAT filesystem. * 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 * @param progressMonitor Progress monitor to report progress during
* processing. * processing.
* @param callback Callback to call when processing is done. * @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.deviceId = deviceId;
this.imagePath = imagePath; this.imagePath = imagePath;
this.timeZone = timeZone; this.timeZone = timeZone;
this.ignoreFatOrphanFiles = ignoreFatOrphanFiles; this.ignoreFatOrphanFiles = ignoreFatOrphanFiles;
this.imageWriterPath = imageWriterPath;
this.callback = callback; this.callback = callback;
this.progressMonitor = progressMonitor; this.progressMonitor = progressMonitor;
tskAddImageProcessLock = new Object(); tskAddImageProcessLock = new Object();
@ -101,7 +108,7 @@ class AddImageTask implements Runnable {
try { try {
currentCase.getSleuthkitCase().acquireExclusiveLock(); currentCase.getSleuthkitCase().acquireExclusiveLock();
synchronized (tskAddImageProcessLock) { 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)); Thread progressUpdateThread = new Thread(new ProgressUpdater(progressMonitor, tskAddImageProcess));
progressUpdateThread.start(); progressUpdateThread.start();
@ -201,6 +208,9 @@ class AddImageTask implements Runnable {
if (!verificationError.isEmpty()) { if (!verificationError.isEmpty()) {
errorMessages.add(verificationError); errorMessages.add(verificationError);
} }
if(! imageWriterPath.isEmpty()){
ImageWriterService.createImageWriter(imageId);
}
newDataSources.add(newImage); newDataSources.add(newImage);
} else { } else {
String errorMessage = String.format("Error commiting adding image %s to the case database, no object id returned", imagePath); //NON-NLS 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) * The "Add Image" wizard panel1 handling the logic of selecting image file(s)
* to add to Case, and pick the time zone. * 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 * The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent(). * component from this class, just use getComponent().
*/ */
private final AddImageWizardAddingProgressPanel progressPanel; private AddImageWizardDataSourceSettingsVisual component;
private AddImageWizardChooseDataSourceVisual component;
private boolean isNextEnable = false; 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) // paths to any set hash lookup databases (can be null)
private String NSRLPath, knownBadPath;
AddImageWizardChooseDataSourcePanel(AddImageWizardAddingProgressPanel proPanel) { AddImageWizardDataSourceSettingsPanel() {
this.progressPanel = proPanel;
} }
@ -68,10 +62,10 @@ class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel
* @return component the UI component of this wizard panel * @return component the UI component of this wizard panel
*/ */
@Override @Override
public AddImageWizardChooseDataSourceVisual getComponent() { public AddImageWizardDataSourceSettingsVisual getComponent() {
if (component == null) { if (component == null) {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
component = new AddImageWizardChooseDataSourceVisual(this); component = new AddImageWizardDataSourceSettingsVisual(this);
} }
component.addPropertyChangeListener(this); component.addPropertyChangeListener(this);
return component; return component;
@ -87,8 +81,7 @@ class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel
public HelpCtx getHelp() { public HelpCtx getHelp() {
// Show no Help button for this panel: // Show no Help button for this panel:
return HelpCtx.DEFAULT_HELP; 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 * 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 * or already-modified settings, if the user used the previous and/or next
@ -178,26 +167,16 @@ class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel
*/ */
@Override @Override
public void readSettings(WizardDescriptor settings) { public void readSettings(WizardDescriptor settings) {
//reset settings if supports it
//getComponent().reset();
// Prepopulate the image directory from the properties file // Prepopulate the image directory from the properties file
try { 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 // 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); AddImageAction.CleanupTask cleanupTask = (AddImageAction.CleanupTask) settings.getProperty(AddImageAction.IMAGECLEANUPTASK_PROP);
if (cleanupTask != null) { if (cleanupTask != null) {
try { try {
cleanupTask.cleanup(); cleanupTask.cleanup();
} catch (Exception ex) { } 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 logger.log(Level.WARNING, "Error cleaning up image task", ex); //NON-NLS
} finally { } finally {
cleanupTask.disable(); cleanupTask.disable();
@ -205,7 +184,7 @@ class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel
} }
} catch (Exception e) { } 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 AddImageAction addImageAction;
private final AddImageWizardAddingProgressPanel progressPanel; private final AddImageWizardAddingProgressPanel progressPanel;
private final AddImageWizardChooseDataSourcePanel dataSourcePanel; private final AddImageWizardDataSourceSettingsPanel dataSourcePanel;
private DataSourceProcessor dsProcessor; private DataSourceProcessor dsProcessor;
private boolean cancelled; private boolean cancelled;
AddImageWizardIngestConfigPanel(AddImageWizardChooseDataSourcePanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) { AddImageWizardIngestConfigPanel(AddImageWizardDataSourceSettingsPanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
this.addImageAction = action; this.addImageAction = action;
this.progressPanel = proPanel; this.progressPanel = proPanel;
this.dataSourcePanel = dsPanel; this.dataSourcePanel = dsPanel;

View File

@ -40,6 +40,7 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
private List<ShortcutWizardDescriptorPanel> panels; private List<ShortcutWizardDescriptorPanel> panels;
private final AddImageAction action; private final AddImageAction action;
private int progressPanelIndex; private int progressPanelIndex;
private int dsPanelIndex;
private final static String PROP_LASTPROFILE_NAME = "AIW_LASTPROFILE_NAME"; //NON-NLS private final static String PROP_LASTPROFILE_NAME = "AIW_LASTPROFILE_NAME"; //NON-NLS
AddImageWizardIterator(AddImageAction action) { AddImageWizardIterator(AddImageAction action) {
@ -53,10 +54,11 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
private List<ShortcutWizardDescriptorPanel> getPanels() { private List<ShortcutWizardDescriptorPanel> getPanels() {
if (panels == null) { if (panels == null) {
panels = new ArrayList<>(); panels = new ArrayList<>();
AddImageWizardSelectDspPanel dspSelection = new AddImageWizardSelectDspPanel();
panels.add(dspSelection);
AddImageWizardAddingProgressPanel progressPanel = new AddImageWizardAddingProgressPanel(); AddImageWizardAddingProgressPanel progressPanel = new AddImageWizardAddingProgressPanel();
AddImageWizardChooseDataSourcePanel dsPanel = new AddImageWizardChooseDataSourcePanel(progressPanel); AddImageWizardDataSourceSettingsPanel dsPanel = new AddImageWizardDataSourceSettingsPanel();
AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(dsPanel, action, progressPanel); AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(dsPanel, action, progressPanel);
panels.add(dsPanel); panels.add(dsPanel);
List<IngestProfiles.IngestProfile> profiles = IngestProfiles.getIngestProfiles(); List<IngestProfiles.IngestProfile> profiles = IngestProfiles.getIngestProfiles();
@ -66,6 +68,7 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
panels.add(ingestConfigPanel); panels.add(ingestConfigPanel);
panels.add(progressPanel); panels.add(progressPanel);
progressPanelIndex = panels.indexOf(progressPanel); //Doing programatically because number of panels is variable progressPanelIndex = panels.indexOf(progressPanel); //Doing programatically because number of panels is variable
dsPanelIndex = panels.indexOf(dsPanel);
String[] steps = new String[panels.size()]; String[] steps = new String[panels.size()];
for (int i = 0; i < panels.size(); i++) { for (int i = 0; i < panels.size(); i++) {
Component c = panels.get(i).getComponent(); 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 * @return boolean true if it has previous panel, false if not
*/ */
@Override @Override
// disable the previous button on all panels // disable the previous button on all panels except the data source panel
public boolean hasPrevious() { 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.localFileChooser.approveButtonToolTipText=
LocalFilesPanel.selectButton.actionCommand=Add LocalFilesPanel.selectButton.actionCommand=Add
AddImageWizardAddingProgressVisual.statusLabel.text=Data source has been added to the local database. Files are being analyzed. 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.progressLabel.text=<progress>
AddImageWizardAddingProgressVisual.viewLogButton.text=View Log 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. 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.toolTipText=
LocalDiskPanel.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems LocalDiskPanel.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems
LocalDiskPanel.descLabel.text=(faster results, although some data will not be searched) 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.browseButton.text=Browse
MissingImageDialog.pathNameTextField.text= MissingImageDialog.pathNameTextField.text=
AddImageWizardAddingProgressVisual.progressTextArea.border.title=Status AddImageWizardAddingProgressVisual.progressTextArea.border.title=Status
@ -224,6 +226,11 @@ LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default
IngestJobInfoPanel.jLabel1.text=Ingest Modules IngestJobInfoPanel.jLabel1.text=Ingest Modules
IngestJobInfoPanel.jLabel2.text=Ingest Jobs IngestJobInfoPanel.jLabel2.text=Ingest Jobs
CaseInformationPanel.closeButton.text=Close 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.updateCaseNameButton.text=Update Name
CasePropertiesPanel.caseNameTextField.text= CasePropertiesPanel.caseNameTextField.text=
CasePropertiesPanel.caseDirLabel.text=Case Directory: 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.localFileChooser.approveButtonText=\u9078\u629e
LocalFilesPanel.selectButton.actionCommand=\u8ffd\u52a0 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 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.progressLabel.text=\uff1c\u30d7\u30ed\u30b0\u30ec\u30b9\uff1e
AddImageWizardAddingProgressVisual.viewLogButton.text=\u30ed\u30b0\u3092\u8868\u793a 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 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.events.ReportAddedEvent;
import org.sleuthkit.autopsy.casemodule.services.Services; import org.sleuthkit.autopsy.casemodule.services.Services;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService; 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.CoordinationServiceException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.core.UserPreferencesException; import org.sleuthkit.autopsy.core.UserPreferencesException;
@ -673,7 +673,7 @@ public class Case {
* cannot be deleted if another node has it open. * cannot be deleted if another node has it open.
*/ */
progressIndicator.start(Bundle.Case_progressMessage_acquiringLocks()); 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); assert (null != dirLock);
/* /*
@ -945,7 +945,7 @@ public class Case {
@Messages({"Case.creationException.couldNotAcquireNameLock=Failed to get lock on case name"}) @Messages({"Case.creationException.couldNotAcquireNameLock=Failed to get lock on case name"})
private static CoordinationService.Lock acquireExclusiveCaseNameLock(String caseName) throws CaseActionException { private static CoordinationService.Lock acquireExclusiveCaseNameLock(String caseName) throws CaseActionException {
try { 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) { if (null == lock) {
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireNameLock()); throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireNameLock());
} }
@ -971,7 +971,7 @@ public class Case {
private static CoordinationService.Lock acquireExclusiveCaseResourcesLock(String caseName) throws CaseActionException { private static CoordinationService.Lock acquireExclusiveCaseResourcesLock(String caseName) throws CaseActionException {
try { try {
String resourcesNodeName = caseName + "_resources"; 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) { if (null == lock) {
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock()); throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
} }
@ -1604,7 +1604,7 @@ public class Case {
"Case.progressIndicatorTitle.creatingCase=Creating Case", "Case.progressIndicatorTitle.creatingCase=Creating Case",
"Case.progressIndicatorCancelButton.label=Cancel", "Case.progressIndicatorCancelButton.label=Cancel",
"Case.progressMessage.preparing=Preparing...", "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 { 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."}) @Messages({"Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directory."})
private void acquireSharedCaseDirLock(String caseDir) throws CaseActionException { private void acquireSharedCaseDirLock(String caseDir) throws CaseActionException {
try { 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) { if (null == caseDirLock) {
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock()); throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock());
} }

View File

@ -455,13 +455,6 @@ public final class CaseMetadata {
this.caseDatabaseName = caseDirectoryPath.relativize(possibleAbsoluteCaseDbPath).toString(); 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) { } catch (ParserConfigurationException | SAXException | IOException ex) {
throw new CaseMetadataException(String.format("Error reading from case metadata file %s", metadataFilePath), 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() { protected void done() {
try { try {
get(); 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 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)); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
@ -124,6 +124,15 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
StartupWindowProvider.getInstance().open(); 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)); 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. * @param callback Callback to call when processing is done.
*/ */
public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { 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(); new Thread(addImageTask).start();
} }

View File

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

View File

@ -3,10 +3,10 @@
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> <Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties> <Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 65]"/> <Dimension value="[0, 420]"/>
</Property> </Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[485, 65]"/> <Dimension value="[485, 410]"/>
</Property> </Property>
</Properties> </Properties>
<AuxValues> <AuxValues>
@ -26,21 +26,38 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="diskLabel" min="-2" max="-2" attributes="0"/> <Group type="102" alignment="0" attributes="0">
<Component id="diskComboBox" min="-2" pref="345" max="-2" attributes="0"/> <Group type="103" groupAlignment="1" attributes="0">
<Component id="errorLabel" min="-2" max="-2" attributes="0"/> <Component id="pathTextField" alignment="1" min="-2" pref="362" max="-2" attributes="0"/>
<Group type="102" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/> <Component id="diskLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <Component id="diskComboBox" min="-2" pref="345" max="-2" attributes="0"/>
<Component id="timeZoneComboBox" min="-2" pref="215" 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> </Group>
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/> <Group type="102" alignment="0" attributes="0">
<Group type="102" attributes="0"> <EmptySpace min="-2" pref="21" max="-2" attributes="0"/>
<EmptySpace min="21" pref="21" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0">
<Component id="descLabel" min="-2" max="-2" 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>
</Group> </Group>
<EmptySpace min="0" pref="102" max="32767" attributes="0"/> <EmptySpace min="0" pref="29" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -61,7 +78,18 @@
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/> <Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="descLabel" min="-2" 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>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -165,5 +193,58 @@
</Property> </Property>
</Properties> </Properties>
</Component> </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> </SubComponents>
</Form> </Form>

View File

@ -22,6 +22,8 @@ import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.Font; import java.awt.Font;
import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
@ -30,6 +32,7 @@ import java.util.TimeZone;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.ComboBoxModel; import javax.swing.ComboBoxModel;
import javax.swing.JFileChooser;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import javax.swing.JPanel; import javax.swing.JPanel;
@ -57,6 +60,7 @@ final class LocalDiskPanel extends JPanel {
private List<LocalDisk> disks; private List<LocalDisk> disks;
private LocalDiskModel model; private LocalDiskModel model;
private boolean enableNext = false; private boolean enableNext = false;
private final JFileChooser fc = new JFileChooser();
/** /**
* Creates new form LocalDiskPanel * Creates new form LocalDiskPanel
@ -88,6 +92,10 @@ final class LocalDiskPanel extends JPanel {
errorLabel.setVisible(false); errorLabel.setVisible(false);
errorLabel.setText(""); errorLabel.setText("");
diskComboBox.setEnabled(false); 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<>(); timeZoneComboBox = new javax.swing.JComboBox<>();
noFatOrphansCheckbox = new javax.swing.JCheckBox(); noFatOrphansCheckbox = new javax.swing.JCheckBox();
descLabel = new javax.swing.JLabel(); 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)); setMinimumSize(new java.awt.Dimension(0, 420));
setPreferredSize(new java.awt.Dimension(485, 65)); setPreferredSize(new java.awt.Dimension(485, 410));
diskLabel.setFont(diskLabel.getFont().deriveFont(diskLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); 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 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)); 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(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); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .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() .addGroup(layout.createSequentialGroup()
.addComponent(timeZoneLabel) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 362, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(noFatOrphansCheckbox) .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() .addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21) .addGap(21, 21, 21)
.addComponent(descLabel))) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 102, Short.MAX_VALUE)) .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 423, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(imageWriterErrorLabel))))
.addGap(0, 29, Short.MAX_VALUE))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -167,19 +222,76 @@ final class LocalDiskPanel extends JPanel {
.addComponent(noFatOrphansCheckbox) .addComponent(noFatOrphansCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(descLabel) .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 }// </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 // 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.JLabel descLabel;
private javax.swing.JComboBox<LocalDisk> diskComboBox; private javax.swing.JComboBox<LocalDisk> diskComboBox;
private javax.swing.JLabel diskLabel; private javax.swing.JLabel diskLabel;
private javax.swing.JLabel errorLabel; private javax.swing.JLabel errorLabel;
private javax.swing.JLabel imageWriterErrorLabel;
private javax.swing.JLabel jLabel1;
private javax.swing.JCheckBox noFatOrphansCheckbox; private javax.swing.JCheckBox noFatOrphansCheckbox;
private javax.swing.JTextField pathTextField;
private javax.swing.JComboBox<String> timeZoneComboBox; private javax.swing.JComboBox<String> timeZoneComboBox;
private javax.swing.JLabel timeZoneLabel; private javax.swing.JLabel timeZoneLabel;
// End of variables declaration//GEN-END:variables // 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. * Return the currently selected disk path.
* *
@ -214,14 +326,69 @@ final class LocalDiskPanel extends JPanel {
boolean getNoFatOrphans() { boolean getNoFatOrphans() {
return noFatOrphansCheckbox.isSelected(); 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 * Should we enable the wizard's next button? We control all the possible
* control the possible selections. * selections except for Image Writer.
* *
* @return true * @return true if panel is valid
*/ */
public boolean validatePanel() { public boolean validatePanel() {
if(copyImageCheckbox.isSelected() &&
! imageWriterPathIsValid()){
return false;
}
return enableNext; return enableNext;
} }
@ -318,15 +485,8 @@ final class LocalDiskPanel extends JPanel {
if (ready) { if (ready) {
selected = (LocalDisk) anItem; selected = (LocalDisk) anItem;
enableNext = true; enableNext = true;
setPotentialImageWriterPath((LocalDisk) selected);
try { fireUpdateEvent();
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);
}
} }
} }

View File

@ -19,9 +19,13 @@
package org.sleuthkit.autopsy.coordinationservice; package org.sleuthkit.autopsy.coordinationservice;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.Collection;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import org.apache.curator.RetryPolicy; import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory; 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.WatchedEvent;
import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.ZooKeeper;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferences;
/** /**
* A coordination service for maintaining configuration information and * A coordination service for maintaining configuration information and
* providing distributed synchronization using a shared hierarchical namespace * providing distributed synchronization using a shared hierarchical namespace
* of nodes. * of nodes.
*
* TODO (JIRA 2205): Simple refactoring for general use.
*/ */
@ThreadSafe
public final class CoordinationService { 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 SESSION_TIMEOUT_MILLISECONDS = 300000;
private static final int CONNECTION_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_SESSION_TIMEOUT_MILLIS = 3000;
private static final int ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS = 15000; 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 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 * 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
*
* @throws CoordinationServiceException If an instance of the coordination
* service cannot be created.
*/ */
public static synchronized CoordinationService getServiceForNamespace(String rootNode) throws CoordinationServiceException { public synchronized static CoordinationService getInstance() throws CoordinationServiceException {
/* if (null == instance) {
* Connect to ZooKeeper via Curator. String rootNode;
*/ Collection<? extends CoordinationServiceNamespace> providers = Lookup.getDefault().lookupAll(CoordinationServiceNamespace.class);
if (null == curator) { Iterator<? extends CoordinationServiceNamespace> it = providers.iterator();
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3); if (it.hasNext()) {
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET; rootNode = it.next().getNamespaceRoot();
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort; } else {
curator = CuratorFrameworkFactory.newClient(connectString, SESSION_TIMEOUT_MILLISECONDS, CONNECTION_TIMEOUT_MILLISECONDS, retryPolicy); rootNode = DEFAULT_NAMESPACE_ROOT;
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;
try { try {
service = new CoordinationService(rootNode); instance = new CoordinationService(rootNode);
} catch (IOException | InterruptedException | KeeperException | CoordinationServiceException ex) { } catch (IOException | InterruptedException | KeeperException | CoordinationServiceException ex) {
curator = null;
throw new CoordinationServiceException("Failed to create coordination service", ex); 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"); 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; String rootNode = rootNodeName;
if (!rootNode.startsWith("/")) { if (!rootNode.startsWith("/")) {
rootNode = "/" + rootNode; rootNode = "/" + rootNode;
} }
categoryNodeToPath = new ConcurrentHashMap<>();
for (CategoryNode node : CategoryNode.values()) { for (CategoryNode node : CategoryNode.values()) {
String nodePath = rootNode + "/" + node.getDisplayName(); String nodePath = rootNode + "/" + node.getDisplayName();
try { try {
@ -422,8 +428,7 @@ public final class CoordinationService {
CASES("cases"), CASES("cases"),
MANIFESTS("manifests"), MANIFESTS("manifests"),
CONFIG("config"), CONFIG("config");
RESOURCE("resource");
private final String displayName; private final String displayName;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2016-2017 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,15 +19,18 @@
package org.sleuthkit.autopsy.coordinationservice; 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 { public interface CoordinationServiceNamespace {
private static final String ROOT = "autopsy";
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

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -163,12 +163,22 @@ public final class ExecUtil {
process.waitFor(timeOut, units); process.waitFor(timeOut, units);
if (process.isAlive() && terminator.shouldTerminateProcess()) { if (process.isAlive() && terminator.shouldTerminateProcess()) {
killProcess(process); 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()); } while (process.isAlive());
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
if (process.isAlive()) { if (process.isAlive()) {
killProcess(process); 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 Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, "Thread interrupted while running {0}", processBuilder.command().get(0)); // NON-NLS
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }

View File

@ -51,7 +51,9 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
* Uses lazy Content.Keys * Uses lazy Content.Keys
*/ */
AbstractContentChildren() { 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 @Override

View File

@ -61,7 +61,7 @@ public class ArtifactStringContent implements StringContent {
* @return The HTML representation of the artifact as a string. * @return The HTML representation of the artifact as a string.
*/ */
@Messages({ @Messages({
"ArtifactStringContent.attrsTableHeader.attribute=Attribute", "ArtifactStringContent.attrsTableHeader.type=Type",
"ArtifactStringContent.attrsTableHeader.value=Value", "ArtifactStringContent.attrsTableHeader.value=Value",
"ArtifactStringContent.attrsTableHeader.sources=Source(s)", "ArtifactStringContent.attrsTableHeader.sources=Source(s)",
"ArtifactStringContent.failedToGetSourcePath.message=Failed to get source file path from case database", "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("<table border='1'>"); //NON-NLS
buffer.append("<tr>"); //NON-NLS buffer.append("<tr>"); //NON-NLS
buffer.append("<td>"); //NON-NLS buffer.append("<td><b>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_attribute()); buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_type());
buffer.append("</td>"); //NON-NLS buffer.append("</b></td>"); //NON-NLS
buffer.append("<td>"); //NON-NLS buffer.append("<td><b>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_value()); buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_value());
buffer.append("</td>"); //NON-NLS buffer.append("</b></td>"); //NON-NLS
buffer.append("<td>"); //NON-NLS buffer.append("<td><b>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_sources()); buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_sources());
buffer.append("</td>"); //NON-NLS buffer.append("</b></td>"); //NON-NLS
buffer.append("</tr>\n"); //NON-NLS buffer.append("</tr>\n"); //NON-NLS
try { try {
Content content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID()); 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.chgTime.name=ChangeTime
KeywordHits.createNodeForKey.accessTime.name=AccessTime KeywordHits.createNodeForKey.accessTime.name=AccessTime
KeywordHits.createNodeForKey.modTime.name=ModifiedTime KeywordHits.createNodeForKey.modTime.name=ModifiedTime
KnownFileFilterNode.selectionContext.dataSources=Data Sources
KnownFileFilterNode.selectionContext.views=Views
LayoutFileNode.propertyType.parts=Parts LayoutFileNode.propertyType.parts=Parts
LayoutFileNode.createSheet.name.name=Name LayoutFileNode.createSheet.name.name=Name
LayoutFileNode.createSheet.name.displayName=Name LayoutFileNode.createSheet.name.displayName=Name
@ -221,8 +219,6 @@ ReportNode.reportNameProperty.name=Report Name
ReportNode.reportNameProperty.displayName=Report Name ReportNode.reportNameProperty.displayName=Report Name
ReportNode.reportNameProperty.desc=Name of the report ReportNode.reportNameProperty.desc=Name of the report
ReportsListNode.displayName=Reports ReportsListNode.displayName=Reports
SlackFileFilterNode.selectionContext.dataSources=Data Sources
SlackFileFilterNode.selectionContext.views=Views
SlackFileNode.getActions.viewInNewWin.text=View in New Window SlackFileNode.getActions.viewInNewWin.text=View in New Window
SlackFileNode.getActions.viewFileInDir.text=View File in Directory SlackFileNode.getActions.viewFileInDir.text=View File in Directory
TagNameNode.namePlusTags.text={0} Tags 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.jNoBreakupRadioButton.text=Do not break up
RawDSInputPanel.j2GBBreakupRadioButton.text=2GB chunks RawDSInputPanel.j2GBBreakupRadioButton.text=2GB chunks
RawDSInputPanel.timeZoneLabel.text=Please select the input timezone: 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 * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * 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.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerManager;
@ -33,6 +35,7 @@ import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction; import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.actions.AddContentTagAction; import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType; 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.LayoutFile;
import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.VirtualDirectory;
@ -67,11 +71,37 @@ import org.sleuthkit.datamodel.VirtualDirectory;
*/ */
public class DataResultFilterNode extends FilterNode { 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) { public DataResultFilterNode(Node node, ExplorerManager em) {
super(node, new DataResultFilterChildren(node, em)); super(node, new DataResultFilterChildren(node, em));
this.sourceEm = 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; 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 * Uses the default nodes actions per node, adds some custom ones and
* returns them per visited node type * returns them per visited node type
@ -236,10 +333,10 @@ public class DataResultFilterNode extends FilterNode {
// The base class Action is "Collapse All", inappropriate. // The base class Action is "Collapse All", inappropriate.
return null; return null;
} }
@Override @Override
public List<Action> visit(FileTypesNode fileTypes) { 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.ExtractedContent;
import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType; import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType;
import org.sleuthkit.autopsy.datamodel.KeywordHits; import org.sleuthkit.autopsy.datamodel.KeywordHits;
import org.sleuthkit.autopsy.datamodel.KnownFileFilterNode;
import org.sleuthkit.autopsy.datamodel.Reports; import org.sleuthkit.autopsy.datamodel.Reports;
import org.sleuthkit.autopsy.datamodel.Results; import org.sleuthkit.autopsy.datamodel.Results;
import org.sleuthkit.autopsy.datamodel.ResultsNode; import org.sleuthkit.autopsy.datamodel.ResultsNode;
import org.sleuthkit.autopsy.datamodel.RootContentChildren; import org.sleuthkit.autopsy.datamodel.RootContentChildren;
import org.sleuthkit.autopsy.datamodel.SlackFileFilterNode;
import org.sleuthkit.autopsy.datamodel.Tags; import org.sleuthkit.autopsy.datamodel.Tags;
import org.sleuthkit.autopsy.datamodel.Views; import org.sleuthkit.autopsy.datamodel.Views;
import org.sleuthkit.autopsy.datamodel.ViewsNode; 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 //set node, wrap in filter node first to filter out children
Node drfn = new DataResultFilterNode(originNode, DirectoryTreeTopComponent.this.em); 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 // 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)) { 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()); EmptyNode emptyNode = new EmptyNode(Bundle.DirectoryTreeTopComponent_emptyMimeNode_text());
Node emptyDrfn = new DataResultFilterNode(emptyNode, DirectoryTreeTopComponent.this.em); dataResult.setNode(new TableFilterNode(emptyNode, true, "This Node Is Empty")); //NON-NLS
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
} else if (originNode instanceof DisplayableItemNode) { } else if (originNode instanceof DisplayableItemNode) {
dataResult.setNode(new TableFilterNode(sffn, true, ((DisplayableItemNode) originNode).getItemType())); dataResult.setNode(new TableFilterNode(drfn, true, ((DisplayableItemNode) originNode).getItemType()));
} else { } else {
dataResult.setNode(new TableFilterNode(sffn, true)); dataResult.setNode(new TableFilterNode(drfn, true));
} }
String displayName = ""; 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.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
@ -413,19 +414,34 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
FilesSetDefsPanel fileIngestFilterPanel; FilesSetDefsPanel fileIngestFilterPanel;
fileIngestFilterPanel = new FilesSetDefsPanel(FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS); fileIngestFilterPanel = new FilesSetDefsPanel(FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS);
fileIngestFilterPanel.load(); fileIngestFilterPanel.load();
//save the filters that exist before any are created
final ArrayList<String> oldFilterList = new ArrayList<>(Arrays.asList(getComboBoxContents()));
dialog.addApplyButtonListener( dialog.addApplyButtonListener(
(ActionEvent e) -> { (ActionEvent e) -> {
fileIngestFilterPanel.store(); 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())); 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.close();
} }
); );
dialog.display(fileIngestFilterPanel); dialog.display(fileIngestFilterPanel);
//return to saved selection in case they cancel out of filter creation
fileIngestFilterComboBox.setSelectedItem(settings.getFileIngestFilter().getName()); fileIngestFilterComboBox.setSelectedItem(settings.getFileIngestFilter().getName());
} else if (evt.getActionCommand().equals("comboBoxChanged")) { } else if (evt.getActionCommand().equals("comboBoxChanged")) {
try { try {
Map<String, FilesSet> fileIngestFilters = FilesSetsManager.getInstance() Map<String, FilesSet> fileIngestFilters = FilesSetsManager.getInstance()
.getCustomFileIngestFilters(); .getCustomFileIngestFilters();

View File

@ -47,6 +47,7 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
private final static int INDEX_OF_SETTINGS_PANEL = 2; private final static int INDEX_OF_SETTINGS_PANEL = 2;
private ProfileSettingsPanel profilePanel; private ProfileSettingsPanel profilePanel;
private final static int INDEX_OF_PROFILE_PANEL = 1; private final static int INDEX_OF_PROFILE_PANEL = 1;
private int indexOfPreviousTab;
/** /**
* This panel implements a property change listener that listens to ingest * 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 * 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() { public IngestOptionsPanel() {
initComponents(); initComponents();
customizeComponents(); customizeComponents();
indexOfPreviousTab = tabbedPane.getSelectedIndex();
} }
private void customizeComponents() { private void customizeComponents() {
@ -78,15 +80,16 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
@Override @Override
public void stateChanged(ChangeEvent e) { public void stateChanged(ChangeEvent e) {
if (e.getSource() instanceof JTabbedPane) { if (e.getSource() instanceof JTabbedPane) {
//because we can have two filterPanels open at the same time //If we are switching to a filter panel we should load
//we need to save the settings when we change tabs otherwise //load the filter panel to ensure it is up to date
//they could be overwritten with out of date //incase a filter was addded through the Profile->new->create new filter manner
if (tabbedPane.getSelectedIndex() == INDEX_OF_FILTER_PANEL) { if (tabbedPane.getSelectedIndex() == INDEX_OF_FILTER_PANEL && tabbedPane.getSelectedIndex() != indexOfPreviousTab) {
filterPanel.load(); filterPanel.load();
} }
else { //save the contents of whichever Tab we just switched from
filterPanel.saveSettings(); 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 @Override
public void saveSettings() { public void saveSettings() {
filterPanel.store(); saveTabByIndex(tabbedPane.getSelectedIndex());
settingsPanel.store(); }
/**
* 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"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="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"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="profileListLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Group type="102" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="profileListPane" alignment="1" min="-2" pref="339" max="-2" attributes="0"/> <Group type="102" alignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Component id="newProfileButton" linkSize="5" min="-2" pref="107" max="-2" attributes="0"/>
<Component id="newProfileButton" linkSize="5" min="-2" pref="107" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <Component id="editProfileButton" linkSize="5" min="-2" pref="107" max="-2" attributes="0"/>
<Component id="editProfileButton" linkSize="5" min="-2" pref="107" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <Component id="deleteProfileButton" linkSize="5" min="-2" pref="109" 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> </Group>
<Component id="profileListLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/> <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
</Group> </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> </Group>
<Component id="jSeparator2" min="-2" pref="2" max="-2" attributes="0"/> <Component id="jSeparator2" min="-2" pref="2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
@ -60,7 +66,7 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Component id="ingestWarningLabel" min="-2" max="-2" 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> </Group>
<Component id="profileDescPane" alignment="1" max="32767" attributes="0"/> <Component id="profileDescPane" alignment="1" max="32767" attributes="0"/>
<Component id="selectedModulesPane" 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"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="0" 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="102" 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"/> <Component id="profileDescPane" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
@ -115,9 +118,16 @@
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="selectedModulesLabel" min="-2" max="-2" attributes="0"/> <Component id="selectedModulesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace 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> </Group>
<Component id="profileListPane" pref="415" max="32767" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/> <EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
@ -128,7 +138,7 @@
</Group> </Group>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Component id="jSeparator2" alignment="1" max="32767" attributes="0"/> <Component id="jSeparator2" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</Group> </Group>
@ -355,5 +365,41 @@
<Property name="orientation" type="int" value="1"/> <Property name="orientation" type="int" value="1"/>
</Properties> </Properties>
</Component> </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> </SubComponents>
</Form> </Form>

View File

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

View File

@ -19,39 +19,40 @@
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" 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"/> <Component id="mimeTypeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/> <EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="mimeTypeTextField" max="32767" attributes="0"/> <Component id="mimeTypeTextField" max="32767" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="1" attributes="0"> <Group type="103" alignment="1" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <Group type="103" alignment="0" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="102" alignment="1" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Component id="addSigButton" min="-2" max="-2" 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"/>
<EmptySpace type="unrelated" 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> </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> </Group>
<Group type="102" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/> <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<Component id="postHitCheckBox" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="postHitCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </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> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
@ -65,7 +66,9 @@
<Component id="mimeTypeLabel" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="mimeTypeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="mimeTypeTextField" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="mimeTypeTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </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"/> <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/> <EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Component id="jScrollPane1" min="-2" pref="83" max="-2" attributes="0"/> <Component id="jScrollPane1" min="-2" pref="83" max="-2" attributes="0"/>
@ -207,5 +210,12 @@
</Property> </Property>
</Properties> </Properties>
</Component> </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> </SubComponents>
</Form> </Form>

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -29,6 +29,7 @@ import org.openide.util.NbBundle.Messages;
import static org.sleuthkit.autopsy.modules.filetypeid.AddFileTypePanel.EVENT.SIG_LIST_CHANGED; 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.AddFileTypeSignatureDialog.BUTTON_PRESSED;
import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature; 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. * Panel for adding or editing file types.
@ -39,7 +40,7 @@ class AddFileTypePanel extends javax.swing.JPanel {
private AddFileTypeSignatureDialog addSigDialog; private AddFileTypeSignatureDialog addSigDialog;
private DefaultListModel<FileType.Signature> signaturesListModel; private DefaultListModel<FileType.Signature> signaturesListModel;
/** /**
* Creates a panel for a new file type. * Creates a panel for a new file type.
*/ */
@ -50,7 +51,7 @@ class AddFileTypePanel extends javax.swing.JPanel {
this.addTypeListSelectionListener(); this.addTypeListSelectionListener();
this.enableButtons(); this.enableButtons();
} }
enum EVENT { enum EVENT {
SIG_LIST_CHANGED SIG_LIST_CHANGED
} }
@ -87,7 +88,10 @@ class AddFileTypePanel extends javax.swing.JPanel {
@Messages({"AddMimeTypePanel.emptySigList.message=Must have at least one signature.", @Messages({"AddMimeTypePanel.emptySigList.message=Must have at least one signature.",
"AddMimeTypePanel.emptySigList.title=Invalid Signature List", "AddMimeTypePanel.emptySigList.title=Invalid Signature List",
"AddMimeTypePanel.emptySetName.message=Interesting files set name is required if alert is requested.", "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() { FileType getFileType() {
String typeName = mimeTypeTextField.getText(); String typeName = mimeTypeTextField.getText();
if (typeName.isEmpty()) { if (typeName.isEmpty()) {
@ -97,7 +101,12 @@ class AddFileTypePanel extends javax.swing.JPanel {
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
return null; 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()) { if (this.signaturesListModel.isEmpty()) {
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(null,
Bundle.AddMimeTypePanel_emptySigList_message(), Bundle.AddMimeTypePanel_emptySigList_message(),
@ -155,7 +164,7 @@ class AddFileTypePanel extends javax.swing.JPanel {
deleteSigButton.setEnabled(true); deleteSigButton.setEnabled(true);
} }
} }
boolean hasSignature() { boolean hasSignature() {
return !this.signaturesListModel.isEmpty(); return !this.signaturesListModel.isEmpty();
} }
@ -180,6 +189,7 @@ class AddFileTypePanel extends javax.swing.JPanel {
postHitCheckBox = new javax.swing.JCheckBox(); postHitCheckBox = new javax.swing.JCheckBox();
setNameLabel = new javax.swing.JLabel(); setNameLabel = new javax.swing.JLabel();
setNameTextField = new javax.swing.JTextField(); 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 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 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.setText(org.openide.util.NbBundle.getMessage(AddFileTypePanel.class, "AddFileTypePanel.setNameTextField.text")); // NOI18N
setNameTextField.setEnabled(postHitCheckBox.isSelected()); 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); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
@ -244,27 +256,28 @@ class AddFileTypePanel extends javax.swing.JPanel {
.addComponent(mimeTypeLabel) .addComponent(mimeTypeLabel)
.addGap(18, 18, 18) .addGap(18, 18, 18)
.addComponent(mimeTypeTextField)) .addComponent(mimeTypeTextField))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
.addGroup(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()
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(addSigButton)
.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)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .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.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1) .addComponent(jLabel1)
.addComponent(postHitCheckBox)) .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()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
@ -274,7 +287,9 @@ class AddFileTypePanel extends javax.swing.JPanel {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(mimeTypeLabel) .addComponent(mimeTypeLabel)
.addComponent(mimeTypeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .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) .addComponent(jLabel1)
.addGap(1, 1, 1) .addGap(1, 1, 1)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE) .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.JButton editSigButton;
private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel1;
private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel mimeFormatLabel;
private javax.swing.JLabel mimeTypeLabel; private javax.swing.JLabel mimeTypeLabel;
private javax.swing.JTextField mimeTypeTextField; private javax.swing.JTextField mimeTypeTextField;
private javax.swing.JCheckBox postHitCheckBox; private javax.swing.JCheckBox postHitCheckBox;

View File

@ -80,4 +80,4 @@ FilesSetRulePanel.allRadioButton.text=All
FilesSetDefsPanel.ingoreUnallocCheckbox.text=Ignore Unallocated Space FilesSetDefsPanel.ingoreUnallocCheckbox.text=Ignore Unallocated Space
FilesSetDefsPanel.ingoreUnallocCheckbox.toolTipText=Ignores unallocated space, such as deleted files. May run faster but produce less complete results. FilesSetDefsPanel.ingoreUnallocCheckbox.toolTipText=Ignores unallocated space, such as deleted files. May run faster but produce less complete results.
FilesSetDefsPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes. FilesSetDefsPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes.
FilesSetDefsPanel.allRadioButton.text=All FilesSetDefsPanel.allRadioButton.text=All

View File

@ -29,15 +29,12 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
<Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
</Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/> <Component id="jScrollPane1" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
@ -68,114 +65,135 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" 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"> <Group type="102" alignment="0" attributes="0">
<Component id="newSetButton" linkSize="3" min="-2" max="-2" attributes="0"/> <Group type="103" groupAlignment="1" max="-2" attributes="0">
<EmptySpace min="-2" pref="9" max="-2" attributes="0"/> <Group type="102" alignment="0" attributes="0">
<Component id="editSetButton" linkSize="3" min="-2" max="-2" 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"/> <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> </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> </Group>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="separator" min="-2" max="-2" attributes="0"/> <Component id="separator" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="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="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="fileNameRadioButton" min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" pref="101" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/> <Component id="filesRadioButton" min="-2" pref="47" max="-2" attributes="0"/>
<Component id="fileNameExtensionRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="fileNameRegexCheckbox" min="-2" max="-2" attributes="0"/> <Component id="dirsRadioButton" 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"/>
<EmptySpace 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>
<Group type="102" alignment="0" attributes="0"> <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="103" groupAlignment="0" attributes="0">
<Component id="jLabel5" alignment="0" min="-2" max="-2" attributes="0"/> <Group type="102" alignment="0" attributes="0">
<Component id="jLabel6" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="fileNameRadioButton" min="-2" max="-2" attributes="0"/>
</Group> <EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <Component id="fileNameExtensionRadioButton" min="-2" max="-2" attributes="0"/>
<Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
</Group> <Component id="fileNameRegexCheckbox" min="-2" max="-2" attributes="0"/>
</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> </Group>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/> <Component id="rulePathConditionRegexCheckBox" alignment="0" min="-2" 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>
</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"> <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"/>
<EmptySpace max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0">
<Component id="fileSizeSpinner" max="32767" attributes="0"/> <Component id="rulesListLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fileSizeUnitComboBox" min="-2" pref="81" 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> </Group>
<Component id="fileNameTextField" max="32767" attributes="0"/>
</Group> </Group>
<EmptySpace min="24" pref="28" max="32767" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="setDescScrollPanel" max="32767" attributes="0"/> <Group type="102" alignment="0" attributes="0">
<Component id="rulesListScrollPane" pref="414" max="32767" 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> </Group>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -185,94 +203,94 @@
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="separator" max="32767" 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="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="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Component id="jLabel6" min="-2" max="-2" 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"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="rulesListScrollPane" pref="64" max="32767" attributes="0"/> <Component id="jLabel5" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" pref="1" 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"/>
</Group> </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> </Group>
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/> <EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
</Group> </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> </Group>
</Group> </Group>
@ -868,6 +886,47 @@
</Property> </Property>
</Properties> </Properties>
</Component> </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> </SubComponents>
</Container> </Container>
</SubComponents> </SubComponents>

View File

@ -19,7 +19,9 @@
package org.sleuthkit.autopsy.modules.interestingitems; package org.sleuthkit.autopsy.modules.interestingitems;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -29,11 +31,14 @@ import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.DefaultListModel; import javax.swing.DefaultListModel;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.netbeans.spi.options.OptionsPanelController; import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
@ -55,7 +60,10 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
"FilesSetDefsPanel.megaBytes=Megabytes", "FilesSetDefsPanel.megaBytes=Megabytes",
"FilesSetDefsPanel.gigaBytes=Gigabytes", "FilesSetDefsPanel.gigaBytes=Gigabytes",
"FilesSetDefsPanel.loadError=Error loading interesting files sets from file.", "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 { public static enum PANEL_TYPE {
FILE_INGEST_FILTERS, FILE_INGEST_FILTERS,
@ -93,12 +101,14 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
this.rulesList.addListSelectionListener(new FilesSetDefsPanel.RulesListSelectionListener()); this.rulesList.addListSelectionListener(new FilesSetDefsPanel.RulesListSelectionListener());
this.ingestWarningLabel.setVisible(false); 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 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.mimeTypeComboBox.setVisible(false);
this.jLabel7.setVisible(false); this.jLabel7.setVisible(false);
this.fileSizeUnitComboBox.setVisible(false); this.fileSizeUnitComboBox.setVisible(false);
this.fileSizeSpinner.setVisible(false); this.fileSizeSpinner.setVisible(false);
this.ruleDialogTitle = "FilesSetPanel.ingest.title"; this.ruleDialogTitle = "FilesSetPanel.ingest.title";
this.jLabel8.setVisible(false); this.jLabel8.setVisible(false);
this.equalitySignComboBox.setVisible(false); this.equalitySignComboBox.setVisible(false);
this.ignoreKnownFilesCheckbox.setVisible(false); this.ignoreKnownFilesCheckbox.setVisible(false);
@ -173,17 +183,23 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
} catch (FilesSetsManager.FilesSetsManagerException ex) { } catch (FilesSetsManager.FilesSetsManagerException ex) {
MessageNotifyUtil.Message.error(Bundle.FilesSetDefsPanel_saveError()); MessageNotifyUtil.Message.error(Bundle.FilesSetDefsPanel_saveError());
logger.log(Level.WARNING, Bundle.FilesSetDefsPanel_saveError(), ex);
} }
} }
public void enableButtons(boolean isEnabled) { public void enableButtons(boolean isEnabled) {
boolean setSelected = (FilesSetDefsPanel.this.setsList.getSelectedValue() != null);
boolean ruleSelected = (FilesSetDefsPanel.this.rulesList.getSelectedValue() != null);
canBeEnabled = isEnabled; canBeEnabled = isEnabled;
newRuleButton.setEnabled(isEnabled); newRuleButton.setEnabled(isEnabled);
copySetButton.setEnabled(isEnabled && setSelected);
newSetButton.setEnabled(isEnabled); newSetButton.setEnabled(isEnabled);
editRuleButton.setEnabled(isEnabled); editRuleButton.setEnabled(isEnabled && ruleSelected);
editSetButton.setEnabled(isEnabled); editSetButton.setEnabled(isEnabled && setSelected);
deleteRuleButton.setEnabled(isEnabled); exportSetButton.setEnabled(setSelected);
deleteSetButton.setEnabled(isEnabled); importSetButton.setEnabled(isEnabled);
deleteRuleButton.setEnabled(isEnabled && ruleSelected);
deleteSetButton.setEnabled(isEnabled && setSelected);
ingestWarningLabel.setVisible(!isEnabled); ingestWarningLabel.setVisible(!isEnabled);
} }
@ -213,6 +229,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
} catch (FilesSetsManager.FilesSetsManagerException ex) { } catch (FilesSetsManager.FilesSetsManagerException ex) {
MessageNotifyUtil.Message.error(Bundle.FilesSetDefsPanel_loadError()); MessageNotifyUtil.Message.error(Bundle.FilesSetDefsPanel_loadError());
logger.log(Level.WARNING, Bundle.FilesSetDefsPanel_loadError(), ex);
this.filesSets = new TreeMap<>(); this.filesSets = new TreeMap<>();
} }
@ -242,6 +259,9 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
this.ingoreUnallocCheckbox.setSelected(true); this.ingoreUnallocCheckbox.setSelected(true);
this.newSetButton.setEnabled(true && canBeEnabled); this.newSetButton.setEnabled(true && canBeEnabled);
this.editSetButton.setEnabled(false); this.editSetButton.setEnabled(false);
this.copySetButton.setEnabled(false);
this.exportSetButton.setEnabled(false);
this.importSetButton.setEnabled(true && canBeEnabled);
this.deleteSetButton.setEnabled(false); this.deleteSetButton.setEnabled(false);
} }
@ -275,30 +295,31 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
if (e.getValueIsAdjusting()) { if (e.getValueIsAdjusting()) {
return; return;
} }
FilesSetDefsPanel.this.rulesListModel.clear(); FilesSetDefsPanel.this.rulesListModel.clear();
FilesSetDefsPanel.this.resetRuleComponents(); 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 // Get the selected interesting files set and populate the set
// components. // components.
FilesSet selectedSet = FilesSetDefsPanel.this.setsList.getSelectedValue(); FilesSet selectedSet = FilesSetDefsPanel.this.setsList.getSelectedValue();
if (selectedSet != null) { if (selectedSet != null) {
// Populate the components that display the properties of the // Populate the components that display the properties of the
// selected files set. // selected files set.
FilesSetDefsPanel.this.setDescriptionTextArea.setText(selectedSet.getDescription()); FilesSetDefsPanel.this.setDescriptionTextArea.setText(selectedSet.getDescription());
FilesSetDefsPanel.this.ignoreKnownFilesCheckbox.setSelected(selectedSet.ignoresKnownFiles()); FilesSetDefsPanel.this.ignoreKnownFilesCheckbox.setSelected(selectedSet.ignoresKnownFiles());
FilesSetDefsPanel.this.ingoreUnallocCheckbox.setSelected(selectedSet.ingoresUnallocatedSpace()); FilesSetDefsPanel.this.ingoreUnallocCheckbox.setSelected(selectedSet.ingoresUnallocatedSpace());
// Enable the new, edit and delete set buttons. // Enable the copy, export, edit and delete set buttons.
FilesSetDefsPanel.this.newSetButton.setEnabled(true && canBeEnabled); FilesSetDefsPanel.this.editSetButton.setEnabled(canBeEnabled);
FilesSetDefsPanel.this.editSetButton.setEnabled(true && canBeEnabled); FilesSetDefsPanel.this.deleteSetButton.setEnabled(canBeEnabled);
FilesSetDefsPanel.this.deleteSetButton.setEnabled(true && canBeEnabled); FilesSetDefsPanel.this.copySetButton.setEnabled(canBeEnabled);
FilesSetDefsPanel.this.exportSetButton.setEnabled(true);
// Populate the rule definitions list, sorted by name. // Populate the rule definitions list, sorted by name.
TreeMap<String, FilesSet.Rule> rules = new TreeMap<>(selectedSet.getRules()); TreeMap<String, FilesSet.Rule> rules = new TreeMap<>(selectedSet.getRules());
for (FilesSet.Rule rule : rules.values()) { for (FilesSet.Rule rule : rules.values()) {
FilesSetDefsPanel.this.rulesListModel.addElement(rule); FilesSetDefsPanel.this.rulesListModel.addElement(rule);
} }
// Select the first rule by default. // Select the first rule by default.
if (!FilesSetDefsPanel.this.rulesListModel.isEmpty()) { if (!FilesSetDefsPanel.this.rulesListModel.isEmpty()) {
FilesSetDefsPanel.this.rulesList.setSelectedIndex(0); FilesSetDefsPanel.this.rulesList.setSelectedIndex(0);
@ -391,15 +412,18 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
* Display an interesting files set definition panel in a dialog box and * Display an interesting files set definition panel in a dialog box and
* respond to user interactions with the dialog. * respond to user interactions with the dialog.
* *
* @param selectedSet The currently selected files set, may be null to * @param selectedSet The currently selected files set, may be null to
* indicate a new interesting files set definition is to * indicate a new interesting files set definition is
* be created. * 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. // Create a files set defintion panle.
FilesSetPanel panel; FilesSetPanel panel;
if (selectedSet != null) { if (selectedSet != null) {
// Editing an existing set definition. // Editing an existing set definition.
panel = new FilesSetPanel(selectedSet, panelType); panel = new FilesSetPanel(selectedSet, panelType);
} else { } else {
// Creating a new set definition. // Creating a new set definition.
@ -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. // 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. // 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(), MessageNotifyUtil.Message.error(NbBundle.getMessage(this.getClass(),
"FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text", "FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text",
panel.getFilesSetName())); panel.getFilesSetName()));
@ -431,7 +455,11 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
// Preserve the existing rules from the set being edited. // Preserve the existing rules from the set being edited.
rules.putAll(selectedSet.getRules()); 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>(); fileSizeUnitComboBox = new javax.swing.JComboBox<String>();
ingoreUnallocCheckbox = new javax.swing.JCheckBox(); ingoreUnallocCheckbox = new javax.swing.JCheckBox();
ingestWarningLabel = new javax.swing.JLabel(); 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)); 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 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 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); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout); jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup( jPanel1Layout.setHorizontalGroup(
@ -792,92 +849,105 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .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() .addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(newSetButton) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGap(9, 9, 9) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
.addComponent(editSetButton) .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) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteSetButton)) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(setsListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 344, javax.swing.GroupLayout.PREFERRED_SIZE)) .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) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(separator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .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.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .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.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(fileNameRadioButton) .addGap(101, 101, 101)
.addGap(4, 4, 4) .addComponent(filesRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileNameExtensionRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(fileNameRegexCheckbox)) .addComponent(dirsRadioButton)
.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)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 158, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(allRadioButton))
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addGap(105, 105, 105)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel5) .addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel6)) .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) .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() .addGroup(jPanel1Layout.createSequentialGroup()
.addGap(29, 29, 29)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addGap(22, 22, 22)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel7) .addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel8)) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(18, 18, 18)) .addComponent(jLabel7)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel8))
.addGroup(jPanel1Layout.createSequentialGroup() .addGap(18, 18, 18))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel3) .addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel2)) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(6, 6, 6)) .addComponent(jLabel3)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addComponent(jLabel2))
.addComponent(jLabel4) .addGap(6, 6, 6))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)))) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel4)
.addComponent(mimeTypeComboBox, 0, 313, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED))))
.addComponent(rulePathConditionTextField) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE) .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) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fileSizeSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(rulesListScrollPane, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(setDescScrollPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addComponent(fileNameTextField))) .addGap(8, 8, 8))))
.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))
); );
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.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -888,75 +958,77 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .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) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(setsListLabel) .addComponent(jLabel5)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGap(1, 1, 1))
.addComponent(setsListScrollPane) .addComponent(ingestWarningLabel, javax.swing.GroupLayout.Alignment.TRAILING))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(newSetButton) .addGap(6, 6, 6)
.addComponent(editSetButton) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(deleteSetButton))) .addComponent(ignoreKnownFilesCheckbox)
.addGroup(jPanel1Layout.createSequentialGroup() .addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel1Layout.createSequentialGroup() .addComponent(rulesListLabel)
.addComponent(jLabel6) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(rulesListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 82, Short.MAX_VALUE)
.addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGap(1, 1, 1)) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addComponent(newRuleButton)
.addComponent(ingestWarningLabel) .addComponent(editRuleButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))) .addComponent(deleteRuleButton))
.addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGap(6, 6, 6) .addComponent(jLabel1)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGap(8, 8, 8)
.addComponent(ignoreKnownFilesCheckbox) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(filesRadioButton)
.addComponent(rulesListLabel) .addComponent(dirsRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(allRadioButton))
.addComponent(rulesListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 64, Short.MAX_VALUE) .addGap(8, 8, 8)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel3)
.addComponent(newRuleButton) .addComponent(fileNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(editRuleButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteRuleButton)) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(fileNameRadioButton)
.addComponent(jLabel1) .addComponent(fileNameExtensionRadioButton)
.addGap(8, 8, 8) .addComponent(fileNameRegexCheckbox))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGap(8, 8, 8)
.addComponent(jLabel2) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(filesRadioButton) .addComponent(jLabel4)
.addComponent(dirsRadioButton) .addComponent(rulePathConditionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(allRadioButton)) .addGap(6, 6, 6)
.addGap(16, 16, 16) .addComponent(rulePathConditionRegexCheckBox)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel3) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(fileNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(jLabel7)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(fileNameRadioButton) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(fileNameExtensionRadioButton) .addComponent(jLabel8)
.addComponent(fileNameRegexCheckbox)) .addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(16, 16, 16) .addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jLabel4) .addGap(5, 5, 5))
.addComponent(rulePathConditionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel1Layout.createSequentialGroup()
.addGap(7, 7, 7) .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(rulePathConditionRegexCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(setsListLabel)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel7) .addComponent(setsListScrollPane)
.addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(newSetButton)
.addComponent(jLabel8) .addComponent(editSetButton)
.addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(deleteSetButton))
.addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addGap(5, 5, 5))) .addComponent(copySetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(5, 5, 5)))) .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}); 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); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addComponent(jScrollPane1)
.addComponent(jScrollPane1)
.addGap(0, 0, 0))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -978,7 +1048,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void newSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newSetButtonActionPerformed 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); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_newSetButtonActionPerformed }//GEN-LAST:event_newSetButtonActionPerformed
@ -1026,7 +1096,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
}//GEN-LAST:event_deleteSetButtonActionPerformed }//GEN-LAST:event_deleteSetButtonActionPerformed
private void editSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editSetButtonActionPerformed 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); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_editSetButtonActionPerformed }//GEN-LAST:event_editSetButtonActionPerformed
@ -1040,14 +1110,166 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_newRuleButtonActionPerformed }//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 // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JRadioButton allRadioButton; private javax.swing.JRadioButton allRadioButton;
private javax.swing.JButton copySetButton;
private javax.swing.JButton deleteRuleButton; private javax.swing.JButton deleteRuleButton;
private javax.swing.JButton deleteSetButton; private javax.swing.JButton deleteSetButton;
private javax.swing.JRadioButton dirsRadioButton; private javax.swing.JRadioButton dirsRadioButton;
private javax.swing.JButton editRuleButton; private javax.swing.JButton editRuleButton;
private javax.swing.JButton editSetButton; private javax.swing.JButton editSetButton;
private javax.swing.JComboBox<String> equalitySignComboBox; private javax.swing.JComboBox<String> equalitySignComboBox;
private javax.swing.JButton exportSetButton;
private javax.swing.ButtonGroup fileNameButtonGroup; private javax.swing.ButtonGroup fileNameButtonGroup;
private javax.swing.JRadioButton fileNameExtensionRadioButton; private javax.swing.JRadioButton fileNameExtensionRadioButton;
private javax.swing.JRadioButton fileNameRadioButton; 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.JComboBox<String> fileSizeUnitComboBox;
private javax.swing.JRadioButton filesRadioButton; private javax.swing.JRadioButton filesRadioButton;
private javax.swing.JCheckBox ignoreKnownFilesCheckbox; private javax.swing.JCheckBox ignoreKnownFilesCheckbox;
private javax.swing.JButton importSetButton;
private javax.swing.JLabel ingestWarningLabel; private javax.swing.JLabel ingestWarningLabel;
private javax.swing.JCheckBox ingoreUnallocCheckbox; private javax.swing.JCheckBox ingoreUnallocCheckbox;
private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel1;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * 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.logging.Level;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; 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.NbObjectInputStream;
import org.openide.util.io.NbObjectOutputStream; import org.openide.util.io.NbObjectOutputStream;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil; 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.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
/**
*
* @author oliver
*/
class InterestingItemsFilesSetSettings implements Serializable { class InterestingItemsFilesSetSettings implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -51,9 +55,9 @@ class InterestingItemsFilesSetSettings implements Serializable {
// TSK Framework FilesSet definitions file schema. // TSK Framework FilesSet definitions file schema.
private static final String FILE_SETS_ROOT_TAG = "INTERESTING_FILE_SETS"; //NON-NLS 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 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 IGNORE_KNOWN_FILES_ATTR = "ignoreKnown"; //NON-NLS
private static final String PATH_REGEX_ATTR = "pathRegex"; //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 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 IGNORE_UNALLOCATED_SPACE = "ingoreUnallocated"; //NON-NLS
private static final String PATH_FILTER_ATTR = "pathFilter"; //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 List<String> illegalFileNameChars = FilesSetsManager.getIllegalFileNameChars();
private static final String FILE_SET_TAG = "INTERESTING_FILE_SET"; //NON-NLS 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 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 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 TYPE_FILTER_VALUE_FILES = "file"; //NON-NLS
private static final String XML_ENCODING = "UTF-8"; //NON-NLS private static final String XML_ENCODING = "UTF-8"; //NON-NLS
private static final Logger logger = Logger.getLogger(InterestingItemsFilesSetSettings.class.getName()); 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 TYPE_FILTER_ATTR = "typeFilter"; //NON-NLS
private static final String EXTENSION_RULE_TAG = "EXTENSION"; //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) { private static String readRuleName(Element elem) {
// The rule must have a name. // The rule must have a name.
String ruleName = elem.getAttribute(InterestingItemsFilesSetSettings.NAME_ATTR); String ruleName = elem.getAttribute(NAME_ATTR);
return ruleName; return ruleName;
} }
@ -130,22 +136,34 @@ class InterestingItemsFilesSetSettings implements Serializable {
* @param ruleElement The XML element. * @param ruleElement The XML element.
* *
* @return The path condition, or null if there is an error (logged). * @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) { private static ParentPathCondition readPathCondition(Element ruleElement) throws FilesSetsManager.FilesSetsManagerException {
FilesSet.Rule.ParentPathCondition condition = null; // Read in the optional path condition. Null is o.k., but if the attribute
String path = ruleElement.getAttribute(InterestingItemsFilesSetSettings.PATH_FILTER_ATTR); // is there, be sure it is not malformed.
String pathRegex = ruleElement.getAttribute(InterestingItemsFilesSetSettings.PATH_REGEX_ATTR); ParentPathCondition pathCondition = null;
if (!pathRegex.isEmpty() && path.isEmpty()) { if (!ruleElement.getAttribute(PATH_FILTER_ATTR).isEmpty() || !ruleElement.getAttribute(PATH_REGEX_ATTR).isEmpty()) {
try { String path = ruleElement.getAttribute(PATH_FILTER_ATTR);
Pattern pattern = Pattern.compile(pathRegex); String pathRegex = ruleElement.getAttribute(PATH_REGEX_ATTR);
condition = new FilesSet.Rule.ParentPathCondition(pattern); if (!pathRegex.isEmpty() && path.isEmpty()) {
} catch (PatternSyntaxException ex) { try {
logger.log(Level.SEVERE, "Error compiling " + InterestingItemsFilesSetSettings.PATH_REGEX_ATTR + " regex, ignoring malformed path condition definition", ex); // NON-NLS 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 * Construct a fileset membership rule from the data in an xml element for
* element. * 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 * @return A file set constructed from the conditions available in the XML element
* error is logged). *
* @throws
* org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
*/ */
private static FilesSet.Rule readFileExtensionRule(Element elem) { private static FilesSet.Rule readRule(Element elem) throws FilesSetsManager.FilesSetsManagerException {
String ruleName = InterestingItemsFilesSetSettings.readRuleName(elem); String ruleName = readRuleName(elem);
// The content of the rule tag is a file name extension condition. It may FileNameCondition nameCondition = readNameCondition(elem);
// be a regex, or it may be from a TSK Framework rule definition MetaTypeCondition metaCondition = readMetaTypeCondition(elem);
// with a "*" globbing char. ParentPathCondition pathCondition = readPathCondition(elem);
String content = elem.getTextContent(); MimeTypeCondition mimeCondition = readMimeCondition(elem);
FilesSet.Rule.ExtensionCondition extCondition; FileSizeCondition sizeCondition = readSizeCondition(elem);
String regex = elem.getAttribute(InterestingItemsFilesSetSettings.REGEX_ATTR); //if meta type condition or all four types of conditions the user can create are all null then don't make the rule
if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { if (metaCondition == null || (nameCondition == null && pathCondition == null && mimeCondition == null && sizeCondition == null)) {
// NON-NLS 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
Pattern pattern = compileRegex(content); throw new FilesSetsManager.FilesSetsManagerException(String.format("Invalid Rule in FilesSet xml, missing necessary conditions for %s", ruleName));
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);
} }
// The rule must have a meta-type condition, unless a TSK Framework return new FilesSet.Rule(ruleName, nameCondition, metaCondition, pathCondition, mimeCondition, sizeCondition);
// 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);
} }
/** /**
* 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 * @return The file name condition, or null if none existed
* logged). *
* @throws
* org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
*/ */
private static FilesSet.Rule readFileNameRule(Element elem) { private static FileNameCondition readNameCondition(Element elem) throws FilesSetsManager.FilesSetsManagerException {
String ruleName = InterestingItemsFilesSetSettings.readRuleName(elem); FileNameCondition nameCondition = null;
// 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.
String content = elem.getTextContent(); String content = elem.getTextContent();
FilesSet.Rule.FullNameCondition nameCondition; String regex = elem.getAttribute(REGEX_ATTR);
String regex = elem.getAttribute(InterestingItemsFilesSetSettings.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("*")) { if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { // NON-NLS
// NON-NLS Pattern pattern = compileRegex(content);
Pattern pattern = compileRegex(content); if (pattern != null) {
if (pattern != null) { if (elem.getTagName().equals(NAME_RULE_TAG)) {
nameCondition = new FilesSet.Rule.FullNameCondition(pattern); 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 { } else {
logger.log(Level.SEVERE, "Error compiling " + InterestingItemsFilesSetSettings.NAME_RULE_TAG + " regex, ignoring malformed '{0}' rule definition", ruleName); // NON-NLS for (String illegalChar : illegalFileNameChars) {
return null; 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
} else { throw new FilesSetsManager.FilesSetsManagerException(String.format("File name has illegal character of %s in rule %s", illegalChar, readRuleName(elem)));
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 if (elem.getTagName().equals(NAME_RULE_TAG)) {
return null; 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. return nameCondition;
FilesSet.Rule.MetaTypeCondition metaTypeCondition = InterestingItemsFilesSetSettings.readMetaTypeCondition(elem); }
if (metaTypeCondition == null) {
// Malformed attribute. /**
return null; * 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 return mimeCondition;
// 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); * Construct a file size condition for a FilesSet membership rule from data in an
if (pathCondition == null) { * XML element.
// Malformed attribute. *
return null; * @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 setElem A FilesSet XML element
* @param filesSets A collection to which the set is to be added. * @param filesSets A collection to which the set is to be added.
* @param filePath The source file, used for error reporting. * @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. // The file set must have a unique name.
String setName = setElem.getAttribute(InterestingItemsFilesSetSettings.NAME_ATTR); String setName = setElem.getAttribute(NAME_ATTR);
if (setName.isEmpty()) { 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; return;
} }
if (filesSets.containsKey(setName)) { if (filesSets.containsKey(setName)) {
@ -296,55 +330,39 @@ class InterestingItemsFilesSetSettings implements Serializable {
return; return;
} }
// The file set may have a description. The empty string is o.k. // 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 // The file set may or may not ignore known files. The default behavior
// is to not ignore them. // 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; boolean ignoreKnownFiles = false;
if (!ignoreKnown.isEmpty()) { if (!ignoreKnown.isEmpty()) {
ignoreKnownFiles = Boolean.parseBoolean(ignoreKnown); ignoreKnownFiles = Boolean.parseBoolean(ignoreKnown);
} }
// The file set may or may not skip unallocated space. The default behavior // The file set may or may not skip unallocated space. The default behavior
// is not to skip it. // is not to skip it.
String ignoreUnallocated = setElem.getAttribute(InterestingItemsFilesSetSettings.IGNORE_UNALLOCATED_SPACE); String ignoreUnallocated = setElem.getAttribute(IGNORE_UNALLOCATED_SPACE);
boolean ignoreUnallocatedSpace = false; boolean ignoreUnallocatedSpace = false;
if (!ignoreUnallocated.isEmpty()) { if (!ignoreUnallocated.isEmpty()) {
ignoreUnallocatedSpace = Boolean.parseBoolean(ignoreUnallocated); ignoreUnallocatedSpace = Boolean.parseBoolean(ignoreUnallocated);
} }
// Read file name set membership rules, if any. // Read the set membership rules, if any.
InterestingItemsFilesSetSettings.unnamedLegacyRuleCounter = 1;
Map<String, FilesSet.Rule> rules = new HashMap<>(); Map<String, FilesSet.Rule> rules = new HashMap<>();
NodeList nameRuleElems = setElem.getElementsByTagName(InterestingItemsFilesSetSettings.NAME_RULE_TAG); NodeList allRuleElems = setElem.getChildNodes();
for (int j = 0; j < nameRuleElems.getLength(); ++j) { for (int j = 0; j < allRuleElems.getLength(); ++j) {
Element elem = (Element) nameRuleElems.item(j); if (allRuleElems.item(j) instanceof Element) { //All the children we need to parse here are elements
FilesSet.Rule rule = InterestingItemsFilesSetSettings.readFileNameRule(elem); Element elem = (Element) allRuleElems.item(j);
if (rule != null) { FilesSet.Rule rule = readRule(elem);
if (!rules.containsKey(rule.getUuid())) { if (rule != null) {
rules.put(rule.getUuid(), rule); 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 { } 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; 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 // 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); FilesSet set = new FilesSet(setName, description, ignoreKnownFiles, ignoreUnallocatedSpace, rules);
filesSets.put(set.getName(), set); filesSets.put(set.getName(), set);
} }
// Note: This method takes a file path to support the possibility of // Note: This method takes a file path to support the possibility of
// multiple intersting files set definition files, e.g., one for // multiple intersting files set definition files, e.g., one for
// definitions that ship with Autopsy and one for user definitions. // 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 * @param fileName The name of the file which is expected to store the
* serialized definitions * 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. * @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 { static Map<String, FilesSet> readDefinitionsFile(String fileName, String legacyFileName) throws FilesSetsManager.FilesSetsManagerException {
Map<String, FilesSet> filesSets = readSerializedDefinitions(fileName); Map<String, FilesSet> filesSets = readSerializedDefinitions(fileName);
@ -373,32 +394,50 @@ class InterestingItemsFilesSetSettings implements Serializable {
} }
// Check if the legacy xml file exists. // Check if the legacy xml file exists.
if (!legacyFileName.isEmpty()) { if (!legacyFileName.isEmpty()) {
File defsFile = Paths.get(PlatformUtil.getUserConfigDirectory(), legacyFileName).toFile(); return readDefinitionsXML(Paths.get(PlatformUtil.getUserConfigDirectory(), legacyFileName).toFile());
if (!defsFile.exists()) { }
return filesSets; 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 * Reads an XML file and returns a map of fileSets. Allows for legacy XML
return filesSets; * support as well as importing of file sets to XMLs.
} *
// Parse the XML in the file. * @param xmlFilePath - The Path to the xml file containing the
Document doc = XMLUtil.loadDoc(InterestingItemsFilesSetSettings.class, defsFile.getPath()); * definition(s).
if (doc == null) { *
logger.log(Level.SEVERE, "FilesSet definition file at {0}", defsFile.getPath()); // NON-NLS * @return fileSets - a Map<String, Filesset> of the definition(s) found in
return filesSets; * the xml file.
} *
// Get the root element. * @throws
Element root = doc.getDocumentElement(); * org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException
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 static Map<String, FilesSet> readDefinitionsXML(File xmlFile) throws FilesSetsManager.FilesSetsManagerException {
return filesSets; Map<String, FilesSet> filesSets = new HashMap<>();
} if (!xmlFile.exists()) {
// Read in the files set definitions. return filesSets;
NodeList setElems = root.getElementsByTagName(FILE_SET_TAG); }
for (int i = 0; i < setElems.getLength(); ++i) { // Check if the file can be read.
readFilesSet((Element) setElems.item(i), filesSets, defsFile.getPath()); 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; return filesSets;
} }
@ -422,6 +461,102 @@ class InterestingItemsFilesSetSettings implements Serializable {
return true; 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 * Construct a meta-type condition for a FilesSet membership rule from data
* in an XML element. * in an XML element.
@ -429,30 +564,40 @@ class InterestingItemsFilesSetSettings implements Serializable {
* @param ruleElement The XML element. * @param ruleElement The XML element.
* *
* @return The meta-type condition, or null if there is an error (logged). * @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) { private static MetaTypeCondition readMetaTypeCondition(Element ruleElement) throws FilesSetsManager.FilesSetsManagerException {
FilesSet.Rule.MetaTypeCondition condition = null; MetaTypeCondition metaCondition = null;
String conditionAttribute = ruleElement.getAttribute(InterestingItemsFilesSetSettings.TYPE_FILTER_ATTR); // The rule must have a meta-type condition, unless a TSK Framework
if (!conditionAttribute.isEmpty()) { // definitions file is being read.
switch (conditionAttribute) { if (!ruleElement.getAttribute(TYPE_FILTER_ATTR).isEmpty()) {
case InterestingItemsFilesSetSettings.TYPE_FILTER_VALUE_FILES: String conditionAttribute = ruleElement.getAttribute(TYPE_FILTER_ATTR);
condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); if (!conditionAttribute.isEmpty()) {
break; switch (conditionAttribute) {
case InterestingItemsFilesSetSettings.TYPE_FILTER_VALUE_DIRS: case TYPE_FILTER_VALUE_FILES:
condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.DIRECTORIES); metaCondition = new MetaTypeCondition(MetaTypeCondition.Type.FILES);
break; break;
case InterestingItemsFilesSetSettings.TYPE_FILTER_VALUE_FILES_AND_DIRS: case TYPE_FILTER_VALUE_DIRS:
condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES_AND_DIRECTORIES); metaCondition = new MetaTypeCondition(MetaTypeCondition.Type.DIRECTORIES);
break; break;
default: case TYPE_FILTER_VALUE_ALL:
logger.log(Level.SEVERE, "Found {0} " + InterestingItemsFilesSetSettings.TYPE_FILTER_ATTR + " attribute with unrecognized value ''{0}'', ignoring malformed rule definition", conditionAttribute); // NON-NLS case TYPE_FILTER_VALUE_FILES_AND_DIRS: //converts legacy xmls to current metaCondition terms
break; 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, // Accept TSK Framework FilesSet definitions,
// default to files. // 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"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
String timeStamp = dateFormat.format(Calendar.getInstance().getTime()); String timeStamp = dateFormat.format(Calendar.getInstance().getTime());
String ingestJobOutputDirName = context.getDataSource().getName() + "_" + context.getDataSource().getId() + "_" + timeStamp; String ingestJobOutputDirName = context.getDataSource().getName() + "_" + context.getDataSource().getId() + "_" + timeStamp;
ingestJobOutputDirName = ingestJobOutputDirName.replace(':', '_');
ingestJobOutputDir = Paths.get(Case.getCurrentCase().getModuleDirectory(), VMExtractorIngestModuleFactory.getModuleName(), ingestJobOutputDirName); ingestJobOutputDir = Paths.get(Case.getCurrentCase().getModuleDirectory(), VMExtractorIngestModuleFactory.getModuleName(), ingestJobOutputDirName);
// create module output folder to write extracted virtual machine files to // create module output folder to write extracted virtual machine files to
Files.createDirectories(ingestJobOutputDir); Files.createDirectories(ingestJobOutputDir);

View File

@ -855,6 +855,8 @@ class ReportHTML implements TableReportModule {
if (iconPath == null) { if (iconPath == null) {
// use default Autopsy icon if custom icon is not set // use default Autopsy icon if custom icon is not set
iconPath = "favicon.ico"; iconPath = "favicon.ico";
} else {
iconPath = "agency_logo"; //ref to writeNav() for agency_logo
} }
index.append("<head>\n<title>").append(reportTitle).append(" ").append( index.append("<head>\n<title>").append(reportTitle).append(" ").append(
NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getDisplayName())).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.nio.file.Paths;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel; import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -280,24 +281,37 @@ public final class AutoIngestCasePanel extends JPanel {
*/ */
private void openCase(Path caseMetadataFilePath) { private void openCase(Path caseMetadataFilePath) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try { new SwingWorker<Void, Void>() {
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);
} finally { @Override
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 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 * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2011 - 2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,7 +18,6 @@
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.experimental.autoingest;
import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
@ -29,15 +28,12 @@ import java.nio.file.Paths;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.Instant; import java.time.Instant;
import java.util.Date; 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.concurrent.TimeUnit;
import java.util.List;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import org.sleuthkit.autopsy.ingest.IngestModuleError; import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.ingest.IngestManager.IngestManagerException; 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 * A logger for the processing of an auto ingest job by an auto ingest node. An
@ -107,14 +103,16 @@ final class AutoIngestJobLogger {
* Advanced users doing troubleshooting of an automated ingest cluster * Advanced users doing troubleshooting of an automated ingest cluster
* should also consult the Autopsy and system logs as needed. * should also consult the Autopsy and system logs as needed.
* *
* @param manifestPath The manifest for the auto ingest job. * @param manifestPath The manifest for the auto ingest job.
* @param caseDirectoryPath The case directory. * @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) { AutoIngestJobLogger(Path manifestPath, String dataSourceFileName, Path caseDirectoryPath) {
this.manifestPath = manifestPath; this.manifestPath = manifestPath;
manifestFileName = manifestPath.getFileName().toString(); manifestFileName = manifestPath.getFileName().toString();
this.dataSourceFileName = dataSourceFileName; this.dataSourceFileName = dataSourceFileName;
this.caseDirectoryPath = caseDirectoryPath; this.caseDirectoryPath = caseDirectoryPath;
hostName = NetworkUtils.getLocalHostName(); hostName = NetworkUtils.getLocalHostName();
} }
@ -195,30 +193,34 @@ final class AutoIngestJobLogger {
void logDataSourceProcessorCancelled() throws AutoIngestJobLoggerException, InterruptedException { void logDataSourceProcessorCancelled() throws AutoIngestJobLoggerException, InterruptedException {
log(MessageCategory.WARNING, "Cancelled adding data source to case"); log(MessageCategory.WARNING, "Cancelled adding data source to case");
} }
/** /**
* Logs selection of a data source processor * 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 * @throws AutoIngestJobLoggerException if there is an error writing the log
* message. * message.
* @throws InterruptedException if interrupted while blocked waiting * @throws InterruptedException if interrupted while blocked waiting
* to acquire an exclusive lock on the * to acquire an exclusive lock on the
* log file. * log file.
*/ */
void logDataSourceProcessorSelected(String dsp) throws AutoIngestJobLoggerException, InterruptedException{ void logDataSourceProcessorSelected(String dsp) throws AutoIngestJobLoggerException, InterruptedException {
log(MessageCategory.INFO, "Using data source processor: " + dsp); log(MessageCategory.INFO, "Using data source processor: " + dsp);
} }
/** /**
* Logs the failure of the selected data source processor. * 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 * @throws AutoIngestJobLoggerException if there is an error writing the log
* message. * message.
* @throws InterruptedException if interrupted while blocked waiting * @throws InterruptedException if interrupted while blocked waiting
* to acquire an exclusive lock on the * to acquire an exclusive lock on the
* log file. * 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); log(MessageCategory.ERROR, "Error processing with data source processor: " + dsp);
} }
@ -431,9 +433,10 @@ final class AutoIngestJobLogger {
* log file. * log file.
*/ */
private void log(MessageCategory category, String message) throws AutoIngestJobLoggerException, InterruptedException { 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) { 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)) { 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)); 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) { } 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;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.core.ServicesMonitor; import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.core.ServicesMonitor.ServicesMonitorException; import org.sleuthkit.autopsy.core.ServicesMonitor.ServicesMonitorException;
import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.core.UserPreferencesException; 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;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; 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.AutoIngestUserPreferences;
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration; import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration;
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.SharedConfigurationException; 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;
import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason; import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason;
import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobSettings;
@ -212,7 +211,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
void startUp() throws AutoIngestManagerStartupException { void startUp() throws AutoIngestManagerStartupException {
SYS_LOGGER.log(Level.INFO, "Auto ingest starting"); SYS_LOGGER.log(Level.INFO, "Auto ingest starting");
try { try {
coordinationService = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()); coordinationService = CoordinationService.getInstance();
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
throw new AutoIngestManagerStartupException("Failed to get coordination service", 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.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.experimental.configuration.AutoIngestSettingsPanel.UpdateConfigSwingWorker; import org.sleuthkit.autopsy.experimental.configuration.AutoIngestSettingsPanel.UpdateConfigSwingWorker;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService; 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.Lock;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
@ -86,7 +87,6 @@ public class SharedConfiguration {
private static final String PREFERENCES_FOLDER = "Preferences"; //NON-NLS private static final String PREFERENCES_FOLDER = "Preferences"; //NON-NLS
public static final String FILE_EXPORTER_FOLDER = "Automated File Exporter"; //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 UPLOAD_IN_PROGRESS_FILE = "uploadInProgress"; // NON-NLS
private static final String moduleDirPath = PlatformUtil.getUserConfigDirectory(); private static final String moduleDirPath = PlatformUtil.getUserConfigDirectory();
private static final Logger logger = Logger.getLogger(SharedConfiguration.class.getName()); private static final Logger logger = Logger.getLogger(SharedConfiguration.class.getName());
@ -160,7 +160,7 @@ public class SharedConfiguration {
File remoteFolder = getSharedFolder(); 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) { if (writeLock == null) {
logger.log(Level.INFO, String.format("Failed to lock %s - another node is currently uploading or downloading configuration", remoteFolder.getAbsolutePath())); logger.log(Level.INFO, String.format("Failed to lock %s - another node is currently uploading or downloading configuration", remoteFolder.getAbsolutePath()));
return SharedConfigResult.LOCKED; return SharedConfigResult.LOCKED;
@ -230,7 +230,7 @@ public class SharedConfiguration {
File remoteFolder = getSharedFolder(); 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) { if (readLock == null) {
return SharedConfigResult.LOCKED; return SharedConfigResult.LOCKED;
} }

View File

@ -19,8 +19,8 @@
<dependency conf="autopsy->*" org="org.apache.solr" name="solr-solrj" rev="6.2.1"/> <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-lang" name="commons-lang" rev="2.4"/>
<dependency conf="autopsy->*" org="commons-validator" name="commons-validator" rev="1.5.1"/> <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 <!-- metadata-extractor is required by Tika but it depends on version 2.6.2 which suffers
from an XMP library issue. --> from an XMP library issue. -->
<dependency conf="autopsy->*" org="com.drewnoakes" name="metadata-extractor" rev="2.7.2" /> <dependency conf="autopsy->*" org="com.drewnoakes" name="metadata-extractor" rev="2.7.2" />
@ -37,6 +37,10 @@
<dependency conf="slf4j-libs->default" org="org.slf4j" name="slf4j-log4j12" rev="1.7.10"/> <dependency conf="slf4j-libs->default" org="org.slf4j" name="slf4j-log4j12" rev="1.7.10"/>
<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="jcl-over-slf4j" rev="1.7.10"/>
<dependency conf="slf4j-libs->default" org="org.slf4j" name="jul-to-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> </dependencies>
</ivy-module> </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-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.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.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-jdk15on-1.54.jar=release/modules/ext/bcmail-jdk15on-1.54.jar
file.reference.bcmail-jdk15-1.45.jar=release/modules/ext/bcmail-jdk15-1.45.jar file.reference.bcpkix-jdk15on-1.54.jar=release/modules/ext/bcpkix-jdk15on-1.54.jar
file.reference.bcprov-jdk15-1.45.jar=release/modules/ext/bcprov-jdk15-1.45.jar file.reference.bcprov-jdk15on-1.54.jar=release/modules/ext/bcprov-jdk15on-1.54.jar
file.reference.commons-compress-1.5.jar=release/modules/ext/commons-compress-1.5.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-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-io-2.5.jar=release/modules/ext/commons-io-2.5.jar
file.reference.commons-lang-2.4-sources.jar=release/modules/ext/commons-lang-2.4-sources.jar file.reference.commons-lang-2.6.jar=release/modules/ext/commons-lang-2.6.jar
file.reference.commons-lang-2.4.jar=release/modules/ext/commons-lang-2.4.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.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.commons-validator-1.5.1-javadoc.jar=release/modules/ext/commons-validator-1.5.1-javadoc.jar
file.reference.fontbox-1.8.4.jar=release/modules/ext/fontbox-1.8.4.jar file.reference.commons-validator-1.5.1-sources.jar=release/modules/ext/commons-validator-1.5.1-sources.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.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.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.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.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.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.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-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-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.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.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.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.lucene-analyzers-common-4.0.0.jar=release/modules/ext/lucene-analyzers-common-4.0.0.jar
file.reference.netcdf-4.2-min.jar=release/modules/ext/netcdf-4.2-min.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.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.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.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.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.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.pdfbox-2.0.3.jar=release/modules/ext/pdfbox-2.0.3.jar
file.reference.poi-3.10-beta2.jar=release/modules/ext/poi-3.10-beta2.jar file.reference.pdfbox-debugger-2.0.3.jar=release/modules/ext/pdfbox-debugger-2.0.3.jar
file.reference.poi-ooxml-3.10-beta2.jar=release/modules/ext/poi-ooxml-3.10-beta2.jar file.reference.pdfbox-tools-2.0.3.jar=release/modules/ext/pdfbox-tools-2.0.3.jar
file.reference.poi-ooxml-schemas-3.10-beta2.jar=release/modules/ext/poi-ooxml-schemas-3.10-beta2.jar file.reference.plexus-utils-1.5.6.jar=release/modules/ext/plexus-utils-1.5.6.jar
file.reference.poi-scratchpad-3.10-beta2.jar=release/modules/ext/poi-scratchpad-3.10-beta2.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.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.quartz-2.2.0.jar=release/modules/ext/quartz-2.2.0.jar
file.reference.slf4j-api-1.7.6.jar=release/modules/ext/slf4j-api-1.7.6.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-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-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-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.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-core-1.14.jar=release/modules/ext/tika-core-1.14.jar
file.reference.tika-parsers-1.5.jar=release/modules/ext/tika-parsers-1.5.jar file.reference.tika-parsers-1.14-javadoc.jar=release/modules/ext/tika-parsers-1.14-javadoc.jar
file.reference.vorbis-java-core-0.1-tests.jar=release/modules/ext/vorbis-java-core-0.1-tests.jar file.reference.tika-parsers-1.14-sources.jar=release/modules/ext/tika-parsers-1.14-sources.jar
file.reference.vorbis-java-tika-0.1.jar=release/modules/ext/vorbis-java-tika-0.1.jar file.reference.tika-parsers-1.14.jar=release/modules/ext/tika-parsers-1.14.jar
file.reference.wstx-asl-3.2.7.jar=release/modules/ext/wstx-asl-3.2.7.jar file.reference.udunits-4.5.5.jar=release/modules/ext/udunits-4.5.5.jar
file.reference.xmlbeans-2.3.0.jar=release/modules/ext/xmlbeans-2.3.0.jar file.reference.uimafit-core-2.1.0.jar=release/modules/ext/uimafit-core-2.1.0.jar
file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.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.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.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial 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 license.file=../LICENSE-2.0.txt
nbm.homepage=http://www.sleuthkit.org/autopsy/ nbm.homepage=http://www.sleuthkit.org/autopsy/
nbm.needs.restart=true 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 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> </dependency>
</module-dependencies> </module-dependencies>
<public-packages> <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.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.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> <package>org.sleuthkit.autopsy.keywordsearch</package>
</public-packages> </public-packages>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/bcmail-jdk15-1.45.jar</runtime-relative-path> <runtime-relative-path>ext/commons-validator-1.5.1-sources.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bcmail-jdk15-1.45.jar</binary-origin> <binary-origin>release/modules/ext/commons-validator-1.5.1-sources.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/tika-parsers-1.5.jar</runtime-relative-path> <runtime-relative-path>ext/commons-digester-1.8.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tika-parsers-1.5.jar</binary-origin> <binary-origin>release/modules/ext/commons-digester-1.8.1.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/jericho-html-3.3.jar</runtime-relative-path> <runtime-relative-path>ext/jwnl-1.3.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jericho-html-3.3.jar</binary-origin> <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>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/org.osgi.compendium-4.0.0.jar</runtime-relative-path> <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> <binary-origin>release/modules/ext/org.osgi.compendium-4.0.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/slf4j-api-1.7.6.jar</runtime-relative-path> <runtime-relative-path>ext/geoapi-3.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/slf4j-api-1.7.6.jar</binary-origin> <binary-origin>release/modules/ext/geoapi-3.0.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/xmlbeans-2.3.0.jar</runtime-relative-path> <runtime-relative-path>ext/hamcrest-core-1.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmlbeans-2.3.0.jar</binary-origin> <binary-origin>release/modules/ext/hamcrest-core-1.3.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/jempbox-1.8.4.jar</runtime-relative-path> <runtime-relative-path>ext/boilerpipe-1.1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jempbox-1.8.4.jar</binary-origin> <binary-origin>release/modules/ext/boilerpipe-1.1.0.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>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-logging-api-1.1.jar</runtime-relative-path> <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> <binary-origin>release/modules/ext/commons-logging-api-1.1.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/asm-all-3.1.jar</runtime-relative-path> <runtime-relative-path>ext/jakarta-regexp-1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/asm-all-3.1.jar</binary-origin> <binary-origin>release/modules/ext/jakarta-regexp-1.4.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/solr-solrj-6.2.1-javadoc.jar</runtime-relative-path> <runtime-relative-path>ext/xmlbeans-2.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/solr-solrj-6.2.1-javadoc.jar</binary-origin> <binary-origin>release/modules/ext/xmlbeans-2.6.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/poi-3.10-beta2.jar</runtime-relative-path> <runtime-relative-path>ext/maven-scm-api-1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-3.10-beta2.jar</binary-origin> <binary-origin>release/modules/ext/maven-scm-api-1.4.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/icu4j-3.8.jar</runtime-relative-path> <runtime-relative-path>ext/quartz-2.2.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/icu4j-3.8.jar</binary-origin> <binary-origin>release/modules/ext/quartz-2.2.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/fontbox-1.8.4.jar</runtime-relative-path> <runtime-relative-path>ext/jackcess-2.1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/fontbox-1.8.4.jar</binary-origin> <binary-origin>release/modules/ext/jackcess-2.1.4.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/xmpcore-5.1.2.jar</runtime-relative-path> <runtime-relative-path>ext/slf4j-api-1.7.12.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmpcore-5.1.2.jar</binary-origin> <binary-origin>release/modules/ext/slf4j-api-1.7.12.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/metadata-extractor-2.7.2.jar</runtime-relative-path> <runtime-relative-path>ext/guava-17.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/metadata-extractor-2.7.2.jar</binary-origin> <binary-origin>release/modules/ext/guava-17.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/tagsoup-1.2.1.jar</runtime-relative-path> <runtime-relative-path>ext/opennlp-maxent-3.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tagsoup-1.2.1.jar</binary-origin> <binary-origin>release/modules/ext/opennlp-maxent-3.0.3.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-compress-1.5.jar</runtime-relative-path> <runtime-relative-path>ext/jVinci-2.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-compress-1.5.jar</binary-origin> <binary-origin>release/modules/ext/jVinci-2.6.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-lang-2.4-javadoc.jar</runtime-relative-path> <runtime-relative-path>ext/json-simple-1.1.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-lang-2.4-javadoc.jar</binary-origin> <binary-origin>release/modules/ext/json-simple-1.1.1.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/org.osgi.core-4.0.0.jar</runtime-relative-path> <runtime-relative-path>ext/sis-utility-0.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/org.osgi.core-4.0.0.jar</binary-origin> <binary-origin>release/modules/ext/sis-utility-0.6.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/httpclient-4.4.1.jar</runtime-relative-path> <runtime-relative-path>ext/jj2000-5.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/httpclient-4.4.1.jar</binary-origin> <binary-origin>release/modules/ext/jj2000-5.2.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/isoparser-1.0-RC-1.jar</runtime-relative-path> <runtime-relative-path>ext/jhighlight-1.0.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/isoparser-1.0-RC-1.jar</binary-origin> <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>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/log4j-1.2.17.jar</runtime-relative-path> <runtime-relative-path>ext/log4j-1.2.17.jar</runtime-relative-path>
<binary-origin>release/modules/ext/log4j-1.2.17.jar</binary-origin> <binary-origin>release/modules/ext/log4j-1.2.17.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-lang-2.4-sources.jar</runtime-relative-path> <runtime-relative-path>ext/ctakes-utils-3.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-lang-2.4-sources.jar</binary-origin> <binary-origin>release/modules/ext/ctakes-utils-3.2.2.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>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/solr-solrj-6.2.1.jar</runtime-relative-path> <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> <binary-origin>release/modules/ext/solr-solrj-6.2.1.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/poi-scratchpad-3.10-beta2.jar</runtime-relative-path> <runtime-relative-path>ext/apache-mime4j-dom-0.7.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-scratchpad-3.10-beta2.jar</binary-origin> <binary-origin>release/modules/ext/apache-mime4j-dom-0.7.2.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/netcdf-4.2-min.jar</runtime-relative-path> <runtime-relative-path>ext/commons-compress-1.12.jar</runtime-relative-path>
<binary-origin>release/modules/ext/netcdf-4.2-min.jar</binary-origin> <binary-origin>release/modules/ext/commons-compress-1.12.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/vorbis-java-core-0.1-tests.jar</runtime-relative-path> <runtime-relative-path>ext/openaifsm-0.0.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/vorbis-java-core-0.1-tests.jar</binary-origin> <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>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-io-2.5.jar</runtime-relative-path> <runtime-relative-path>ext/commons-io-2.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-io-2.5.jar</binary-origin> <binary-origin>release/modules/ext/commons-io-2.5.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-codec-1.5.jar</runtime-relative-path> <runtime-relative-path>ext/junit-4.11.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-codec-1.5.jar</binary-origin> <binary-origin>release/modules/ext/junit-4.11.jar</binary-origin>
</class-path-extension> </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> <class-path-extension>
<runtime-relative-path>ext/jericho-html-3.3-sources.jar</runtime-relative-path> <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> <binary-origin>release/modules/ext/jericho-html-3.3-sources.jar</binary-origin>
</class-path-extension> </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> <class-path-extension>
<runtime-relative-path>ext/juniversalchardet-1.0.3.jar</runtime-relative-path> <runtime-relative-path>ext/juniversalchardet-1.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/juniversalchardet-1.0.3.jar</binary-origin> <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> <binary-origin>release/modules/ext/org.apache.felix.scr.annotations-1.6.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/noggit-0.6.jar</runtime-relative-path> <runtime-relative-path>ext/commons-lang-2.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/noggit-0.6.jar</binary-origin> <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>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/apache-mime4j-core-0.7.2.jar</runtime-relative-path> <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> <binary-origin>release/modules/ext/apache-mime4j-core-0.7.2.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/httpmime-4.4.1.jar</runtime-relative-path> <runtime-relative-path>ext/rome-utils-1.5.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/httpmime-4.4.1.jar</binary-origin> <binary-origin>release/modules/ext/rome-utils-1.5.1.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/qdox-1.12.jar</runtime-relative-path> <runtime-relative-path>ext/pdfbox-tools-2.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/qdox-1.12.jar</binary-origin> <binary-origin>release/modules/ext/pdfbox-tools-2.0.3.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/httpcore-4.4.1.jar</runtime-relative-path> <runtime-relative-path>ext/sis-storage-0.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/httpcore-4.4.1.jar</binary-origin> <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>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-validator-1.5.1.jar</runtime-relative-path> <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> <binary-origin>release/modules/ext/commons-validator-1.5.1.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-validator-1.5.1.jar</runtime-relative-path> <runtime-relative-path>ext/uimafit-core-2.1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-validator-1.5.1.jar</binary-origin> <binary-origin>release/modules/ext/uimafit-core-2.1.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-lang-2.4.jar</runtime-relative-path> <runtime-relative-path>ext/cleartk-util-2.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-lang-2.4.jar</binary-origin> <binary-origin>release/modules/ext/cleartk-util-2.0.0.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>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/jdom-1.0.jar</runtime-relative-path> <runtime-relative-path>ext/jdom-1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jdom-1.0.jar</binary-origin> <binary-origin>release/modules/ext/jdom-1.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/poi-ooxml-schemas-3.10-beta2.jar</runtime-relative-path> <runtime-relative-path>ext/cxf-core-3.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-schemas-3.10-beta2.jar</binary-origin> <binary-origin>release/modules/ext/cxf-core-3.0.3.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/pdfbox-1.8.4.jar</runtime-relative-path> <runtime-relative-path>ext/regexp-1.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/pdfbox-1.8.4.jar</binary-origin> <binary-origin>release/modules/ext/regexp-1.3.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/wstx-asl-3.2.7.jar</runtime-relative-path> <runtime-relative-path>ext/commons-beanutils-1.9.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/wstx-asl-3.2.7.jar</binary-origin> <binary-origin>release/modules/ext/commons-beanutils-1.9.2.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/aspectjrt-1.6.11.jar</runtime-relative-path> <runtime-relative-path>ext/ehcache-core-2.6.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/aspectjrt-1.6.11.jar</binary-origin> <binary-origin>release/modules/ext/ehcache-core-2.6.2.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/dom4j-1.6.1.jar</runtime-relative-path> <runtime-relative-path>ext/spring-context-3.1.2.RELEASE.jar</runtime-relative-path>
<binary-origin>release/modules/ext/dom4j-1.6.1.jar</binary-origin> <binary-origin>release/modules/ext/spring-context-3.1.2.RELEASE.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/bcprov-jdk15-1.45.jar</runtime-relative-path> <runtime-relative-path>ext/ctakes-type-system-3.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bcprov-jdk15-1.45.jar</binary-origin> <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> </class-path-extension>
</data> </data>
</configuration> </configuration>

View File

@ -89,8 +89,17 @@ class AddKeywordsDialog extends javax.swing.JDialog {
* Intended to be used to redisplay any keywords that contained errors * Intended to be used to redisplay any keywords that contained errors
* @param initialKeywords * @param initialKeywords
*/ */
void setInitialKeywordList(String initialKeywords){ void setInitialKeywordList(String initialKeywords, boolean isLiteral, boolean isWholeWord){
keywordTextArea.setText(initialKeywords); 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.keywordDupesSkippedPlural.text={0} keywords were already in the list.
GlobalEditListPanel.keywordErrors.text={0} keyword could not be parsed. Please review and try again. 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. 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.ServiceName=Solr Keyword Search Service
SolrSearchService.IndexUpgradeDialog.title=Text Index Upgrade Required In Order To Open Case 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.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.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> 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.Port=\u30dd\u30fc\u30c8\u756a\u53f7\u304c\u7121\u52b9\u3067\u3059\u3002
SolrConnectionCheck.MissingHostname=hostname\u304c\u6b20\u3051\u3066\u307e\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 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 @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
String changed = evt.getPropertyName(); if (RuntimeProperties.runningWithGUI()) {
if (changed.equals(Case.Events.CURRENT_CASE.toString())) { String changed = evt.getPropertyName();
dropPanel.clearSearchBox(); if (changed.equals(Case.Events.CURRENT_CASE.toString())) {
if (RuntimeProperties.runningWithGUI() || null == evt.getNewValue()) { if (null != evt.getNewValue()) {
try { /*
Server server = KeywordSearch.getServer(); * A case has been opened.
Index indexInfo = server.getIndexInfo(); */
if (server.coreIsOpen() && IndexFinder.getCurrentSolrVersion().equals(indexInfo.getSolrVersion())) { try {
boolean schemaIsCurrent = IndexFinder.getCurrentSchemaVersion().equals(indexInfo.getSchemaVersion()); Server server = KeywordSearch.getServer();
listsButton.setEnabled(schemaIsCurrent); Index indexInfo = server.getIndexInfo();
searchDropButton.setEnabled(true); if (server.coreIsOpen() && IndexFinder.getCurrentSolrVersion().equals(indexInfo.getSolrVersion())) {
dropPanel.setRegexSearchEnabled(schemaIsCurrent); /*
active = true; * Solr version is current, so check the Solr
} else { * 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); searchDropButton.setEnabled(false);
listsButton.setEnabled(false); listsButton.setEnabled(false);
active = false; active = false;
} }
} catch (KeywordSearchModuleException ex) { } else {
logger.log(Level.SEVERE, "Error getting text index info", ex); //NON-NLS /*
* A case has been closed.
*/
dropPanel.clearSearchBox();
searchDropButton.setEnabled(false); searchDropButton.setEnabled(false);
listsButton.setEnabled(false); listsButton.setEnabled(false);
active = false; active = false;

View File

@ -44,52 +44,34 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" 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"> <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="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Component id="jScrollPane1" pref="483" max="32767" 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>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="keywordsLabel" min="-2" max="-2" attributes="0"/> <Component id="ingestMessagesCheckbox" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/> <Component id="newKeywordsButton" linkSize="3" min="-2" pref="133" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
<Component id="ingestMessagesCheckbox" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="editWordButton" linkSize="3" min="-2" pref="132" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
<Component id="exportButton" min="-2" max="-2" attributes="0"/> <Component id="deleteWordButton" linkSize="3" min="-2" pref="144" 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>
</Group> </Group>
</Group> </Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -98,34 +80,17 @@
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="keywordsLabel" min="-2" max="-2" attributes="0"/> <Component id="keywordsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="117" max="32767" attributes="0"/> <Component id="jScrollPane1" pref="257" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/> <EmptySpace 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"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="exportButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="deleteWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="saveListButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="newKeywordsButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteListButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="editWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </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>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -162,61 +127,6 @@
</Component> </Component>
</SubComponents> </SubComponents>
</Container> </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"> <Component class="javax.swing.JCheckBox" name="ingestMessagesCheckbox">
<Properties> <Properties>
<Property name="selected" type="boolean" value="true"/> <Property name="selected" type="boolean" value="true"/>
@ -238,58 +148,43 @@
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="keywordOptionsLabel"> <Component class="javax.swing.JButton" name="newKeywordsButton">
<Properties> <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"> <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> </Property>
</Properties> </Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newKeywordsButtonActionPerformed"/>
</Events>
</Component> </Component>
<Component class="javax.swing.JLabel" name="listOptionsLabel"> <Component class="javax.swing.JButton" name="deleteWordButton">
<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">
<Properties> <Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/delete16.png"/> <Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/delete16.png"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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> </Property>
</Properties> </Properties>
<Events> <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> </Events>
</Component> </Component>
<Component class="javax.swing.JButton" name="saveListButton"> <Component class="javax.swing.JButton" name="editWordButton">
<Properties> <Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> <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>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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;)"/> <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>
</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;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <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> </Events>
</Component> </Component>
</SubComponents> </SubComponents>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,22 +19,17 @@
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; import java.util.regex.PatternSyntaxException;
import javax.swing.JFileChooser;
import javax.swing.JTable; import javax.swing.JTable;
import javax.swing.ListSelectionModel; import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.netbeans.spi.options.OptionsPanelController; import org.netbeans.spi.options.OptionsPanelController;
@ -64,8 +59,6 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
private void customizeComponents() { private void customizeComponents() {
newKeywordsButton.setToolTipText((NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.addWordToolTip"))); 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")); deleteWordButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.removeSelectedMsg"));
keywordTable.getParent().setBackground(keywordTable.getBackground()); keywordTable.getParent().setBackground(keywordTable.getBackground());
@ -87,11 +80,10 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
lsm.addListSelectionListener(new ListSelectionListener() { lsm.addListSelectionListener(new ListSelectionListener() {
@Override @Override
public void valueChanged(ListSelectionEvent e) { public void valueChanged(ListSelectionEvent e) {
if (lsm.isSelectionEmpty() || currentKeywordList.isEditable() || IngestManager.getInstance().isIngestRunning()) { boolean canDelete = !(lsm.isSelectionEmpty() || currentKeywordList.isEditable() || IngestManager.getInstance().isIngestRunning());
deleteWordButton.setEnabled(false); boolean canEdit = canDelete && (lsm.getMaxSelectionIndex() == lsm.getMinSelectionIndex()); //edit only enabled with single selection
} else { deleteWordButton.setEnabled(canDelete);
deleteWordButton.setEnabled(true); editWordButton.setEnabled(canEdit);
}
} }
}); });
@ -109,322 +101,56 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
} }
}); });
} }
/**
* Enables and disables buttons on this panel based on the current state.
*/
void setButtonStates() { void setButtonStates() {
boolean isIngestRunning = IngestManager.getInstance().isIngestRunning(); boolean isIngestRunning = IngestManager.getInstance().isIngestRunning();
boolean isListSelected = currentKeywordList != null; boolean isListSelected = currentKeywordList != null;
// items that only need a selected list // items that only need a selected list
boolean canEditList = ((isListSelected == true) && (isIngestRunning == false)); boolean canEditList = isListSelected && !isIngestRunning;
ingestMessagesCheckbox.setEnabled(canEditList); ingestMessagesCheckbox.setEnabled(canEditList);
ingestMessagesCheckbox.setSelected(currentKeywordList != null && currentKeywordList.getIngestMessages()); ingestMessagesCheckbox.setSelected(currentKeywordList != null && currentKeywordList.getIngestMessages());
listOptionsLabel.setEnabled(canEditList);
listOptionsSeparator.setEnabled(canEditList);
// items that need an unlocked list w/out ingest running // items that need an unlocked list w/out ingest running
boolean isListLocked = ((isListSelected == false) || (currentKeywordList.isEditable())); boolean canAddWord = canEditList && !currentKeywordList.isEditable();
boolean canAddWord = isListSelected && !isIngestRunning && !isListLocked;
newKeywordsButton.setEnabled(canAddWord); newKeywordsButton.setEnabled(canAddWord);
keywordOptionsLabel.setEnabled(canAddWord);
keywordOptionsSeparator.setEnabled(canAddWord);
deleteListButton.setEnabled(canAddWord);
// items that need a non-empty list // items that need a non-empty list
if ((currentKeywordList == null) || (currentKeywordList.getKeywords().isEmpty())) { if ((currentKeywordList == null) || (currentKeywordList.getKeywords().isEmpty())) {
saveListButton.setEnabled(false);
exportButton.setEnabled(false);
deleteWordButton.setEnabled(false); deleteWordButton.setEnabled(false);
} else { editWordButton.setEnabled(false);
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.
} }
} }
/** /**
* This method is called from within the constructor to initialize the form. * Adds keywords to a keyword list, returns true if at least one keyword was successfully added and no
* WARNING: Do NOT modify this code. The content of this method is always * duplicates were found.
* regenerated by the Form Editor. *
* @return - true or false
*/ */
@SuppressWarnings("unchecked") private boolean addKeywordsAction(String existingKeywords, boolean isLiteral, boolean isWholeWord) {
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents String keywordsToRedisplay = existingKeywords;
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 = "";
AddKeywordsDialog dialog = new AddKeywordsDialog(); AddKeywordsDialog dialog = new AddKeywordsDialog();
int goodCount; int goodCount = 0;
int dupeCount; int dupeCount = 0;
int badCount = 1; // Default to 1 so we enter the loop the first time int badCount = 1; // Default to 1 so we enter the loop the first time
while(badCount > 0){ while (badCount > 0) {
dialog.setInitialKeywordList(keywordsToRedisplay); dialog.setInitialKeywordList(keywordsToRedisplay, isLiteral, isWholeWord);
dialog.display(); dialog.display();
goodCount = 0; goodCount = 0;
dupeCount = 0; dupeCount = 0;
badCount = 0; badCount = 0;
keywordsToRedisplay = ""; keywordsToRedisplay = "";
if(!dialog.getKeywords().isEmpty()){
if (!dialog.getKeywords().isEmpty()) {
for(String newWord:dialog.getKeywords()){ for (String newWord : dialog.getKeywords()) {
if (newWord.isEmpty()) { if (newWord.isEmpty()) {
continue; continue;
} }
@ -459,30 +185,30 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
XmlKeywordSearchList.getCurrent().addList(currentKeywordList); XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
if((badCount > 0) || (dupeCount > 0)){ if ((badCount > 0) || (dupeCount > 0)) {
// Display the error counts to the user // Display the error counts to the user
// The add keywords dialog will pop up again if any were invalid with any // The add keywords dialog will pop up again if any were invalid with any
// invalid entries (valid entries and dupes will disappear) // invalid entries (valid entries and dupes will disappear)
String summary = ""; String summary = "";
KeywordSearchUtil.DIALOG_MESSAGE_TYPE level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO; KeywordSearchUtil.DIALOG_MESSAGE_TYPE level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO;
if(goodCount > 0){ if (goodCount > 0) {
if(goodCount > 1){ if (goodCount > 1) {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordsAddedPlural.text", goodCount) + "\n"; summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordsAddedPlural.text", goodCount) + "\n";
} else { } else {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordsAdded.text", goodCount) + "\n"; summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordsAdded.text", goodCount) + "\n";
} }
} }
if(dupeCount > 0){ if (dupeCount > 0) {
if(dupeCount > 1){ if (dupeCount > 1) {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordDupesSkippedPlural.text", dupeCount) + "\n"; summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordDupesSkippedPlural.text", dupeCount) + "\n";
} else { } else {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordDupesSkipped.text", dupeCount) + "\n"; summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordDupesSkipped.text", dupeCount) + "\n";
} }
level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN; level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN;
} }
if(badCount > 0){ if (badCount > 0) {
if(badCount > 1){ if (badCount > 1) {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordErrorsPlural.text", badCount) + "\n"; summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordErrorsPlural.text", badCount) + "\n";
} else { } else {
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordErrors.text", badCount) + "\n"; summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordErrors.text", badCount) + "\n";
@ -496,24 +222,185 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
} }
setFocusOnKeywordTextBox(); setFocusOnKeywordTextBox();
setButtonStates(); 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 }//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 // 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 deleteWordButton;
private javax.swing.JButton exportButton; private javax.swing.JButton editWordButton;
private javax.swing.JCheckBox ingestMessagesCheckbox; private javax.swing.JCheckBox ingestMessagesCheckbox;
private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel keywordOptionsLabel;
private javax.swing.JSeparator keywordOptionsSeparator;
private javax.swing.JTable keywordTable; private javax.swing.JTable keywordTable;
private javax.swing.JLabel keywordsLabel; private javax.swing.JLabel keywordsLabel;
private javax.swing.JPanel listEditorPanel; private javax.swing.JPanel listEditorPanel;
private javax.swing.JLabel listOptionsLabel;
private javax.swing.JSeparator listOptionsSeparator;
private javax.swing.JButton newKeywordsButton; private javax.swing.JButton newKeywordsButton;
private javax.swing.JButton saveListButton;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
@Override @Override
@ -554,14 +441,6 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
currentKeywordList = list; currentKeywordList = list;
} }
void addDeleteButtonActionPerformed(ActionListener l) {
deleteListButton.addActionListener(l);
}
void addSaveButtonActionPerformed(ActionListener l) {
saveListButton.addActionListener(l);
}
private class KeywordTableModel extends AbstractTableModel { private class KeywordTableModel extends AbstractTableModel {
@Override @Override

View File

@ -41,13 +41,18 @@
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/> <Border info="null"/>
</Property> </Property>
<Property name="dividerLocation" type="int" value="275"/> <Property name="dividerLocation" type="int" value="300"/>
<Property name="dividerSize" type="int" value="1"/> <Property name="dividerSize" type="int" value="1"/>
</Properties> </Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents> <SubComponents>
<Container class="javax.swing.JPanel" name="leftPanel"> <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> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/> <JSplitPaneConstraints position="left"/>
@ -57,7 +62,7 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="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> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
@ -82,7 +87,7 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="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> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * 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.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
@ -41,68 +42,32 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
private void customizeComponents() { private void customizeComponents() {
listsManagementPanel.addListSelectionListener(editListPanel); listsManagementPanel.addListSelectionListener(editListPanel);
editListPanel.addDeleteButtonActionPerformed(new ActionListener() { listsManagementPanel.addDeleteButtonActionPerformed(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { 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)) { 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(); String toDelete = editListPanel.getCurrentKeywordList().getName();
editListPanel.setCurrentKeywordList(null); deleteAction(toDelete);
editListPanel.setButtonStates();
XmlKeywordSearchList deleter = XmlKeywordSearchList.getCurrent();
deleter.deleteList(toDelete);
listsManagementPanel.resync(); listsManagementPanel.resync();
} }
} }
}); });
editListPanel.addSaveButtonActionPerformed(new ActionListener() { listsManagementPanel.addRenameButtonActionPerformed(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
final String FEATURE_NAME = NbBundle.getMessage(this.getClass(), String toDelete = editListPanel.getCurrentKeywordList().getName();
"KeywordSearchGlobalListSettingsPanel.component.featureName.text"); if (copyAction()) {
KeywordList currentKeywordList = editListPanel.getCurrentKeywordList(); deleteAction(toDelete);
listsManagementPanel.resync();
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);
} }
}
});
listsManagementPanel.addCopyButtonActionPerformed(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
copyAction();
listsManagementPanel.resync(); listsManagementPanel.resync();
} }
}); });
@ -113,6 +78,69 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
mainSplitPane.repaint(); 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 @Override
public void addPropertyChangeListener(PropertyChangeListener l) { public void addPropertyChangeListener(PropertyChangeListener l) {
listsManagementPanel.addPropertyChangeListener(l); listsManagementPanel.addPropertyChangeListener(l);
@ -159,14 +187,16 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
rightPanel = new javax.swing.JPanel(); rightPanel = new javax.swing.JPanel();
mainSplitPane.setBorder(null); mainSplitPane.setBorder(null);
mainSplitPane.setDividerLocation(275); mainSplitPane.setDividerLocation(300);
mainSplitPane.setDividerSize(1); mainSplitPane.setDividerSize(1);
leftPanel.setPreferredSize(new java.awt.Dimension(287, 327));
javax.swing.GroupLayout leftPanelLayout = new javax.swing.GroupLayout(leftPanel); javax.swing.GroupLayout leftPanelLayout = new javax.swing.GroupLayout(leftPanel);
leftPanel.setLayout(leftPanelLayout); leftPanel.setLayout(leftPanelLayout);
leftPanelLayout.setHorizontalGroup( leftPanelLayout.setHorizontalGroup(
leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 275, Short.MAX_VALUE) .addGap(0, 300, Short.MAX_VALUE)
); );
leftPanelLayout.setVerticalGroup( leftPanelLayout.setVerticalGroup(
leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -181,7 +211,7 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
rightPanel.setLayout(rightPanelLayout); rightPanel.setLayout(rightPanelLayout);
rightPanelLayout.setHorizontalGroup( rightPanelLayout.setHorizontalGroup(
rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 397, Short.MAX_VALUE) .addGap(0, 372, Short.MAX_VALUE)
); );
rightPanelLayout.setVerticalGroup( rightPanelLayout.setVerticalGroup(
rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

View File

@ -21,20 +21,32 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="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"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="1" pref="0" max="32767" attributes="1"/> <Component id="jScrollPane1" pref="0" max="32767" attributes="1"/>
<Group type="102" attributes="0"> <Component id="keywordListsLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="keywordListsLabel" min="-2" max="-2" attributes="0"/> <Component id="newListButton" linkSize="4" min="-2" pref="85" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <Component id="deleteListButton" linkSize="4" alignment="0" pref="0" max="32767" attributes="0"/>
<Component id="newListButton" min="-2" pref="114" max="-2" attributes="0"/> </Group>
<EmptySpace type="separate" max="-2" attributes="0"/> <EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
<Component id="importButton" min="-2" pref="126" 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>
</Group> </Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
@ -44,14 +56,21 @@
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" 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"/> <Component id="keywordListsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="355" max="32767" attributes="0"/> <Component id="jScrollPane1" pref="316" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="newListButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="newListButton" linkSize="5" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="importButton" 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> </Group>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
@ -94,6 +113,10 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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;)"/> <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>
<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> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newListButtonActionPerformed"/> <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"> <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;)"/> <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>
<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> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="importButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="importButtonActionPerformed"/>
@ -119,5 +146,73 @@
</Property> </Property>
</Properties> </Properties>
</Component> </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> </SubComponents>
</Form> </Form>

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -18,7 +18,11 @@
*/ */
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.awt.EventQueue;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -31,7 +35,7 @@ import javax.swing.table.AbstractTableModel;
import org.netbeans.spi.options.OptionsPanelController; import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel; 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. * 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 { class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final Logger logger = Logger.getLogger(GlobalListsManagementPanel.class.getName());
private final KeywordListTableModel tableModel; private final KeywordListTableModel tableModel;
private final org.sleuthkit.autopsy.keywordsearch.GlobalListSettingsPanel globalListSettingsPanel; private final org.sleuthkit.autopsy.keywordsearch.GlobalListSettingsPanel globalListSettingsPanel;
@ -56,122 +58,61 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
listsTable.setTableHeader(null); listsTable.setTableHeader(null);
listsTable.setShowHorizontalLines(false); listsTable.setShowHorizontalLines(false);
listsTable.setShowVerticalLines(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.getParent().setBackground(listsTable.getBackground());
listsTable.setCellSelectionEnabled(false); listsTable.setCellSelectionEnabled(false);
listsTable.setRowSelectionAllowed(true); listsTable.setRowSelectionAllowed(true);
tableModel.resync(); tableModel.resync();
setButtonStates();
listsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { listsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override @Override
public void valueChanged(ListSelectionEvent e) { public void valueChanged(ListSelectionEvent e) {
globalListSettingsPanel.setFocusOnKeywordTextBox(); globalListSettingsPanel.setFocusOnKeywordTextBox();
setButtonStates();
} }
}); });
/*
* XmlKeywordSearchList.getCurrent().addPropertyChangeListener(new IngestManager.getInstance().addIngestJobEventListener(new PropertyChangeListener() {
* PropertyChangeListener() { @Override
* public void propertyChange(PropertyChangeEvent evt) {
* @Override public void propertyChange(PropertyChangeEvent evt) { if Object source = evt.getSource();
* (evt.getPropertyName().equals(XmlKeywordSearchList.ListsEvt.LIST_ADDED.toString())) if (source instanceof String && ((String) source).equals("LOCAL")) { //NON-NLS
* { tableModel.resync(); for(int i = 0; i<listsTable.getRowCount(); EventQueue.invokeLater(() -> {
* i++) { String name = (String) listsTable.getValueAt(i, 0); globalListSettingsPanel.setFocusOnKeywordTextBox();
* if(((String) evt.getNewValue()).equals(name)) { setButtonStates();
* 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(); } } } });
*/ 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. * Opens the dialogue for creating a new keyword list and adds it to the table.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/ */
@SuppressWarnings("unchecked") private void newKeywordListAction() {
// <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
XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent(); XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent();
String listName = (String) JOptionPane.showInputDialog(null, NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"), String listName = "";
NbBundle.getMessage(this.getClass(), "KeywordSearch.newKeywordListMsg"), JOptionPane.PLAIN_MESSAGE, null, null, "");
if (listName == null || listName.trim().equals("")) {
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; return;
} }
boolean shouldAdd = false; boolean shouldAdd = false;
@ -197,8 +138,9 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
shouldAdd = true; shouldAdd = true;
} }
if (shouldAdd) { if (shouldAdd) {
writer.addList(listName, new ArrayList<Keyword>()); writer.addList(listName, new ArrayList<>());
} }
tableModel.resync(); tableModel.resync();
//This loop selects the recently ADDED keywordslist in the JTable //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); 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); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
globalListSettingsPanel.setFocusOnKeywordTextBox(); globalListSettingsPanel.setFocusOnKeywordTextBox();
}//GEN-LAST:event_newListButtonActionPerformed }//GEN-LAST:event_newListButtonActionPerformed
@ -251,7 +365,7 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
} }
List<KeywordList> toImport = reader.getListsL(); List<KeywordList> toImport = reader.getListsL();
List<KeywordList> toImportConfirmed = new ArrayList<KeywordList>(); List<KeywordList> toImportConfirmed = new ArrayList<>();
final XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent(); final XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent();
@ -321,12 +435,81 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
tableModel.resync(); tableModel.resync();
}//GEN-LAST:event_listsTableKeyPressed }//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 // 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.JButton importButton;
private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel keywordListsLabel; private javax.swing.JLabel keywordListsLabel;
private javax.swing.JTable listsTable; private javax.swing.JTable listsTable;
private javax.swing.JButton newListButton; private javax.swing.JButton newListButton;
private javax.swing.JButton renameListButton;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
@Override @Override
@ -345,6 +528,8 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
private class KeywordListTableModel extends AbstractTableModel { private class KeywordListTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private final XmlKeywordSearchList listsHandle = XmlKeywordSearchList.getCurrent(); private final XmlKeywordSearchList listsHandle = XmlKeywordSearchList.getCurrent();
@Override @Override

View File

@ -27,7 +27,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.TreeSet;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
@ -244,7 +243,6 @@ class HighlightedText implements IndexedText {
@Override @Override
public boolean hasNextPage() { public boolean hasNextPage() {
return getIndexOfCurrentPage() < pages.size() - 1; return getIndexOfCurrentPage() < pages.size() - 1;
} }
@Override @Override
@ -255,7 +253,7 @@ class HighlightedText implements IndexedText {
@Override @Override
public int nextPage() { public int nextPage() {
if (hasNextPage()) { if (hasNextPage()) {
currentPage = Iterators.get(pages.iterator(),getIndexOfCurrentPage() + 1); currentPage = Iterators.get(pages.iterator(), getIndexOfCurrentPage() + 1);
return currentPage; return currentPage;
} else { } else {
throw new IllegalStateException("No next page."); throw new IllegalStateException("No next page.");
@ -265,7 +263,7 @@ class HighlightedText implements IndexedText {
@Override @Override
public int previousPage() { public int previousPage() {
if (hasPreviousPage()) { if (hasPreviousPage()) {
currentPage = Iterators.get(pages.iterator(),getIndexOfCurrentPage()-1); currentPage = Iterators.get(pages.iterator(), getIndexOfCurrentPage() - 1);
return currentPage; return currentPage;
} else { } else {
throw new IllegalStateException("No previous page."); throw new IllegalStateException("No previous page.");
@ -387,7 +385,7 @@ class HighlightedText implements IndexedText {
highlightedContent = insertAnchors(highlightedContent); highlightedContent = insertAnchors(highlightedContent);
return "<html><pre>" + highlightedContent + "</pre></html>"; //NON-NLS 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 logger.log(Level.SEVERE, "Error getting highlighted text for " + objectId, ex); //NON-NLS
return NbBundle.getMessage(this.getClass(), "HighlightedMatchesSource.getMarkup.queryFailedMsg"); 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 //we also need to escape the keyword so that it matches the escpared text
final String escapedKeyword = StringEscapeUtils.escapeHtml(keyword); final String escapedKeyword = StringEscapeUtils.escapeHtml(keyword);
int textOffset = 0; int textOffset = 0;
int hitOffset; int hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset);
while ((hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset)) != -1) { while (hitOffset != -1) {
// Append the portion of text up to (but not including) the hit. // Append the portion of text up to (but not including) the hit.
highlightedText.append(text.substring(textOffset, hitOffset)); highlightedText.append(text.substring(textOffset, hitOffset));
// Add in the highlighting around the keyword. // Add in the highlighting around the keyword.
@ -464,13 +462,15 @@ class HighlightedText implements IndexedText {
// Advance the text offset past the keyword. // Advance the text offset past the keyword.
textOffset = hitOffset + escapedKeyword.length(); textOffset = hitOffset + escapedKeyword.length();
hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset);
} }
// Append the remainder of text field // Append the remainder of text field
highlightedText.append(text.substring(textOffset, text.length())); highlightedText.append(text.substring(textOffset, text.length()));
if (highlightedText.length() == 0) { if (highlightedText.length() == 0) {
return NbBundle.getMessage(HighlightedText.class, "HighlightedMatchesSource.getMarkup.noMatchMsg"); return NbBundle.getMessage(HighlightedText.class, "HighlightedMatchesSource.getMarkup.noMatchMsg");
} }
//reset for next pass //reset for next pass
text = highlightedText.toString(); text = highlightedText.toString();
highlightedText = new StringBuilder(""); highlightedText = new StringBuilder("");
@ -487,22 +487,21 @@ class HighlightedText implements IndexedText {
* @return * @return
*/ */
private String insertAnchors(String searchableContent) { private String insertAnchors(String searchableContent) {
int searchOffset = 0;
int index = -1;
StringBuilder buf = new StringBuilder(searchableContent); StringBuilder buf = new StringBuilder(searchableContent);
final String searchToken = HIGHLIGHT_PRE; final String searchToken = HIGHLIGHT_PRE;
final int indexSearchTokLen = searchToken.length(); final int indexSearchTokLen = searchToken.length();
final String insertPre = "<a name='" + ANCHOR_PREFIX; //NON-NLS final String insertPre = "<a name='" + ANCHOR_PREFIX; //NON-NLS
final String insertPost = "'></a>"; //NON-NLS final String insertPost = "'></a>"; //NON-NLS
int count = 0; 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; String insertString = insertPre + Integer.toString(count + 1) + insertPost;
int insertStringLen = insertString.length(); int insertStringLen = insertString.length();
buf.insert(index, insertString); buf.insert(index, insertString);
searchOffset = index + indexSearchTokLen + insertStringLen; //next offset past this anchor searchOffset = index + indexSearchTokLen + insertStringLen; //next offset past this anchor
++count; ++count;
index = buf.indexOf(searchToken, searchOffset);
} }
//store total hits for this page, now that we know it //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.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.math.NumberUtils;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
@ -99,10 +101,10 @@ class IndexFinder {
} }
/** /**
* Creates a copy of an existing Solr index. * Creates a copy of an existing Solr index.
* *
* @param indexToUpgrade Index object to create a copy of * @param indexToUpgrade Index object to create a copy of
* @param context AutopsyService.CaseContext object * @param context AutopsyService.CaseContext object
* *
* @return The absolute path of the new Solr index directory * @return The absolute path of the new Solr index directory
* *
@ -120,20 +122,31 @@ class IndexFinder {
List<File> contents = getAllContentsInFolder(targetDirPath.getAbsolutePath()); List<File> contents = getAllContentsInFolder(targetDirPath.getAbsolutePath());
if (!contents.isEmpty()) { if (!contents.isEmpty()) {
// target directory is not empty // 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(); targetDirPath.mkdirs();
FileUtils.copyDirectory(new File(indexToUpgrade.getIndexPath()), targetDirPath); FileUtils.copyDirectory(new File(indexToUpgrade.getIndexPath()), targetDirPath);
return targetDirPath.getAbsolutePath(); return targetDirPath.getAbsolutePath();
} catch (AutopsyService.AutopsyServiceException | IOException ex) { } 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); 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 * Find existing Solr 4 Schema 1.8 index directory location for the case.
* subdirectory search of all existing * This is done via subdirectory search of all existing
* "ModuleOutput/node_name/keywordsearch/data/" folders. * "ModuleOutput/node_name/keywordsearch/data/" folders.
* *
* @param theCase the case to get index dir for * @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. // 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. // 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 * NOTE: the following path is an example of valid Solr 4 Schema 1.8
* path: X:\Case\ingest1\ModuleOutput\keywordsearch\data\index * multi-user index path:
* X:\Case\ingest1\ModuleOutput\keywordsearch\data\index
*/ */
// get a list of all folder's contents // get a list of all folder's contents
@ -169,8 +183,8 @@ class IndexFinder {
} else { } else {
// single user case // single user case
/* /*
* NOTE: the following path is valid single user Solr 4 Schema 1.8 index * NOTE: the following path is valid single user Solr 4 Schema 1.8
* path: X:\Case\ModuleOutput\keywordsearch\data\index * 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 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 // must be a non-empty index directory

View File

@ -186,7 +186,7 @@ class IndexUpgrader {
* *
* @return The new Solr index version. * @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) { if (currentIndexVersion != 5) {
return currentIndexVersion; return currentIndexVersion;
} }
@ -218,7 +218,11 @@ class IndexUpgrader {
ProcessBuilder processBuilder = new ProcessBuilder(commandLine); ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
processBuilder.redirectOutput(new File(outputFileFullPath)); processBuilder.redirectOutput(new File(outputFileFullPath));
processBuilder.redirectError(new File(errFileFullPath)); 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 // 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 // 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; return query;
} }
StringBuilder sb = new StringBuilder(); return "\""+query+"\"";
sb.append("\"").append(query).append("\"");
return sb.toString();
} }
/** /**

View File

@ -27,10 +27,12 @@ import java.util.logging.Level;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.math.NumberUtils;
import org.apache.solr.client.solrj.SolrQuery; 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.SolrRequest.METHOD;
import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.CursorMarkParams;
import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.EscapeUtil;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.Version; 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.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
/** /**
@ -47,14 +50,13 @@ import org.sleuthkit.datamodel.TskException;
class LuceneQuery implements KeywordSearchQuery { class LuceneQuery implements KeywordSearchQuery {
private static final Logger logger = Logger.getLogger(LuceneQuery.class.getName()); private static final Logger logger = Logger.getLogger(LuceneQuery.class.getName());
private final String keywordString; //original unescaped query
private String keywordStringEscaped; private String keywordStringEscaped;
private boolean isEscaped; private boolean isEscaped;
private Keyword originalKeyword = null; private final Keyword originalKeyword ;
private KeywordList keywordList = null; private final KeywordList keywordList ;
private final List<KeywordQueryFilter> filters = new ArrayList<>(); private final List<KeywordQueryFilter> filters = new ArrayList<>();
private String field = null; 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 int SNIPPET_LENGTH = 50;
static final String HIGHLIGHT_FIELD = Server.Schema.TEXT.toString(); static final String HIGHLIGHT_FIELD = Server.Schema.TEXT.toString();
@ -65,14 +67,10 @@ class LuceneQuery implements KeywordSearchQuery {
* *
* @param keyword * @param keyword
*/ */
public LuceneQuery(KeywordList keywordList, Keyword keyword) { LuceneQuery(KeywordList keywordList, Keyword keyword) {
this.keywordList = keywordList; this.keywordList = keywordList;
this.originalKeyword = keyword; this.originalKeyword = keyword;
this.keywordStringEscaped = this.originalKeyword.getSearchTerm();
// @@@ 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;
} }
@Override @Override
@ -89,12 +87,12 @@ class LuceneQuery implements KeywordSearchQuery {
public void setSubstringQuery() { public void setSubstringQuery() {
// Note that this is not a full substring search. Normally substring // Note that this is not a full substring search. Normally substring
// searches will be done with TermComponentQuery objects instead. // searches will be done with TermComponentQuery objects instead.
keywordStringEscaped = keywordStringEscaped + "*"; keywordStringEscaped += "*";
} }
@Override @Override
public void escape() { public void escape() {
keywordStringEscaped = KeywordSearchUtil.escapeLuceneQuery(keywordString); keywordStringEscaped = KeywordSearchUtil.escapeLuceneQuery(originalKeyword.getSearchTerm());
isEscaped = true; isEscaped = true;
} }
@ -115,22 +113,82 @@ class LuceneQuery implements KeywordSearchQuery {
@Override @Override
public String getQueryString() { public String getQueryString() {
return this.keywordString; return this.originalKeyword.getSearchTerm();
}
@Override
public KeywordList getKeywordList() {
return keywordList;
} }
@Override @Override
public QueryResults performQuery() throws KeywordSearchModuleException, NoOpenCoreException { 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 //in case of single term literal query there is only 1 term
boolean showSnippets = KeywordSearchSettings.getShowSnippets(); results.addResult(new Keyword(originalKeyword.getSearchTerm(), true), matches);
results.addResult(new Keyword(keywordString, true), performLuceneQuery(showSnippets));
return results; return results;
} }
@Override @Override
public boolean validate() { public boolean validate() {
return keywordString != null && !keywordString.equals(""); return StringUtils.isNotBlank(originalKeyword.getSearchTerm());
} }
@Override @Override
@ -143,7 +201,7 @@ class LuceneQuery implements KeywordSearchQuery {
try { try {
bba = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT); bba = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
writeResult = new KeywordCachedArtifact(bba); writeResult = new KeywordCachedArtifact(bba);
} catch (Exception e) { } catch (TskCoreException e) {
logger.log(Level.WARNING, "Error adding bb artifact for keyword hit", e); //NON-NLS logger.log(Level.WARNING, "Error adding bb artifact for keyword hit", e); //NON-NLS
return null; 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_PREVIEW, MODULE_NAME, snippet));
} }
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, foundKeyword.getSearchTerm())); 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)); 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) { if (originalKeyword != null) {
BlackboardAttribute.ATTRIBUTE_TYPE selType = originalKeyword.getArtifactAttributeType(); BlackboardAttribute.ATTRIBUTE_TYPE selType = originalKeyword.getArtifactAttributeType();
if (selType != null) { if (selType != null) {
@ -180,81 +235,14 @@ class LuceneQuery implements KeywordSearchQuery {
bba.addAttributes(attributes); //write out to bb bba.addAttributes(attributes); //write out to bb
writeResult.add(attributes); writeResult.add(attributes);
return writeResult; return writeResult;
} catch (TskException e) { } catch (TskCoreException e) {
logger.log(Level.WARNING, "Error adding bb attributes to artifact", e); //NON-NLS 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 * Create the query object for the stored keyword
* *
* @param snippets True if query should request snippets * @param snippets True if query should request snippets
@ -265,51 +253,59 @@ class LuceneQuery implements KeywordSearchQuery {
SolrQuery q = new SolrQuery(); SolrQuery q = new SolrQuery();
q.setShowDebugInfo(DEBUG); //debug q.setShowDebugInfo(DEBUG); //debug
// Wrap the query string in quotes if this is a literal search term. // 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; ? KeywordSearchUtil.quoteQuery(keywordStringEscaped) : keywordStringEscaped;
// Run the query against an optional alternative field. // Run the query against an optional alternative field.
if (field != null) { if (field != null) {
//use the optional field //use the optional field
StringBuilder sb = new StringBuilder(); queryStr = field + ":" + queryStr;
sb.append(field).append(":").append(theQueryStr);
theQueryStr = sb.toString();
} }
q.setQuery(theQueryStr); q.setQuery(queryStr);
q.setRows(MAX_RESULTS); 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(), q.setFields(Server.Schema.ID.toString(),
Server.Schema.CHUNK_SIZE.toString(), Server.Schema.CHUNK_SIZE.toString(),
Server.Schema.CONTENT_STR.toString()); Server.Schema.CONTENT_STR.toString());
q.addSort(Server.Schema.ID.toString(), SolrQuery.ORDER.asc);
for (KeywordQueryFilter filter : filters) { for (KeywordQueryFilter filter : filters) {
q.addFilterQuery(filter.toString()); q.addFilterQuery(filter.toString());
} }
if (snippets) { if (snippets) {
q.addHighlightField(Server.Schema.TEXT.toString()); configurwQueryForHighlighting(q);
//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
} }
return 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 { 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 * 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 * @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); return querySnippet(query, solrObjectId, 0, isRegex, group);
} }
@ -360,62 +356,33 @@ class LuceneQuery implements KeywordSearchQuery {
* *
* @return * @return
*/ */
public static String querySnippet(String query, long solrObjectId, int chunkID, boolean isRegex, boolean group) throws NoOpenCoreException { static String querySnippet(String query, long solrObjectId, int chunkID, boolean isRegex, boolean group) throws NoOpenCoreException {
Server solrServer = KeywordSearch.getServer();
SolrQuery q = new SolrQuery(); SolrQuery q = new SolrQuery();
q.setShowDebugInfo(DEBUG); //debug
String queryStr; String queryStr;
if (isRegex) { if (isRegex) {
StringBuilder sb = new StringBuilder(); queryStr = HIGHLIGHT_FIELD + ":"
sb.append(LuceneQuery.HIGHLIGHT_FIELD).append(":"); + (group ? KeywordSearchUtil.quoteQuery(query)
if (group) { : query);
sb.append("\"");
}
sb.append(query);
if (group) {
sb.append("\"");
}
queryStr = sb.toString();
} else { } 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); queryStr = KeywordSearchUtil.quoteQuery(query);
} }
q.setQuery(queryStr); q.setQuery(queryStr);
String contentIDStr; String contentIDStr = (chunkID == 0)
? Long.toString(solrObjectId)
if (chunkID == 0) { : Server.getChunkIdString(solrObjectId, chunkID);
contentIDStr = Long.toString(solrObjectId);
} else {
contentIDStr = Server.getChunkIdString(solrObjectId, chunkID);
}
String idQuery = Server.Schema.ID.toString() + ":" + KeywordSearchUtil.escapeLuceneQuery(contentIDStr); String idQuery = Server.Schema.ID.toString() + ":" + KeywordSearchUtil.escapeLuceneQuery(contentIDStr);
q.setShowDebugInfo(DEBUG); //debug
q.addFilterQuery(idQuery); 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 configurwQueryForHighlighting(q);
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. Server solrServer = KeywordSearch.getServer();
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
try { try {
QueryResponse response = solrServer.query(q, METHOD.POST); QueryResponse response = solrServer.query(q, METHOD.POST);
@ -439,42 +406,4 @@ class LuceneQuery implements KeywordSearchQuery {
return ""; 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<>(); 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.keywordSearchQuery = query;
this.keywordList = keywordList;
} }
void addResult(Keyword keyword, List<KeywordHit> hits) { void addResult(Keyword keyword, List<KeywordHit> hits) {
results.put(keyword, hits); results.put(keyword, hits);
} }
// TODO: This is redundant. The keyword list is in the query.
KeywordList getKeywordList() {
return keywordList;
}
KeywordSearchQuery getQuery() { KeywordSearchQuery getQuery() {
return keywordSearchQuery; return keywordSearchQuery;
@ -129,7 +121,7 @@ class QueryResults {
if (hitDisplayStr.length() > 50) { if (hitDisplayStr.length() > 50) {
hitDisplayStr = hitDisplayStr.substring(0, 49) + "..."; hitDisplayStr = hitDisplayStr.substring(0, 49) + "...";
} }
subProgress.progress(keywordList.getName() + ": " + hitDisplayStr, unitProgress); subProgress.progress(keywordSearchQuery.getKeywordList().getName() + ": " + hitDisplayStr, unitProgress);
} }
for (KeywordHit hit : getOneHitPerObject(keyword)) { for (KeywordHit hit : getOneHitPerObject(keyword)) {
@ -138,7 +130,11 @@ class QueryResults {
if (StringUtils.isBlank(snippet)) { if (StringUtils.isBlank(snippet)) {
final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(termString); final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(termString);
try { 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); snippet = LuceneQuery.querySnippet(snippetQuery, hit.getSolrObjectId(), hit.getChunkId(), !keywordSearchQuery.isLiteral(), true);
} catch (NoOpenCoreException e) { } catch (NoOpenCoreException e) {
logger.log(Level.WARNING, "Error querying snippet: " + snippetQuery, e); //NON-NLS logger.log(Level.WARNING, "Error querying snippet: " + snippetQuery, e); //NON-NLS
@ -149,16 +145,14 @@ class QueryResults {
continue; continue;
} }
} }
if (snippet != null) { KeywordCachedArtifact writeResult = keywordSearchQuery.writeSingleFileHitsToBlackBoard(keyword, hit, snippet, keywordSearchQuery.getKeywordList().getName());
KeywordCachedArtifact writeResult = keywordSearchQuery.writeSingleFileHitsToBlackBoard(keyword, hit, snippet, keywordList.getName()); if (writeResult != null) {
if (writeResult != null) { newArtifacts.add(writeResult.getArtifact());
newArtifacts.add(writeResult.getArtifact()); if (notifyInbox) {
if (notifyInbox) { writeSingleFileInboxMessage(writeResult, hit.getContent());
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
} }
} 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; ++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 final Keyword originalKeyword; // The regular expression originalKeyword used to perform the search.
private String field = Server.Schema.CONTENT_STR.toString(); private String field = Server.Schema.CONTENT_STR.toString();
private final String keywordString; 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 boolean escaped;
private String escapedQuery; private String escapedQuery;
@ -154,7 +154,6 @@ final class RegexQuery implements KeywordSearchQuery {
@Override @Override
public QueryResults performQuery() throws NoOpenCoreException { public QueryResults performQuery() throws NoOpenCoreException {
QueryResults results = new QueryResults(this, keywordList);
final Server solrServer = KeywordSearch.getServer(); final Server solrServer = KeywordSearch.getServer();
SolrQuery solrQuery = new SolrQuery(); SolrQuery solrQuery = new SolrQuery();
@ -187,12 +186,12 @@ final class RegexQuery implements KeywordSearchQuery {
.map(KeywordQueryFilter::toString) .map(KeywordQueryFilter::toString)
.forEach(solrQuery::addFilterQuery); .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. // Setting the sort order is necessary for cursor based paging to work.
solrQuery.setSort(SortClause.asc(Server.Schema.ID.toString())); solrQuery.setSort(SortClause.asc(Server.Schema.ID.toString()));
String cursorMark = CursorMarkParams.CURSOR_MARK_START; String cursorMark = CursorMarkParams.CURSOR_MARK_START;
SolrDocumentList resultList = null; SolrDocumentList resultList ;
boolean allResultsProcessed = false; boolean allResultsProcessed = false;
while (!allResultsProcessed) { while (!allResultsProcessed) {
@ -218,15 +217,14 @@ final class RegexQuery implements KeywordSearchQuery {
} }
cursorMark = nextCursorMark; cursorMark = nextCursorMark;
} catch (KeywordSearchModuleException ex) { } 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()); 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()) { for (Keyword k : hitsMultiMap.keySet()) {
results.addResult(k, hitsMultiMap.get(k)); results.addResult(k, hitsMultiMap.get(k));
} }
return results; return results;
} }

View File

@ -590,7 +590,7 @@ public final class SearchRunner {
// Create a new (empty) QueryResults object to hold the most recently // Create a new (empty) QueryResults object to hold the most recently
// found hits. // found hits.
QueryResults newResults = new QueryResults(queryResult.getQuery(), queryResult.getKeywordList()); QueryResults newResults = new QueryResults(queryResult.getQuery());
// For each keyword represented in the results. // For each keyword represented in the results.
for (Keyword keyword : queryResult.getKeywords()) { 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. * 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) { for (Term term : terms) {
/* /*
* If searching for credit card account numbers, do a Luhn check on * 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 com.google.common.io.CharSource;
import java.io.IOException; import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader; import java.io.Reader;
import java.util.List; import java.util.List;
import java.util.MissingResourceException; import java.util.MissingResourceException;
@ -69,20 +70,29 @@ class TikaTextExtractor extends FileTextExtractor {
final Future<Reader> future = tikaParseExecutor.submit(() -> new Tika().parse(stream, metadata)); final Future<Reader> future = tikaParseExecutor.submit(() -> new Tika().parse(stream, metadata));
try { try {
final Reader tikaReader = future.get(getTimeout(sourceFile.getSize()), TimeUnit.SECONDS); 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. //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) { } catch (TimeoutException te) {
final String msg = NbBundle.getMessage(this.getClass(), "AbstractFileTikaTextExtract.index.tikaParseTimeout.text", sourceFile.getId(), sourceFile.getName()); final String msg = NbBundle.getMessage(this.getClass(), "AbstractFileTikaTextExtract.index.tikaParseTimeout.text", sourceFile.getId(), sourceFile.getName());
logWarning(msg, te); logWarning(msg, te);
future.cancel(true);
throw new TextExtractorException(msg, te); throw new TextExtractorException(msg, te);
} catch (Exception ex) { } catch (Exception ex) {
KeywordSearch.getTikaLogger().log(Level.WARNING, "Exception: Unable to Tika parse the content" + sourceFile.getId() + ": " + sourceFile.getName(), ex.getCause()); //NON-NLS 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()); final String msg = NbBundle.getMessage(this.getClass(), "AbstractFileTikaTextExtract.index.exception.tikaParse.msg", sourceFile.getId(), sourceFile.getName());
logWarning(msg, ex); logWarning(msg, ex);
future.cancel(true);
throw new TextExtractorException(msg, ex); throw new TextExtractorException(msg, ex);
} finally {
future.cancel(true);
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

View File

@ -1,19 +1,19 @@
/* /*
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012-2014 Basis Technology Corp. * Copyright 2012-2014 Basis Technology Corp.
* *
* Copyright 2012 42six Solutions. * Copyright 2012 42six Solutions.
* *
* Project Contact/Architect: carrier <at> sleuthkit <dot> org * Project Contact/Architect: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -112,6 +112,7 @@ class Chrome extends Extract {
} }
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
while (j < historyFiles.size()) { while (j < historyFiles.size()) {
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + historyFiles.get(j).getName().toString() + j + ".db"; //NON-NLS 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, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS (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(); dbFile.delete();
} }
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY)); NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
} }
/** /**
@ -185,6 +191,7 @@ class Chrome extends Extract {
} }
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
while (j < bookmarkFiles.size()) { while (j < bookmarkFiles.size()) {
@ -286,9 +293,10 @@ class Chrome extends Extract {
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"Chrome.parentModuleName"), domain)); "Chrome.parentModuleName"), domain));
bbart.addAttributes(bbattributes); bbart.addAttributes(bbattributes);
// index the artifact for keyword search // index the artifact for keyword search
this.indexArtifact(bbart); this.indexArtifact(bbart);
bbartifacts.add(bbart);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to insert Chrome bookmark artifact{0}", ex); //NON-NLS logger.log(Level.SEVERE, "Error while trying to insert Chrome bookmark artifact{0}", ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
@ -299,7 +307,9 @@ class Chrome extends Extract {
dbFile.delete(); 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; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
while (j < cookiesFiles.size()) { while (j < cookiesFiles.size()) {
AbstractFile cookiesFile = cookiesFiles.get(j++); AbstractFile cookiesFile = cookiesFiles.get(j++);
@ -370,13 +381,19 @@ class Chrome extends Extract {
domain = domain.replaceFirst("^\\.+(?!$)", ""); domain = domain.replaceFirst("^\\.+(?!$)", "");
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), 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(); 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; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
while (j < downloadFiles.size()) { while (j < downloadFiles.size()) {
AbstractFile downloadFile = downloadFiles.get(j++); AbstractFile downloadFile = downloadFiles.get(j++);
@ -456,14 +474,19 @@ class Chrome extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
NbBundle.getMessage(this.getClass(), "Chrome.moduleName"))); 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(); dbFile.delete();
} }
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD)); NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
} }
/** /**
@ -487,6 +510,7 @@ class Chrome extends Extract {
} }
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
while (j < signonFiles.size()) { while (j < signonFiles.size()) {
AbstractFile signonFile = signonFiles.get(j++); AbstractFile signonFile = signonFiles.get(j++);
@ -539,8 +563,13 @@ class Chrome extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
result.get("signon_realm").toString())); //NON-NLS 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<>(); Collection<BlackboardAttribute> osAcctAttributes = new ArrayList<>();
osAcctAttributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, osAcctAttributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
@ -551,7 +580,9 @@ class Chrome extends Extract {
dbFile.delete(); 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) { private boolean isChromePreVersion30(String temps) {

View File

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

View File

@ -1,19 +1,19 @@
/* /*
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* *
* Copyright 2012 42six Solutions. * Copyright 2012 42six Solutions.
* Contact: aebadirad <at> 42six <dot> com * Contact: aebadirad <at> 42six <dot> com
* Project Contact/Architect: carrier <at> sleuthkit <dot> org * Project Contact/Architect: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -41,6 +41,7 @@ import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.Collection; import java.util.Collection;
import java.util.Scanner; import java.util.Scanner;
import java.util.stream.Collectors;
import org.openide.modules.InstalledFileLocator; import org.openide.modules.InstalledFileLocator;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils;
@ -109,6 +110,7 @@ class ExtractIE extends Extract {
} }
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
for (AbstractFile fav : favoritesFiles) { for (AbstractFile fav : favoritesFiles) {
if (fav.getSize() == 0) { if (fav.getSize() == 0) {
continue; continue;
@ -143,10 +145,15 @@ class ExtractIE extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), domain)); "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( 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) { private String getURLFromIEBookmarkFile(AbstractFile fav) {
@ -205,6 +212,7 @@ class ExtractIE extends Extract {
} }
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
for (AbstractFile cookiesFile : cookiesFiles) { for (AbstractFile cookiesFile : cookiesFiles) {
if (context.dataSourceIngestIsCancelled()) { if (context.dataSourceIngestIsCancelled()) {
break; break;
@ -253,10 +261,14 @@ class ExtractIE extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), domain)); "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( 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; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
String temps; String temps;
String indexFileName; String indexFileName;
for (AbstractFile indexFile : indexFiles) { for (AbstractFile indexFile : indexFiles) {
@ -336,7 +349,10 @@ class ExtractIE extends Extract {
//At this point pasco2 proccessed the index files. //At this point pasco2 proccessed the index files.
//Now fetch the results, parse them and the delete the files. //Now fetch the results, parse them and the delete the files.
if (bPascProcSuccess) { 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; foundHistory = true;
//Delete index<n>.dat file since it was succcessfully by Pasco //Delete index<n>.dat file since it was succcessfully by Pasco
@ -350,7 +366,8 @@ class ExtractIE extends Extract {
if (foundHistory) { if (foundHistory) {
services.fireModuleDataEvent(new ModuleDataEvent( 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 * @param origFile Original index.dat file that was analyzed to
* get this output * get this output
* @param pascoOutputFileName name of pasco output file * @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; String fnAbs = moduleTempResultsDir + File.separator + pascoOutputFileName;
File file = new File(fnAbs); File file = new File(fnAbs);
@ -414,13 +434,13 @@ class ExtractIE extends Extract {
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(), NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(),
file.getName())); file.getName()));
logger.log(Level.WARNING, "Pasco Output not found: {0}", file.getPath()); //NON-NLS 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 // Make sure the file the is not empty or the Scanner will
// throw a "No Line found" Exception // throw a "No Line found" Exception
if (file.length() == 0) { if (file.length() == 0) {
return; return bbartifacts;
} }
Scanner fileScanner; Scanner fileScanner;
@ -431,7 +451,7 @@ class ExtractIE extends Extract {
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(), NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(),
file.getName())); file.getName()));
logger.log(Level.WARNING, "Unable to find the Pasco file at " + file.getPath(), ex); //NON-NLS 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 // Keep a list of reported user accounts to avoid repeats
@ -521,6 +541,7 @@ class ExtractIE extends Extract {
// index the artifact for keyword search // index the artifact for keyword search
this.indexArtifact(bbart); this.indexArtifact(bbart);
bbartifacts.add(bbart);
if ((!user.isEmpty()) && (!reportedUserAccounts.contains(user))) { if ((!user.isEmpty()) && (!reportedUserAccounts.contains(user))) {
BlackboardArtifact osAttr = origFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); BlackboardArtifact osAttr = origFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
@ -529,6 +550,7 @@ class ExtractIE extends Extract {
// index the artifact for keyword search // index the artifact for keyword search
this.indexArtifact(osAttr); this.indexArtifact(osAttr);
bbartifacts.add(osAttr);
reportedUserAccounts.add(user); reportedUserAccounts.add(user);
} }
@ -537,5 +559,6 @@ class ExtractIE extends Extract {
} }
} }
fileScanner.close(); fileScanner.close();
return bbartifacts;
} }
} }

View File

@ -97,7 +97,7 @@ class Firefox extends Extract {
} }
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
for (AbstractFile historyFile : historyFiles) { for (AbstractFile historyFile : historyFiles) {
if (historyFile.getSize() == 0) { if (historyFile.getSize() == 0) {
@ -148,14 +148,19 @@ class Firefox extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"), (Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS "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; ++j;
dbFile.delete(); dbFile.delete();
} }
services.fireModuleDataEvent(new ModuleDataEvent( 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; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
for (AbstractFile bookmarkFile : bookmarkFiles) { for (AbstractFile bookmarkFile : bookmarkFiles) {
if (bookmarkFile.getSize() == 0) { if (bookmarkFile.getSize() == 0) {
@ -228,15 +233,19 @@ class Firefox extends Extract {
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"), "Firefox.parentModuleName.noSpace"),
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS (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; ++j;
dbFile.delete(); dbFile.delete();
} }
services.fireModuleDataEvent(new ModuleDataEvent( 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; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
for (AbstractFile cookiesFile : cookiesFiles) { for (AbstractFile cookiesFile : cookiesFiles) {
if (cookiesFile.getSize() == 0) { if (cookiesFile.getSize() == 0) {
@ -326,14 +336,19 @@ class Firefox extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"), domain)); "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; ++j;
dbFile.delete(); dbFile.delete();
} }
services.fireModuleDataEvent(new ModuleDataEvent( 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; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
for (AbstractFile downloadsFile : downloadsFiles) { for (AbstractFile downloadsFile : downloadsFiles) {
if (downloadsFile.getSize() == 0) { if (downloadsFile.getSize() == 0) {
@ -436,8 +452,11 @@ class Firefox extends Extract {
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"), "Firefox.parentModuleName.noSpace"),
(Util.extractDomain((result.get("source").toString() != null) ? result.get("source").toString() : "")))); //NON-NLS (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) { if (errors > 0) {
this.addErrorMessage( this.addErrorMessage(
@ -450,7 +469,8 @@ class Firefox extends Extract {
} }
services.fireModuleDataEvent(new ModuleDataEvent( 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; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
for (AbstractFile downloadsFile : downloadsFiles) { for (AbstractFile downloadsFile : downloadsFiles) {
if (downloadsFile.getSize() == 0) { if (downloadsFile.getSize() == 0) {
@ -546,8 +567,11 @@ class Firefox extends Extract {
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"), "Firefox.parentModuleName.noSpace"),
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS (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) { if (errors > 0) {
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts", this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
@ -559,6 +583,7 @@ class Firefox extends Extract {
} }
services.fireModuleDataEvent(new ModuleDataEvent( 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 #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 LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314 SPLASH_HEIGHT=314
SPLASH_WIDTH=538 SPLASH_WIDTH=538

View File

@ -1,4 +1,4 @@
#Updated by build script #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=Autopsy 4.3.0
CTL_MainWindow_Title_No_Project=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"/> <import file="nbproject/build-impl.xml"/>
<!-- IMPORTANT: nbproject/platform.properties has a netbeans-plat-version property that MUST be kept in sync (manually) --> <!-- 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}" /> <property name="nbplatform.active.dir" value="${basedir}/netbeans-plat/${netbeans-plat-version}" />
<!-- Supported java versions.--> <!-- Supported java versions.-->
<condition property="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/build-impl.xml.stylesheet.CRC32=0f381476@2.47.1
nbproject/platform.xml.data.CRC32=2e7964b0 nbproject/platform.xml.data.CRC32=2e7964b0
nbproject/platform.xml.script.CRC32=6dcbd131 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 branding.token=autopsy
# Version of platform that is automatically downloaded # Version of platform that is automatically downloaded
# IMPORTANT: autopsy/build.xml has a netbeans-plat-version property that MUST be kept in sync (manually) # 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} suite.dir=${basedir}
nbplatform.active.dir=${suite.dir}/netbeans-plat/${netbeans-plat-version} nbplatform.active.dir=${suite.dir}/netbeans-plat/${netbeans-plat-version}
harness.dir=${nbplatform.active.dir}/harness harness.dir=${nbplatform.active.dir}/harness

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

Binary file not shown.