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

This commit is contained in:
Eugene Livis
2016-04-08 14:02:04 -04:00
58 changed files with 1015 additions and 1718 deletions
@@ -20,8 +20,10 @@ package org.sleuthkit.autopsy.casemodule;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.MessageFormat;
import java.util.logging.Level;
import javax.swing.Action;
import javax.swing.ImageIcon;
@@ -74,6 +76,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
static final String NOFATORPHANS_PROP = "nofatorphans"; //NON-NLS
static final Logger logger = Logger.getLogger(AddImageAction.class.getName());
static final Dimension SIZE = new Dimension(875, 550);
private WizardDescriptor wizardDescriptor;
private WizardDescriptor.Iterator<WizardDescriptor> iterator;
@@ -119,11 +122,14 @@ public final class AddImageAction extends CallableSystemAction implements Presen
wizardDescriptor = new WizardDescriptor(iterator);
wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "AddImageAction.wizard.title"));
wizardDescriptor.putProperty(NAME, e);
wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
if (dialog != null) {
dialog.setVisible(false); // hide the old one
}
dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
Dimension d = dialog.getSize();
dialog.setSize(SIZE);
dialog.setVisible(true);
dialog.toFront();
@@ -34,13 +34,7 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="inputPanel" alignment="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="nextLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="54" max="32767" attributes="0"/>
</Group>
</Group>
<Component id="inputPanel" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
@@ -48,35 +42,15 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="39" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Component id="inputPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="24" max="32767" attributes="0"/>
<Component id="nextLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<EmptySpace pref="44" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="nextLabel">
<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.nextLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[514, 35]"/>
</Property>
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="inputPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
<EtchetBorder/>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
@@ -88,9 +62,9 @@
<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="115" max="32767" attributes="0"/>
<EmptySpace min="0" pref="119" max="32767" attributes="0"/>
</Group>
<Component id="typePanel" alignment="1" pref="544" max="32767" attributes="0"/>
<Component id="typePanel" alignment="1" pref="548" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@@ -105,8 +79,8 @@
<Component id="typeComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="typePanel" pref="173" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="typePanel" min="-2" pref="225" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@@ -132,12 +106,12 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="544" max="32767" 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="173" max="32767" attributes="0"/>
<EmptySpace min="0" pref="225" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@@ -205,7 +205,6 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
buttonGroup1 = new javax.swing.ButtonGroup();
jLabel2 = new javax.swing.JLabel();
nextLabel = new javax.swing.JLabel();
inputPanel = new javax.swing.JPanel();
typeTabel = new javax.swing.JLabel();
typePanel = new javax.swing.JPanel();
@@ -215,12 +214,6 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
setPreferredSize(new java.awt.Dimension(588, 328));
org.openide.awt.Mnemonics.setLocalizedText(nextLabel, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.nextLabel.text")); // NOI18N
nextLabel.setPreferredSize(new java.awt.Dimension(514, 35));
nextLabel.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
inputPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
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));
@@ -230,11 +223,11 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
typePanel.setLayout(typePanelLayout);
typePanelLayout.setHorizontalGroup(
typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 544, Short.MAX_VALUE)
.addGap(0, 548, Short.MAX_VALUE)
);
typePanelLayout.setVerticalGroup(
typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 173, Short.MAX_VALUE)
.addGap(0, 225, Short.MAX_VALUE)
);
javax.swing.GroupLayout inputPanelLayout = new javax.swing.GroupLayout(inputPanel);
@@ -248,8 +241,8 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
.addComponent(typeTabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(typeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 115, Short.MAX_VALUE))
.addComponent(typePanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 544, Short.MAX_VALUE))
.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(
@@ -260,8 +253,8 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
.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.DEFAULT_SIZE, 173, Short.MAX_VALUE)
.addContainerGap())
.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);
@@ -270,28 +263,21 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(inputPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(nextLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 54, Short.MAX_VALUE)))
.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(39, 39, 39)
.addGap(6, 6, 6)
.addComponent(inputPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 24, Short.MAX_VALUE)
.addComponent(nextLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0))
.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.JLabel nextLabel;
private javax.swing.JComboBox<String> typeComboBox;
private javax.swing.JPanel typePanel;
private javax.swing.JLabel typeTabel;
@@ -21,34 +21,19 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="subtitleLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="218" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="configPanel" min="-2" pref="609" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="configPanel" alignment="0" max="32767" attributes="0"/>
</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="subtitleLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="configPanel" pref="258" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Component id="configPanel" alignment="0" pref="300" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="subtitleLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageWizardIngestConfigVisual.subtitleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="configPanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
@@ -59,12 +44,12 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="569" max="32767" attributes="0"/>
<EmptySpace min="0" pref="609" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="258" max="32767" attributes="0"/>
<EmptySpace min="0" pref="349" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@@ -42,7 +42,6 @@ class AddImageWizardIngestConfigVisual extends JPanel {
}
private void customizeComponents() {
configPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
configPanel.setLayout(new BorderLayout());
configPanel.add(ingestPanel, BorderLayout.CENTER);
}
@@ -66,24 +65,21 @@ class AddImageWizardIngestConfigVisual extends JPanel {
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
subtitleLabel = new javax.swing.JLabel();
configPanel = new javax.swing.JPanel();
setPreferredSize(new java.awt.Dimension(569, 300));
subtitleLabel.setText(org.openide.util.NbBundle.getMessage(AddImageWizardIngestConfigVisual.class, "AddImageWizardIngestConfigVisual.subtitleLabel.text")); // NOI18N
configPanel.setPreferredSize(new java.awt.Dimension(569, 400));
javax.swing.GroupLayout configPanelLayout = new javax.swing.GroupLayout(configPanel);
configPanel.setLayout(configPanelLayout);
configPanelLayout.setHorizontalGroup(
configPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 569, Short.MAX_VALUE)
.addGap(0, 609, Short.MAX_VALUE)
);
configPanelLayout.setVerticalGroup(
configPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 258, Short.MAX_VALUE)
.addGap(0, 349, Short.MAX_VALUE)
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
@@ -91,23 +87,15 @@ class AddImageWizardIngestConfigVisual extends JPanel {
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(subtitleLabel)
.addContainerGap(218, Short.MAX_VALUE))
.addComponent(configPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(configPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 609, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(6, 6, 6)
.addComponent(subtitleLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(configPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 258, Short.MAX_VALUE)
.addContainerGap())
.addComponent(configPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel configPanel;
private javax.swing.JLabel subtitleLabel;
// End of variables declaration//GEN-END:variables
}
@@ -69,11 +69,9 @@ LocalFilesPanel.selectedPaths.toolTipText=
LocalFilesPanel.localFileChooser.approveButtonText=Select
LocalFilesPanel.localFileChooser.approveButtonToolTipText=
LocalFilesPanel.selectButton.actionCommand=Add
AddImageWizardIngestConfigVisual.subtitleLabel.text=Configure the ingest modules you would like to run on this data source.
AddImageWizardAddingProgressVisual.statusLabel.text=Data source has been added to the local database. Files are being analyzed.
AddImageWizardChooseDataSourceVisual.typeTabel.text=Select source type to add:
AddImageWizardChooseDataSourceVisual.typeTabel.text=Select data source type:
AddImageWizardChooseDataSourceVisual.jLabel2.text=jLabel2
AddImageWizardChooseDataSourceVisual.nextLabel.text=<html> Press 'Next' to analyze the input data, extract volume and file system data, and populate a local database.</html>
AddImageWizardAddingProgressVisual.progressLabel.text=<progress>
AddImageWizardAddingProgressVisual.viewLogButton.text=View Log
AddImageWizardAddingProgressVisual.subTitle1Label.text=Processing data source and adding it to a local database. File analysis will start when this finishes.
@@ -100,7 +98,7 @@ AddImageWizardAddingProgressVisual.getName.text=Add Data Source
AddImageWizardAddingProgressVisual.showErrors.critText=*Failed to add data source (critical errors encountered). Click below to view the log.
AddImageWizardAddingProgressVisual.showErrors.nonCritText=*Data Source added (non-critical errors encountered). Click below to view the log.
AddImageWizardChooseDataSourcePanel.moveFocusNext=Next >
AddImageWizardChooseDataSourceVisual.getName.text=Enter Data Source Information
AddImageWizardChooseDataSourceVisual.getName.text=Select Data Source
AddImageWizardIngestConfigPanel.dsProcDone.noErrs.text=*Data Source added.
AddImageWizardIngestConfigPanel.dsProcDone.errs.text=*Errors encountered in adding Data Source.
AddImageWizardIngestConfigVisual.getName.text=Configure Ingest Modules
@@ -219,14 +217,6 @@ RecentItems.openRecentCase.msgDlg.text=Case {0} no longer exists.
StartupWindow.title.text=Welcome
UpdateRecentCases.menuItem.clearRecentCases.text=Clear Recent Cases
UpdateRecentCases.menuItem.empty=-Empty-
XMLCaseManagement.create.exception.msg=Error setting up Case XML file,
XMLCaseManagement.writeFile.exception.noCase.msg=No set case to write management file for.
XMLCaseManagement.writeFile.exception.errWriteToFile.msg=Error writing to case file
XMLCaseManagement.open.exception.errReadXMLFile.msg=Error reading case XML file\: {0}
XMLCaseManagement.open.msgDlg.notAutCase.msg=Error\: This is not an Autopsy config file ("{0}").\n\n\
Detail\: \n\
Cannot open a non-Autopsy config file (at {1}).
XMLCaseManagement.open.msgDlg.notAutCase.title=Error
AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel
ImageFilePanel.errorLabel.text=Error Label
DataSourceOnCDriveError.text=Warning\: Path to multi-user data source is on "C\:" drive
@@ -53,11 +53,9 @@ LocalFilesPanel.clearButton.text=\u30af\u30ea\u30a2
LocalFilesPanel.clearButton.toolTipText=\u73fe\u5728\u9078\u629e\u3055\u308c\u3066\u3044\u308b\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\u304c\u30af\u30ea\u30a2\u3055\u308c\u307e\u3059
LocalFilesPanel.localFileChooser.approveButtonText=\u9078\u629e
LocalFilesPanel.selectButton.actionCommand=\u8ffd\u52a0
AddImageWizardIngestConfigVisual.subtitleLabel.text=\u3053\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306b\u5bfe\u3057\u3066\u5b9f\u884c\u3057\u305f\u3044\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u8a2d\u5b9a\u3057\u307e\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
AddImageWizardChooseDataSourceVisual.nextLabel.text=<html> \u300c\u6b21\u3078\u300d\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u3001\u30a4\u30f3\u30d7\u30c3\u30c8\u30c7\u30fc\u30bf\u3092\u89e3\u6790\u3001\u30dc\u30ea\u30e5\u30fc\u30e0\u304a\u3088\u3073\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u30c7\u30fc\u30bf\u3092\u62bd\u51fa\u3001\u30ed\u30fc\u30ab\u30eb\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30c7\u30fc\u30bf\u3092\u6295\u5165\u3002</html>
AddImageWizardAddingProgressVisual.progressLabel.text=\uff1c\u30d7\u30ed\u30b0\u30ec\u30b9\uff1e
AddImageWizardAddingProgressVisual.viewLogButton.text=\u30ed\u30b0\u3092\u8868\u793a
AddImageWizardAddingProgressVisual.subTitle1Label.text=\u30ed\u30fc\u30ab\u30eb\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u60c5\u5831\u3092\u8ffd\u52a0\u4e2d\u3067\u3059\u3002\u3053\u3061\u3089\u304c\u5b8c\u4e86\u6b21\u7b2c\u3001\u30d5\u30a1\u30a4\u30eb\u89e3\u6790\u304c\u59cb\u307e\u308a\u307e\u3059\u3002
@@ -178,14 +176,6 @@ RecentItems.openRecentCase.msgDlg.text=\u30a8\u30e9\u30fc\uff1a\u30b1\u30fc\u30b
StartupWindow.title.text=\u3088\u3046\u3053\u305d
UpdateRecentCases.menuItem.clearRecentCases.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u30af\u30ea\u30a2
UpdateRecentCases.menuItem.empty=-\u7a7a\u767d-
XMLCaseManagement.create.exception.msg=\u30b1\u30fc\u30b9XML\u30d5\u30a1\u30a4\u30eb\u306e\u8a2d\u5b9a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3001
XMLCaseManagement.writeFile.exception.noCase.msg=\u30de\u30cd\u30b8\u30e1\u30f3\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u66f8\u304f\u5fc5\u8981\u304c\u3042\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002
XMLCaseManagement.writeFile.exception.errWriteToFile.msg=\u30b1\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3078\u306e\u66f8\u304d\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
XMLCaseManagement.open.exception.errReadXMLFile.msg=\u30b1\u30fc\u30b9XML\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u53d6\u308a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}
XMLCaseManagement.open.msgDlg.notAutCase.msg=\u30a8\u30e9\u30fc\uff1aAutopsy\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb("{0}")\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n\n\
\u8a73\u7d30\uff1a\n\
Autopsy\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u4ee5\u5916\u306f(at {1})\u3067\u958b\u3051\u307e\u305b\u3093\u3002
XMLCaseManagement.open.msgDlg.notAutCase.title=\u30a8\u30e9\u30fc
ImageFilePanel.noFatOrphansCheckbox.text=FAT\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u306e\u30aa\u30fc\u30d5\u30a1\u30f3\u30d5\u30a1\u30a4\u30eb\u306f\u7121\u8996
LocalDiskPanel.noFatOrphansCheckbox.text=FAT\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u306e\u30aa\u30fc\u30d5\u30a1\u30f3\u30d5\u30a1\u30a4\u30eb\u306f\u7121\u8996
AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=\u30ad\u30e3\u30f3\u30bb\u30eb
@@ -48,6 +48,7 @@ import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.apache.commons.io.FileUtils;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.actions.CallableSystemAction;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.CaseMetadata.CaseMetadataException;
@@ -260,19 +261,12 @@ public class Case implements SleuthkitCase.ErrorObserver {
}
};
private String name;
private String number;
private String examiner;
private String configFilePath;
private final XMLCaseManagement xmlcm;
private final CaseMetadata caseMetadata;
private final SleuthkitCase db;
// Track the current case (only set with changeCase() method)
private static Case currentCase = null;
private final CaseType caseType;
private final Services services;
private static final Logger logger = Logger.getLogger(Case.class.getName());
static final String CASE_EXTENSION = "aut"; //NON-NLS
static final String CASE_DOT_EXTENSION = "." + CASE_EXTENSION;
private final static String CACHE_FOLDER = "Cache"; //NON-NLS
private final static String EXPORT_FOLDER = "Export"; //NON-NLS
private final static String LOG_FOLDER = "Log"; //NON-NLS
@@ -288,13 +282,8 @@ public class Case implements SleuthkitCase.ErrorObserver {
/**
* Constructor for the Case class
*/
private Case(String name, String number, String examiner, String configFilePath, XMLCaseManagement xmlcm, SleuthkitCase db, CaseType type) {
this.name = name;
this.number = number;
this.examiner = examiner;
this.configFilePath = configFilePath;
this.xmlcm = xmlcm;
this.caseType = type;
private Case(CaseMetadata caseMetadata, SleuthkitCase db) {
this.caseMetadata = caseMetadata;
this.db = db;
this.services = new Services(db);
}
@@ -365,7 +354,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
NbBundle.getMessage(Case.class, "IntervalErrorReport.ErrorText"));
doCaseChange(currentCase);
SwingUtilities.invokeLater(() -> {
RecentCases.getInstance().addRecentCase(currentCase.name, currentCase.configFilePath); // update the recent cases
RecentCases.getInstance().addRecentCase(currentCase.getName(), currentCase.getCaseMetadata().getFilePath().toString()); // update the recent cases
});
if (CaseType.MULTI_USER_CASE == newCase.getCaseType()) {
try {
@@ -448,8 +437,9 @@ public class Case implements SleuthkitCase.ErrorObserver {
* CaseActionException.getCause will return a Throwable
* (null otherwise).
*
* @throws CaseActionException if there is a problem creating the case.
* @throws CaseActionException if there is a problem creating the case.
*/
@Messages({"Case.creationException=Could not create case: failed to make metadata file."})
public static void create(String caseDir, String caseName, String caseNumber, String examiner, CaseType caseType) throws CaseActionException {
logger.log(Level.INFO, "Creating case with case directory {0}, caseName {1}", new Object[]{caseDir, caseName}); //NON-NLS
@@ -478,14 +468,13 @@ public class Case implements SleuthkitCase.ErrorObserver {
/*
* Create the case metadata (.aut) file.
*
* TODO (AUT-1885): Replace use of obsolete and unsafe XMLCaseManagement
* class with use of CaseMetadata class.
*/
String configFilePath = caseDir + File.separator + caseName + CASE_DOT_EXTENSION;
XMLCaseManagement xmlcm = new XMLCaseManagement();
xmlcm.create(caseDir, caseName, examiner, caseNumber, caseType, dbName, indexName);
xmlcm.writeFile();
CaseMetadata metadata;
try {
metadata = new CaseMetadata(caseDir, caseType, caseName, caseNumber, examiner, dbName, indexName);
} catch (CaseMetadataException ex) {
throw new CaseActionException(Bundle.Case_creationException(), ex);
}
/*
* Create the case database.
@@ -515,7 +504,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.databaseConnectionInfo.error.msg"), ex);
}
Case newCase = new Case(caseName, caseNumber, examiner, configFilePath, xmlcm, db, caseType);
Case newCase = new Case(metadata, db);
changeCase(newCase);
}
@@ -598,8 +587,8 @@ public class Case implements SleuthkitCase.ErrorObserver {
/*
* Verify the extension of the case metadata file.
*/
if (!caseMetadataFilePath.endsWith(CASE_DOT_EXTENSION)) {
throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.open.exception.checkFile.msg", CASE_DOT_EXTENSION));
if (!caseMetadataFilePath.endsWith(CaseMetadata.getFileExtension())) {
throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.open.exception.checkFile.msg", CaseMetadata.getFileExtension()));
}
try {
@@ -607,25 +596,23 @@ public class Case implements SleuthkitCase.ErrorObserver {
* Get the case metadata required to open the case database.
*/
CaseMetadata metadata = new CaseMetadata(Paths.get(caseMetadataFilePath));
String caseName = metadata.getCaseName();
String caseNumber = metadata.getCaseNumber();
String examiner = metadata.getExaminer();
CaseType caseType = metadata.getCaseType();
String caseDir = metadata.getCaseDirectory();
/*
* Open the case database.
*/
SleuthkitCase db;
String caseDir;
if (caseType == CaseType.SINGLE_USER_CASE) {
String dbPath = Paths.get(caseDir, "autopsy.db").toString(); //NON-NLS
String dbPath = metadata.getCaseDatabasePath(); //NON-NLS
db = SleuthkitCase.openCase(dbPath);
caseDir = new File(dbPath).getParent();
} else {
if (!UserPreferences.getIsMultiUserModeEnabled()) {
throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.open.exception.multiUserCaseNotEnabled"));
}
try {
db = SleuthkitCase.openCase(metadata.getCaseDatabaseName(), UserPreferences.getDatabaseConnectionInfo(), caseDir);
db = SleuthkitCase.openCase(metadata.getCaseDatabaseName(), UserPreferences.getDatabaseConnectionInfo(), metadata.getCaseDirectory());
} catch (UserPreferencesException ex) {
throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.databaseConnectionInfo.error.msg"), ex);
}
@@ -674,14 +661,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
}
}
}
/*
* TODO (AUT-1885): Replace use of obsolete and unsafe
* XMLCaseManagement class with use of CaseMetadata class.
*/
XMLCaseManagement xmlcm = new XMLCaseManagement();
xmlcm.open(caseMetadataFilePath);
Case openedCase = new Case(caseName, caseNumber, examiner, caseMetadataFilePath, xmlcm, db, caseType);
Case openedCase = new Case(metadata, db);
changeCase(openedCase);
} catch (CaseMetadataException ex) {
@@ -859,7 +839,6 @@ public class Case implements SleuthkitCase.ErrorObserver {
changeCase(null);
try {
services.close();
this.xmlcm.close(); // close the xmlcm
this.db.close();
} catch (Exception e) {
throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.closeCase.exception.msg"), e);
@@ -877,11 +856,9 @@ public class Case implements SleuthkitCase.ErrorObserver {
logger.log(Level.INFO, "Deleting case.\ncaseDir: {0}", caseDir); //NON-NLS
try {
xmlcm.close(); // close the xmlcm
boolean result = deleteCaseDirectory(caseDir); // delete the directory
RecentCases.getInstance().removeRecentCase(this.name, this.configFilePath); // remove it from the recent case
RecentCases.getInstance().removeRecentCase(this.caseMetadata.getCaseName(), this.caseMetadata.getFilePath().toString()); // remove it from the recent case
Case.changeCase(null);
if (result == false) {
throw new CaseActionException(
@@ -906,8 +883,8 @@ public class Case implements SleuthkitCase.ErrorObserver {
*/
void updateCaseName(String oldCaseName, String oldPath, String newCaseName, String newPath) throws CaseActionException {
try {
xmlcm.setCaseName(newCaseName); // set the case
name = newCaseName; // change the local value
getCaseMetadata().setCaseName(newCaseName); // set the case
caseMetadata.setCaseName(newCaseName); // change the local value
eventPublisher.publish(new AutopsyEvent(Events.NAME.toString(), oldCaseName, newCaseName));
SwingUtilities.invokeLater(() -> {
try {
@@ -922,42 +899,6 @@ public class Case implements SleuthkitCase.ErrorObserver {
}
}
/**
* Updates the case examiner
*
* This should not be called from the EDT.
*
* @param oldExaminer the old examiner
* @param newExaminer the new examiner
*/
void updateExaminer(String oldExaminer, String newExaminer) throws CaseActionException {
try {
xmlcm.setCaseExaminer(newExaminer); // set the examiner
examiner = newExaminer;
eventPublisher.publish(new AutopsyEvent(Events.EXAMINER.toString(), oldExaminer, newExaminer));
} catch (Exception e) {
throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateExaminer.exception.msg"), e);
}
}
/**
* Updates the case number
*
* This should not be called from the EDT.
*
* @param oldCaseNumber the old case number
* @param newCaseNumber the new case number
*/
void updateCaseNumber(String oldCaseNumber, String newCaseNumber) throws CaseActionException {
try {
xmlcm.setCaseNumber(newCaseNumber); // set the case number
number = newCaseNumber;
eventPublisher.publish(new AutopsyEvent(Events.NUMBER.toString(), oldCaseNumber, newCaseNumber));
} catch (Exception e) {
throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateCaseNum.exception.msg"), e);
}
}
/**
* Checks whether there is a current case open.
*
@@ -967,24 +908,6 @@ public class Case implements SleuthkitCase.ErrorObserver {
return currentCase != null;
}
/**
* Uses the given path to store it as the configuration file path
*
* @param givenPath the given config file path
*/
private void setConfigFilePath(String givenPath) {
configFilePath = givenPath;
}
/**
* Get the config file path in the given path
*
* @return configFilePath the path of the configuration file
*/
String getConfigFilePath() {
return configFilePath;
}
/**
* Returns the current version of Autopsy
*
@@ -994,6 +917,13 @@ public class Case implements SleuthkitCase.ErrorObserver {
return autopsyVer;
}
/**
* @return the caseMetadata
*/
CaseMetadata getCaseMetadata() {
return caseMetadata;
}
/**
* Gets the application name
*
@@ -1012,7 +942,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
* @return name
*/
public String getName() {
return name;
return caseMetadata.getCaseName();
}
/**
@@ -1021,7 +951,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
* @return number
*/
public String getNumber() {
return number;
return caseMetadata.getCaseNumber();
}
/**
@@ -1030,7 +960,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
* @return examiner
*/
public String getExaminer() {
return examiner;
return caseMetadata.getExaminer();
}
/**
@@ -1039,11 +969,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
* @return caseDirectoryPath
*/
public String getCaseDirectory() {
if (xmlcm == null) {
return "";
} else {
return xmlcm.getCaseDirectory();
}
return caseMetadata.getCaseDirectory();
}
/**
@@ -1052,7 +978,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
* @return
*/
public CaseType getCaseType() {
return this.caseType;
return this.getCaseMetadata().getCaseType();
}
/**
@@ -1170,7 +1096,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
private String getHostDirectory() {
String caseDirectory = getCaseDirectory();
Path hostPath;
if (caseType == CaseType.MULTI_USER_CASE) {
if (getCaseMetadata().getCaseType() == CaseType.MULTI_USER_CASE) {
hostPath = Paths.get(caseDirectory, NetworkUtils.getLocalHostName());
} else {
hostPath = Paths.get(caseDirectory);
@@ -1241,11 +1167,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
* @return case creation date
*/
public String getCreatedDate() {
if (xmlcm == null) {
return "";
} else {
return xmlcm.getCreatedDate();
}
return getCaseMetadata().getCreatedDate();
}
/**
@@ -1254,11 +1176,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
* @return Index name.
*/
public String getTextIndexName() {
if (xmlcm == null) {
return "";
} else {
return xmlcm.getTextIndexName();
}
return getCaseMetadata().getTextIndexName();
}
/**
@@ -1621,7 +1539,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
if (RuntimeProperties.coreComponentsAreActive()) {
SwingUtilities.invokeLater(() -> {
updateMainWindowTitle(currentCase.name);
updateMainWindowTitle(currentCase.getName());
});
} else {
SwingUtilities.invokeLater(() -> {
@@ -1754,4 +1672,15 @@ public class Case implements SleuthkitCase.ErrorObserver {
return hasData;
}
/**
* Gets the full path to the case metadata file for this case.
*
* @return configFilePath The case metadata file path.
* @deprecated Use getCaseMetadata and CaseMetadata.getFilePath instead.
*/
@Deprecated
String getConfigFilePath() {
return getCaseMetadata().getFilePath().toString();
}
}
@@ -1,52 +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.casemodule;
/**
* NOTE: NOTHING ACTUALLY USES THIS
*
* The interface for the classes that edit the case configuration file
*/
//TODO: check that this can just be deleted.
interface CaseConfigFileInterface {
public void open(String conFilePath) throws Exception; // opens the confiuation store (XML, DB...)
public void writeFile() throws Exception; // writes out the configuration to store
public void close() throws Exception; // close and clear the document handler
// public int[] getImageIDs() throws Exception; // returns a list of image IDs and names
// public int getNextImageID() throws Exception; // returns the next free ID to be assigned to new image, and increments the internal counter
// all the get and set methods
public String getCaseName() throws Exception; // get the case name
public void setCaseName(String caseName) throws Exception; // set the case name
public String getCaseNumber() throws Exception; // get the case number
public void setCaseNumber(String caseNumber) throws Exception; // set the case number
public String getCaseExaminer() throws Exception; // get the examiner
public void setCaseExaminer(String examiner) throws Exception; // set the examiner
// public void getXXX(); // methods to get the case attributes
// public void setXXX(); // methods to set the case attributes
}
@@ -81,8 +81,7 @@ final class CaseDeleteAction extends CallableSystemAction {
@Override
public void actionPerformed(ActionEvent e) {
Case currentCase = Case.getCurrentCase();
File configFile = new File(currentCase.getConfigFilePath());
File caseFolder = new File(configFile.getParent());
File caseFolder = new File(currentCase.getCaseDirectory());
String caseName = currentCase.getName();
if (!caseFolder.exists()) {
// throw an error
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2015 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,98 +18,138 @@
*/
package org.sleuthkit.autopsy.casemodule;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Provides access to case metadata.
* Provides access to the case metadata stored in the case metadata file.
*/
public final class CaseMetadata {
private static final String FILE_EXTENSION = ".aut";
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
private static final String SCHEMA_VERSION_ONE = "1.0";
private final static String AUTOPSY_CREATED_VERSION_ELEMENT_NAME = "AutopsyCreatedVersion"; //NON-NLS
private final static String CASE_DATABASE_NAME_ELEMENT_NAME = "DatabaseName"; //NON-NLS
private final static String TEXT_INDEX_NAME_ELEMENT = "TextIndexName"; //NON-NLS
private static final String CURRENT_SCHEMA_VERSION = "2.0";
private final static String ROOT_ELEMENT_NAME = "AutopsyCase"; //NON-NLS
private final static String SCHEMA_VERSION_ELEMENT_NAME = "SchemaVersion"; //NON-NLS
private final static String CREATED_DATE_ELEMENT_NAME = "CreatedDate"; //NON-NLS
private final static String MODIFIED_DATE_ELEMENT_NAME = "ModifiedDate"; //NON-NLS
private final static String AUTOPSY_CREATED_BY_ELEMENT_NAME = "CreatedByAutopsyVersion"; //NON-NLS
private final static String AUTOPSY_SAVED_BY_ELEMENT_NAME = "SavedByAutopsyVersion"; //NON-NLS
private final static String CASE_ELEMENT_NAME = "Case"; //NON-NLS
private final static String CASE_NAME_ELEMENT_NAME = "Name"; //NON-NLS
private final static String CASE_NUMBER_ELEMENT_NAME = "Number"; //NON-NLS
private final static String EXAMINER_ELEMENT_NAME = "Examiner"; //NON-NLS
private final static String CASE_TYPE_ELEMENT_NAME = "CaseType"; //NON-NLS
private final static String CASE_DATABASE_ELEMENT_NAME = "Database"; //NON-NLS
private final static String TEXT_INDEX_ELEMENT = "TextIndex"; //NON-NLS
private final Path metadataFilePath;
private Case.CaseType caseType;
private String caseName;
private String caseNumber;
private String examiner;
private String caseDatabase;
private String textIndexName;
private String createdDate;
private String createdByVersion;
/**
* Exception thrown by the CaseMetadata class when there is a problem
* accessing the metadata for a case.
* Gets the file extension used for case metadata files.
*
* @return The file extension.
*/
public final static class CaseMetadataException extends Exception {
private static final long serialVersionUID = 1L;
private CaseMetadataException(String message) {
super(message);
}
private CaseMetadataException(String message, Throwable cause) {
super(message, cause);
}
public static String getFileExtension() {
return FILE_EXTENSION;
}
private final Case.CaseType caseType;
private final String caseName;
private final String caseNumber;
private final String examiner;
private final String caseDirectory;
private final String caseDatabaseName;
private final String caseTextIndexName;
/**
* Constructs an object that provides access to the case metadata stored in
* a new case metadata file that is created using the supplied metadata.
*
* @param caseDirectory The case directory.
* @param caseType The type of case.
* @param caseName The name of the case.
* @param caseNumber The case number.
* @param examiner The name of the case examiner.
* @param caseDatabase For a single-user case, the full path to the
* case database file. For a multi-user case, the
* case database name.
* @param caseTextIndexName The text index name.
*
* @throws CaseMetadataException If the new case metadata file cannot be
* created.
*/
CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseNumber, String examiner, String caseDatabase, String caseTextIndexName) throws CaseMetadataException {
metadataFilePath = Paths.get(caseDirectory, caseName + FILE_EXTENSION);
this.caseType = caseType;
this.caseName = caseName;
this.caseNumber = caseNumber;
this.examiner = examiner;
this.caseDatabase = caseDatabase;
this.textIndexName = caseTextIndexName;
createdByVersion = Version.getVersion();
createdDate = CaseMetadata.DATE_FORMAT.format(new Date());
writeToFile();
}
/**
* Constructs an object that provides access to case metadata.
* Constructs an object that provides access to the case metadata stored in
* an existing case metadata file.
*
* @param metadataFilePath Path to the metadata (.aut) file for a case.
* @param metadataFilePath The full path to the case metadata file.
*
* @throws CaseMetadataException If the new case metadata file cannot be
* read.
*/
public CaseMetadata(Path metadataFilePath) throws CaseMetadataException {
try {
/*
* TODO (RC): This class should eventually replace the non-public
* and unsafe XMLCaseManagement class altogether.
*/
XMLCaseManagement metadata = new XMLCaseManagement();
metadata.open(metadataFilePath.toString());
try {
caseType = metadata.getCaseType();
} catch (NullPointerException unused) {
throw new CaseMetadataException("Case type element missing");
}
try {
caseName = metadata.getCaseName();
if (caseName.isEmpty()) {
throw new CaseMetadataException("Case name missing");
}
} catch (NullPointerException unused) {
throw new CaseMetadataException("Case name element missing");
}
try {
caseNumber = metadata.getCaseNumber();
} catch (NullPointerException unused) {
throw new CaseMetadataException("Case number element missing");
}
try {
examiner = metadata.getCaseExaminer();
} catch (NullPointerException unused) {
throw new CaseMetadataException("Examiner element missing");
}
try {
caseDirectory = metadata.getCaseDirectory();
if (caseDirectory.isEmpty()) {
throw new CaseMetadataException("Case directory missing");
}
} catch (NullPointerException unused) {
throw new CaseMetadataException("Case directory element missing");
}
try {
caseDatabaseName = metadata.getDatabaseName();
} catch (NullPointerException unused) {
throw new CaseMetadataException("Case database element missing");
}
try {
caseTextIndexName = metadata.getTextIndexName();
if (Case.CaseType.MULTI_USER_CASE == caseType && caseDatabaseName.isEmpty()) {
throw new CaseMetadataException("Case keyword search index name missing");
}
} catch (NullPointerException unused) {
throw new CaseMetadataException("Case keyword search index name missing");
}
} catch (CaseActionException ex) {
throw new CaseMetadataException(ex.getLocalizedMessage(), ex);
}
this.metadataFilePath = metadataFilePath;
readFromFile();
}
/**
* Gets the full path to the case metadata file.
*
* @return The path to the metadata file
*/
Path getFilePath() {
return metadataFilePath;
}
/**
* Gets the case directory.
*
* @return The case directory.
*/
public String getCaseDirectory() {
return metadataFilePath.getParent().toString();
}
/**
@@ -118,18 +158,35 @@ public final class CaseMetadata {
* @return The case type.
*/
public Case.CaseType getCaseType() {
return this.caseType;
return caseType;
}
/**
* Gets the case name.
* Gets the case display name.
*
* @return The case name.
* @return The case display name.
*/
public String getCaseName() {
return caseName;
}
/**
* Sets the case display name. This does not change the name of the case
* directory, the case database, or the text index name.
*
* @param caseName A case display name.
*/
void setCaseName(String caseName) throws CaseMetadataException {
String oldCaseName = caseName;
this.caseName = caseName;
try {
writeToFile();
} catch (CaseMetadataException ex) {
this.caseName = oldCaseName;
throw ex;
}
}
/**
* Gets the case number.
*
@@ -149,30 +206,281 @@ public final class CaseMetadata {
}
/**
* Gets the case directory.
* Gets the name of the case case database.
*
* @return The case directory.
* @return The case database name.
*/
public String getCaseDirectory() {
return caseDirectory;
public String getCaseDatabaseName() {
if (caseType == Case.CaseType.MULTI_USER_CASE) {
return caseDatabase;
} else {
return Paths.get(caseDatabase).getFileName().toString();
}
}
/**
* Gets the case database name.
* Gets the full path to the case database file if the case is a single-user
* case.
*
* @return The case database name, will be empty for a single-user case.
* @return The full path to the case database file for a single-user case.
*
* @throws UnsupportedOperationException If called for a multi-user case.
*/
public String getCaseDatabaseName() {
return caseDatabaseName;
public String getCaseDatabasePath() throws UnsupportedOperationException {
if (caseType == Case.CaseType.SINGLE_USER_CASE) {
return caseDatabase;
} else {
throw new UnsupportedOperationException();
}
}
/**
* Gets the text index name.
*
* @return The case text index name, will be empty for a single-user case.
* @return The name of the text index for the case.
*/
public String getTextIndexName() {
return caseTextIndexName;
return textIndexName;
}
/**
* Gets the date the case was created.
*
* @return The date this case was created as a string
*/
String getCreatedDate() {
return createdDate;
}
/**
* Sets the date the case was created. Used for preserving the case creation
* date during single-user to multi-user case conversion.
*
* @param createdDate The date the case was created as a string.
*/
void setCreatedDate(String createdDate) throws CaseMetadataException {
String oldCreatedDate = createdDate;
this.createdDate = createdDate;
try {
writeToFile();
} catch (CaseMetadataException ex) {
this.createdDate = oldCreatedDate;
throw ex;
}
}
/**
* Gets the Autopsy version that created the case.
*
* @return A build identifier.
*/
String getCreatedByVersion() {
return createdByVersion;
}
/**
* Sets the Autopsy version that created the case. Used for preserving this
* metadata during single-user to multi-user case conversion.
*
* @param buildVersion An build version identifier.
*/
void setCreatedByVersion(String buildVersion) throws CaseMetadataException {
String oldCreatedByVersion = this.createdByVersion;
this.createdByVersion = buildVersion;
try {
this.writeToFile();
} catch (CaseMetadataException ex) {
this.createdByVersion = oldCreatedByVersion;
throw ex;
}
}
/**
* Writes the case metadata to the metadata file.
*
* @throws CaseMetadataException If there is an error writing to the case
* metadata file.
*/
private void writeToFile() throws CaseMetadataException {
try {
/*
* Create the XML DOM.
*/
Document doc = XMLUtil.createDocument();
createXMLDOM(doc);
doc.normalize();
/*
* Prepare the DOM for pretty printing to the metadata file.
*/
Source source = new DOMSource(doc);
StringWriter stringWriter = new StringWriter();
Result streamResult = new StreamResult(stringWriter);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //NON-NLS
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); //NON-NLS
transformer.transform(source, streamResult);
/*
* Write the DOM to the metadata file.
*/
try (BufferedWriter fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(metadataFilePath.toFile())))) {
fileWriter.write(stringWriter.toString());
fileWriter.flush();
}
} catch (ParserConfigurationException | TransformerException | IOException ex) {
throw new CaseMetadataException(String.format("Error writing to case metadata file %s", metadataFilePath), ex);
}
}
/*
* Creates an XML DOM from the case metadata.
*/
private void createXMLDOM(Document doc) {
/*
* Create the root element and its children.
*/
Element rootElement = doc.createElement(ROOT_ELEMENT_NAME);
doc.appendChild(rootElement);
createChildElement(doc, rootElement, SCHEMA_VERSION_ELEMENT_NAME, CURRENT_SCHEMA_VERSION);
createChildElement(doc, rootElement, CREATED_DATE_ELEMENT_NAME, createdDate);
createChildElement(doc, rootElement, MODIFIED_DATE_ELEMENT_NAME, DATE_FORMAT.format(new Date()));
createChildElement(doc, rootElement, AUTOPSY_CREATED_BY_ELEMENT_NAME, createdByVersion);
createChildElement(doc, rootElement, AUTOPSY_SAVED_BY_ELEMENT_NAME, Version.getVersion());
Element caseElement = doc.createElement(CASE_ELEMENT_NAME);
rootElement.appendChild(caseElement);
/*
* Create the children of the case element.
*/
createChildElement(doc, caseElement, CASE_NAME_ELEMENT_NAME, caseName);
createChildElement(doc, caseElement, CASE_NUMBER_ELEMENT_NAME, caseNumber);
createChildElement(doc, caseElement, EXAMINER_ELEMENT_NAME, examiner);
createChildElement(doc, caseElement, CASE_TYPE_ELEMENT_NAME, caseType.toString());
createChildElement(doc, caseElement, CASE_DATABASE_ELEMENT_NAME, caseDatabase);
createChildElement(doc, caseElement, TEXT_INDEX_ELEMENT, textIndexName);
}
/**
* Creates an XML element for the case metadata XML DOM.
*
* @param doc The document.
* @param parentElement The parent element of the element to be created.
* @param elementName The name of the element to be created.
* @param elementContent The text content of the element to be created, may
* be empty.
*/
private void createChildElement(Document doc, Element parentElement, String elementName, String elementContent) {
Element element = doc.createElement(elementName);
element.appendChild(doc.createTextNode(elementContent));
parentElement.appendChild(element);
}
/**
* Reads the case metadata from the metadata file.
*
* @throws CaseMetadataException If there is an error reading from the case
* metadata file.
*/
private void readFromFile() throws CaseMetadataException {
try {
/*
* Parse the file into an XML DOM and get the root element.
*/
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(this.getFilePath().toFile());
doc.getDocumentElement().normalize();
Element rootElement = doc.getDocumentElement();
if (!rootElement.getNodeName().equals(ROOT_ELEMENT_NAME)) {
throw new CaseMetadataException("Case metadata file corrupted");
}
/*
* Get the content of the relevant children of the root element.
*/
String schemaVersion = getElementTextContent(rootElement, SCHEMA_VERSION_ELEMENT_NAME, true);
this.createdDate = getElementTextContent(rootElement, CREATED_DATE_ELEMENT_NAME, true);
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) {
this.createdByVersion = getElementTextContent(rootElement, AUTOPSY_CREATED_VERSION_ELEMENT_NAME, true);
} else {
this.createdByVersion = getElementTextContent(rootElement, AUTOPSY_CREATED_BY_ELEMENT_NAME, true);
}
/*
* Get the content of the children of the case element.
*/
NodeList caseElements = doc.getElementsByTagName(CASE_ELEMENT_NAME);
if (caseElements.getLength() == 0) {
throw new CaseMetadataException("Case metadata file corrupted");
}
Element caseElement = (Element) caseElements.item(0);
this.caseName = getElementTextContent(caseElement, CASE_NAME_ELEMENT_NAME, true);
this.caseNumber = getElementTextContent(caseElement, CASE_NUMBER_ELEMENT_NAME, false);
this.examiner = getElementTextContent(caseElement, EXAMINER_ELEMENT_NAME, false);
this.caseType = Case.CaseType.fromString(getElementTextContent(caseElement, CASE_TYPE_ELEMENT_NAME, true));
if (null == this.caseType) {
throw new CaseMetadataException("Case metadata file corrupted");
}
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) {
this.caseDatabase = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_NAME_ELEMENT, true);
} else {
this.caseDatabase = getElementTextContent(caseElement, CASE_DATABASE_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, true);
}
/*
* Update the file to the current schema, if necessary.
*/
if (!schemaVersion.equals(CURRENT_SCHEMA_VERSION)) {
writeToFile();
}
} catch (ParserConfigurationException | SAXException | IOException ex) {
throw new CaseMetadataException(String.format("Error reading from case metadata file %s", metadataFilePath), ex);
}
}
/**
* Gets the text content of an XML element.
*
* @param parentElement The parent element.
* @param elementName The element name.
* @param contentIsRequired Whether or not the content is required.
*
* @return The text content, may be empty if not required.
*
* @throws CaseMetadataException If the element is missing or content is
* required and it is empty.
*/
private String getElementTextContent(Element parentElement, String elementName, boolean contentIsRequired) throws CaseMetadataException {
NodeList elementsList = parentElement.getElementsByTagName(elementName);
if (elementsList.getLength() == 0) {
throw new CaseMetadataException(String.format("Missing %s element from case metadata file %s", elementName, metadataFilePath));
}
String textContent = elementsList.item(0).getTextContent();
if (textContent.isEmpty() && contentIsRequired) {
throw new CaseMetadataException(String.format("Empty %s element in case metadata file %s", elementName, metadataFilePath));
}
return textContent;
}
/**
* Exception thrown by the CaseMetadata class when there is a problem
* accessing the metadata for a case.
*/
public final static class CaseMetadataException extends Exception {
private static final long serialVersionUID = 1L;
private CaseMetadataException(String message) {
super(message);
}
private CaseMetadataException(String message, Throwable cause) {
super(message, cause);
}
}
}
@@ -54,7 +54,7 @@ public final class CaseOpenAction implements ActionListener {
* Constructs an action that opens an existing case.
*/
public CaseOpenAction() {
caseMetadataFileFilter = new FileNameExtensionFilter(NbBundle.getMessage(CaseOpenAction.class, "CaseOpenAction.autFilter.title", Version.getName(), Case.CASE_DOT_EXTENSION), Case.CASE_EXTENSION);
caseMetadataFileFilter = new FileNameExtensionFilter(NbBundle.getMessage(CaseOpenAction.class, "CaseOpenAction.autFilter.title", Version.getName(), CaseMetadata.getFileExtension()), CaseMetadata.getFileExtension().substring(1));
fileChooser.setDragEnabled(false);
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setMultiSelectionEnabled(false);
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,7 +24,6 @@
*/
package org.sleuthkit.autopsy.casemodule;
import java.awt.*;
import java.nio.file.Paths;
import java.awt.event.ActionListener;
import java.io.File;
@@ -41,9 +40,8 @@ import org.openide.NotifyDescriptor;
import org.openide.util.actions.CallableSystemAction;
/**
* The form where user can change / update the properties of the current case.
*
* @author jantonius
* The form where user can change / update the properties of the current case
* metadata.
*/
class CasePropertiesForm extends javax.swing.JPanel {
@@ -89,8 +87,12 @@ class CasePropertiesForm extends javax.swing.JPanel {
caseDirTextArea.setText(caseDir);
current = currentCase;
CaseMetadata caseMetadata = new CaseMetadata(Paths.get(currentCase.getConfigFilePath()));
tbDbName.setText(caseMetadata.getCaseDatabaseName());
CaseMetadata caseMetadata = currentCase.getCaseMetadata();
if (caseMetadata.getCaseType() == Case.CaseType.SINGLE_USER_CASE) {
tbDbName.setText(caseMetadata.getCaseDatabasePath());
} else {
tbDbName.setText(caseMetadata.getCaseDatabaseName());
}
Case.CaseType caseType = caseMetadata.getCaseType();
tbDbType.setText(caseType.getLocalizedDisplayName());
if (caseType == Case.CaseType.SINGLE_USER_CASE) {
@@ -103,15 +105,16 @@ class CasePropertiesForm extends javax.swing.JPanel {
// create the headers and add all the rows
// Header names are internationalized via the generated code, do not overwrite.
String[] headers = {imagesTable.getColumnName(0),
imagesTable.getColumnName(1)};
String[] headers = {imagesTable.getColumnName(0),
imagesTable.getColumnName(1)};
String[][] rows = new String[totalImages][];
int i = 0;
for (long key : imgPaths.keySet()) {
String path = imgPaths.get(key);
String shortenPath = shrinkPath(path, 70);
rows[i++] = new String[]{shortenPath};
rows[i] = new String[]{shortenPath};
i++;
}
// create the table inside with the imgPaths information
@@ -124,61 +127,17 @@ class CasePropertiesForm extends javax.swing.JPanel {
}
};
imagesTable.setModel(model);
// // set the size of the remove column
// TableColumn removeCol = imagesTable.getColumnModel().getColumn(lastColumn);
// removeCol.setPreferredWidth(75);
// removeCol.setMaxWidth(75);
// removeCol.setMinWidth(75);
// removeCol.setResizable(false);
// // create the delete action to remove the image from the current case
// Action delete = new AbstractAction()
// {
// @Override
// public void actionPerformed(ActionEvent e)
// {
// // get the image path
// JTable table = (JTable)e.getSource();
// int modelRow = Integer.valueOf(e.getActionCommand());
// String removeColumn = table.getValueAt(modelRow, lastColumn).toString();
// // get the image ID
// int selectedID = Integer.parseInt(removeColumn.substring(0, removeColumn.indexOf('|')));
// String imagePath = removeColumn.substring(removeColumn.indexOf('|') + 1);
//
// // throw the confirmation first
// String confMsg = "Are you sure want to remove image \"" + imagePath + "\" from this case?";
// NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg, "Create directory", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
// d.setValue(NotifyDescriptor.NO_OPTION);
//
// Object res = DialogDisplayer.getDefault().notify(d);
// // if user select "Yes"
// if(res != null && res == DialogDescriptor.YES_OPTION){
// // remove the image in the case class and in the xml config file
// try {
// current.removeImage(selectedID, imagePath);
// } catch (Exception ex) {
// Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: couldn't remove image.", ex);
// }
// // remove the row of the image path
// ((DefaultTableModel)table.getModel()).removeRow(modelRow);
// }
// }
// };
//
// ButtonColumn buttonColumn = new ButtonColumn(imagesTable, delete, 1, "Remove");
// buttonColumn.setMnemonic(KeyEvent.VK_D);
}
/**
* In this generated code below, there are 2 strings "Path" and "Remove" that are
* table column headers in the DefaultTableModel. When this model is generated,
* it puts the hard coded English strings into the generated code. And then about 15
* lines later, it separately internationalizes them using:
* imagesTable.getColumnModel().getColumn(0).setHeaderValue().
* There is no way to prevent the GUI designer from putting the hard coded
* English strings into the generated code. So, they remain, and are not used.
/**
* In this generated code below, there are 2 strings "Path" and "Remove"
* that are table column headers in the DefaultTableModel. When this model
* is generated, it puts the hard coded English strings into the generated
* code. And then about 15 lines later, it separately internationalizes them
* using: imagesTable.getColumnModel().getColumn(0).setHeaderValue(). There
* is no way to prevent the GUI designer from putting the hard coded English
* strings into the generated code. So, they remain, and are not used.
*/
/**
* 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
@@ -429,9 +388,6 @@ class CasePropertiesForm extends javax.swing.JPanel {
private void updateCaseNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateCaseNameButtonActionPerformed
String oldCaseName = Case.getCurrentCase().getName();
String newCaseName = caseNameTextField.getText();
//String oldPath = caseDirTextArea.getText() + File.separator + oldCaseName + ".aut";
//String newPath = caseDirTextArea.getText() + File.separator + newCaseName + ".aut";
// check if the old and new case name is not equal
if (!oldCaseName.equals(newCaseName)) {
@@ -469,7 +425,7 @@ class CasePropertiesForm extends javax.swing.JPanel {
Object res = DialogDisplayer.getDefault().notify(d);
if (res != null && res == DialogDescriptor.YES_OPTION) {
// if user select "Yes"
String oldPath = current.getConfigFilePath();
String oldPath = current.getCaseMetadata().getFilePath().toString();
try {
current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath);
} catch (Exception ex) {
@@ -1,124 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
This file describes the schema definition for its twin files, $autopsyCaseDir/$case.aut
.aut files are created in the case directory when user makes a new case.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- definition of simple elements -->
<xs:element name="Name" type="String"/>
<xs:element name="Number" type="String" nillable="true"/>
<xs:element name="Examiner" type="String" nillable="true"/>
<xs:element name="CaseType" type="String" nillable="false"/>
<xs:element name="DatabaseName" type="String" nillable="false"/>
<xs:element name="TextIndexName" type="String" nillable="true"/>
<xs:attribute name="Relative" type="xs:boolean"/>
<xs:element name="CreatedDate" >
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="([0-9]{4}/)+([0-1][0-9]/)+([0-3][0-9] )+([0-2][0-9]:[0-5][0-9]:[0-9][0-9] )+(\([A-Z][A-Z][A-Z]\))"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="ModifiedDate">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="([0-9]{4}/)+([0-1][0-9]/)+([0-3][0-9] )+([0-2][0-9]:[0-5][0-9]:[0-9][0-9] )+(\([A-Z][A-Z][A-Z]\))"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="AutopsyCreatedVersion" type="xs:integer"/>
<xs:element name="AutopsySavedVersion" type="xs:integer"/>
<xs:element name="SchemaVersion" type="xs:decimal"/>
<!-- Wrappers over the built in values to allow empty string elements, eg <number/> -->
<xs:simpleType name="Integer">
<xs:union memberTypes="xs:integer empty"/>
</xs:simpleType>
<xs:simpleType name="String">
<xs:union memberTypes="xs:string empty"/>
</xs:simpleType>
<xs:simpleType name="empty">
<xs:restriction base="xs:string">
<xs:enumeration value="" />
</xs:restriction>
</xs:simpleType>
<!-- definition of complex elements -->
<xs:element name="ExportFolder">
<xs:complexType mixed="true">
<xs:attribute ref="Relative" default="true" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="LogFolder" >
<xs:complexType mixed="true">
<xs:attribute ref="Relative" default="true" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="TempFolder">
<xs:complexType mixed="true">
<xs:attribute ref="Relative" default="true" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="CacheFolder" >
<xs:complexType mixed="true">
<xs:attribute ref="Relative" default="true" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="Case">
<xs:complexType>
<xs:sequence>
<xs:element ref="Name"/>
<xs:element ref="Number" />
<xs:element ref="Examiner" />
<xs:element ref="ExportFolder"/>
<xs:element ref="LogFolder"/>
<xs:element ref="TempFolder"/>
<xs:element ref="CacheFolder"/>
<xs:sequence minOccurs="0" maxOccurs="1">
<xs:element ref="CaseType"/>
<xs:element ref="DatabaseName"/>
<xs:element ref="TextIndexName"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="AutopsyCase">
<xs:complexType>
<xs:sequence>
<xs:element ref="CreatedDate" />
<xs:element ref="ModifiedDate" />
<xs:element ref="AutopsyCreatedVersion"/>
<xs:element ref="AutopsySavedVersion"/>
<xs:element ref="SchemaVersion"/>
<xs:element ref="Case"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -408,7 +408,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
String[] casePaths = new String[LENGTH];
String currentCasePath = null;
try {
currentCasePath = Case.getCurrentCase().getConfigFilePath();
currentCasePath = Case.getCurrentCase().getCaseMetadata().getFilePath().toString();
} catch (IllegalStateException ex) {
// in case there is no current case.
}
@@ -46,7 +46,7 @@ import org.sleuthkit.autopsy.coreutils.NetworkUtils;
public class SingleUserCaseConverter {
private static final String AUTOPSY_DB_FILE = "autopsy.db"; //NON-NLS
private static final String DOTAUT = ".aut"; //NON-NLS
private static final String DOTAUT = CaseMetadata.getFileExtension(); //NON-NLS
private static final String TIMELINE_FOLDER = "Timeline"; //NON-NLS
private static final String TIMELINE_FILE = "events.db"; //NON-NLS
private static final String POSTGRES_DEFAULT_DB_NAME = "postgres"; //NON-NLS
@@ -165,9 +165,8 @@ public class SingleUserCaseConverter {
}
// Read old xml config
XMLCaseManagement oldXmlCaseManagement = new XMLCaseManagement();
oldXmlCaseManagement.open(icd.getCaseInputFolder().resolve(icd.getAutFileName()).toString());
if (oldXmlCaseManagement.getCaseType() == CaseType.MULTI_USER_CASE) {
CaseMetadata oldCaseMetadata = new CaseMetadata(icd.getCaseInputFolder().resolve(icd.getAutFileName()));
if (oldCaseMetadata.getCaseType() == CaseType.MULTI_USER_CASE) {
throw new Exception(NbBundle.getMessage(SingleUserCaseConverter.class, "SingleUserCaseConverter.AlreadyMultiUser")); //NON-NLS
}
@@ -191,15 +190,15 @@ public class SingleUserCaseConverter {
copyImages(icd);
// Create new .aut file
XMLCaseManagement newXmlCaseManagement = new XMLCaseManagement();
newXmlCaseManagement.create(icd.getCaseOutputFolder().toString(),
CaseMetadata newCaseMetadata = new CaseMetadata(icd.getCaseOutputFolder().toString(),
CaseType.MULTI_USER_CASE,
icd.getNewCaseName(),
oldXmlCaseManagement.getCaseExaminer(),
oldXmlCaseManagement.getCaseNumber(),
CaseType.MULTI_USER_CASE, dbName, solrName);
oldCaseMetadata.getCaseNumber(),
oldCaseMetadata.getExaminer(),
dbName, solrName);
// Set created date. This calls writefile, no need to call it again
newXmlCaseManagement.setCreatedDate(oldXmlCaseManagement.getCreatedDate());
newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate());
newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion());
// At this point the import has been finished successfully so we can delete the original case
// (if requested). This *should* be fairly safe - at this point we know there was an autopsy file
@@ -1,814 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012-2015 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.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
/**
*
* This class is used to create, access, and modify the XML configuration file,
* where we store the information about the case and image(s). This class uses
* the document handler to store the information about the case. The document
* handler will be created / opened when the case configuration file is created/
* opened.
*
* @author jantonius
*/
class XMLCaseManagement implements CaseConfigFileInterface {
final static String XSDFILE = "CaseSchema.xsd"; //NON-NLS
final static String TOP_ROOT_NAME = "AutopsyCase"; //NON-NLS
final static String CASE_ROOT_NAME = "Case"; //NON-NLS
// general metadata about the case file
final static String NAME = "Name"; //NON-NLS
final static String NUMBER = "Number"; //NON-NLS
final static String EXAMINER = "Examiner"; //NON-NLS
final static String CREATED_DATE_NAME = "CreatedDate"; //NON-NLS
final static String MODIFIED_DATE_NAME = "ModifiedDate"; //NON-NLS
final static String SCHEMA_VERSION_NAME = "SchemaVersion"; //NON-NLS
final static String AUTOPSY_CRVERSION_NAME = "AutopsyCreatedVersion"; //NON-NLS
final static String AUTOPSY_MVERSION_NAME = "AutopsySavedVersion"; //NON-NLS
final static String CASE_TEXT_INDEX_NAME = "TextIndexName"; //NON-NLS
// folders inside case directory
final static String LOG_FOLDER_NAME = "LogFolder"; //NON-NLS
final static String LOG_FOLDER_RELPATH = "Log"; //NON-NLS
final static String TEMP_FOLDER_NAME = "TempFolder"; //NON-NLS
final static String TEMP_FOLDER_RELPATH = "Temp"; //NON-NLS
final static String EXPORT_FOLDER_NAME = "ExportFolder"; //NON-NLS
final static String EXPORT_FOLDER_RELPATH = "Export"; //NON-NLS
final static String CACHE_FOLDER_NAME = "CacheFolder"; //NON-NLS
final static String CACHE_FOLDER_RELPATH = "Cache"; //NON-NLS
final static String CASE_TYPE = "CaseType"; //NON-NLS
final static String DATABASE_NAME = "DatabaseName"; //NON-NLS
// folders attribute
final static String RELATIVE_NAME = "Relative"; // relevant path info NON-NLS
// folder attr values
final static String RELATIVE_TRUE = "true"; // if it's a relative path NON-NLS
final static String RELATIVE_FALSE = "false"; // if it's not a relative path NON-NLS
// the document
private Document doc;
// general info
private final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
private String caseDirPath; // case directory path
private String caseName; // case name
private String caseNumber; // case number
private String examiner; // examiner name
private final String schemaVersion = "1.0";
private final String autopsySavedVersion;
private CaseType caseType; // The type of case: local or shared
private String dbName; // The name of the database
private String textIndexName; // The name of the index where extracted text is stored.
// for error handling
private JPanel caller;
private final String className = this.getClass().toString();
private static final Logger logger = Logger.getLogger(XMLCaseManagement.class.getName());
/**
* The constructor
*/
public XMLCaseManagement() {
autopsySavedVersion = System.getProperty("netbeans.buildnumber");
}
/**
* Sets the case directory path of the case directory on the local variable
*
* @param givenPath the new path to be stored as case directory path
*/
private void setCaseDirPath(String givenPath) {
caseDirPath = givenPath; // change this to change the xml file if needed
}
/**
* Sets the case Name on the XML configuration file
*
* @param givenCaseName the new case name to be set
*/
@Override
public void setCaseName(String givenCaseName) throws CaseActionException {
// change this to change the xml file if needed
Element nameElement = (Element) getCaseElement().getElementsByTagName(NAME).item(0);
nameElement.setTextContent(givenCaseName);
doc.normalize();
// edit the modified data
String newDate = dateFormat.format(new Date());
Element rootEl = getRootElement();
rootEl.getElementsByTagName(MODIFIED_DATE_NAME).item(0).setTextContent(newDate);
writeFile();
}
/**
* Sets the case number on the XML configuration file
*
* @param givenCaseNumber the new case number to be set
*/
@Override
public void setCaseNumber(String givenCaseNumber) throws CaseActionException {
// change this to change the xml file if needed
Element nameElement = (Element) getCaseElement().getElementsByTagName(NUMBER).item(0);
nameElement.setTextContent(String.valueOf(givenCaseNumber));
doc.normalize();
// edit the modified data
String newDate = dateFormat.format(new Date());
Element rootEl = getRootElement();
rootEl.getElementsByTagName(MODIFIED_DATE_NAME).item(0).setTextContent(newDate);
writeFile();
}
/**
* Sets the created date on the XML configuration file. This method is for
* preserving the created date when converting a case from single-user to
* multi-user.
*
* @param createdDate the date the case was originally created
*
* @throws org.sleuthkit.autopsy.casemodule.CaseActionException
*/
public void setCreatedDate(String createdDate) throws CaseActionException {
String newDate = dateFormat.format(new Date());
Element rootEl = getRootElement();
rootEl.getElementsByTagName(CREATED_DATE_NAME).item(0).setTextContent(createdDate);
rootEl.getElementsByTagName(MODIFIED_DATE_NAME).item(0).setTextContent(newDate);
writeFile();
}
/**
* Sets the examiner on the XML configuration file
*
* @param givenExaminer the new examiner to be set
*/
@Override
public void setCaseExaminer(String givenExaminer) throws CaseActionException {
// change this to change the xml file if needed
Element nameElement = (Element) getCaseElement().getElementsByTagName(EXAMINER).item(0);
nameElement.setTextContent(givenExaminer);
doc.normalize();
// edit the modified data
String newDate = dateFormat.format(new Date());
Element rootEl = getRootElement();
rootEl.getElementsByTagName(MODIFIED_DATE_NAME).item(0).setTextContent(newDate);
writeFile();
}
/**
* Sets the case name internally (on local variable in this class)
*
* @param givenCaseName the new case name
*/
private void setName(String givenCaseName) {
caseName = givenCaseName; // change this to change the xml file if needed
}
/**
* Sets the case number internally (on local variable in this class)
*
* @param givenCaseNumber the new case number
*/
private void setNumber(String givenCaseNumber) {
caseNumber = givenCaseNumber; // change this to change the xml file if needed
}
/**
* Sets the case type internally (on local variable in this class)
*
* @param givenCaseType the new case type
*/
private void setCaseType(CaseType givenCaseType) {
caseType = givenCaseType; // change this to change the xml file if needed
}
/**
* Gets the case Type from the document handler. Defaults to local if it
* can't figure it out.
*
* @return caseType from the document handler
*/
public CaseType getCaseType() {
if (doc == null) {
return CaseType.SINGLE_USER_CASE;
} else {
if (getCaseElement().getElementsByTagName(CASE_TYPE).getLength() > 0) {
Element nameElement = (Element) getCaseElement().getElementsByTagName(CASE_TYPE).item(0);
return CaseType.fromString(nameElement.getTextContent());
} else {
return CaseType.SINGLE_USER_CASE;
}
}
}
/**
* Sets the database name internally (on local variable in this class)
*
* @param givenDbName the new db name
*/
private void setDatabaseName(String givenDbName) {
dbName = givenDbName; // change this to change the xml file if needed
}
/**
* Gets the database name from the document handler
*
* @return the database name
*/
public String getDatabaseName() {
if (doc == null) {
return "";
} else {
if (getCaseElement().getElementsByTagName(DATABASE_NAME).getLength() > 0) {
Element nameElement = (Element) getCaseElement().getElementsByTagName(DATABASE_NAME).item(0);
return nameElement.getTextContent();
} else {
return ""; /// couldn't find one, so return a blank name
}
}
}
/**
* Sets the text index name internally (on local variable in this class)
*
* @param textIndexName the new name for the index where extracted text is
* stored for the case.
*/
private void setTextIndexName(String textIndexName) {
this.textIndexName = textIndexName; // change this to change the xml file if needed
}
/**
* Gets the name of the index where extracted text is stored.
*
* @return the index name
*/
public String getTextIndexName() {
if (doc == null) {
return "";
} else {
if (getCaseElement().getElementsByTagName(CASE_TEXT_INDEX_NAME).getLength() > 0) {
Element nameElement = (Element) getCaseElement().getElementsByTagName(CASE_TEXT_INDEX_NAME).item(0);
return nameElement.getTextContent();
} else {
return ""; /// couldn't find one, so return a blank index name
}
}
}
/**
* Sets the examiner name internally (on local variable in this class)
*
* @param givenExaminer the new examiner
*/
private void setExaminer(String givenExaminer) {
examiner = givenExaminer; // change this to change the xml file if needed
}
/**
* Gets the case Name from the document handler
*
* @return caseName the case name from the document handler
*/
@Override
public String getCaseName() {
if (doc == null) {
return "";
} else {
Element nameElement = (Element) getCaseElement().getElementsByTagName(NAME).item(0);
String result = nameElement.getTextContent();
return result;
}
}
/**
* Gets the case Number from the document handler
*
* @return caseNumber the case number from the document handler
*/
@Override
public String getCaseNumber() {
if (doc == null) {
return "";
} else {
Element numberElement = (Element) getCaseElement().getElementsByTagName(NUMBER).item(0);
String result = "-1";
if (numberElement != null) {
result = numberElement.getTextContent();
}
return result;
}
}
/**
* Gets the examiner from the document handler
*
* @return examiner the examiner from the document handler
*/
@Override
public String getCaseExaminer() {
if (doc == null) {
return "";
} else {
Element examinerElement = (Element) getCaseElement().getElementsByTagName(EXAMINER).item(0);
String result = "";
if (examinerElement != null) {
result = examinerElement.getTextContent();
}
return result;
}
}
/**
* Gets the case directory path that's stored in this class
*
* @return caseDirPath the case directory path
*/
public String getCaseDirectory() {
if (doc == null) {
return "";
} else {
return caseDirPath;
}
// Note: change this to get the case name from the xml file if needed
}
/**
* Gets the Root Element from the document handler
*
* @return rootElement the root element on the document handler
*/
private Element getRootElement() {
if (doc != null) {
return doc.getDocumentElement();
} else {
return null; // should throw error or exception
}
}
/**
* Gets the created Date from the document handler
*
* @return createdDate the creation date of this case
*/
public String getCreatedDate() {
if (doc != null) {
Element crDateElement = (Element) getRootElement().getElementsByTagName(CREATED_DATE_NAME).item(0);
return crDateElement.getTextContent();
} else {
return ""; // should throw error or exception
}
}
/**
* Gets the Modified Date from the document handler
*
* @return modifiedDate the modification date of this case
*/
protected String getModifiedDate() {
if (doc != null) {
Element mDateElement = (Element) getRootElement().getElementsByTagName(MODIFIED_DATE_NAME).item(0);
return mDateElement.getTextContent();
} else {
return ""; // should throw error or exception
}
}
/**
* Gets the Autopsy Created Version from the document handler
*
* @return createdVersion the version of autopsy when this case was created
*/
protected String getCreatedVersion() {
if (doc != null) {
Element crVerElement = (Element) getRootElement().getElementsByTagName(AUTOPSY_CRVERSION_NAME).item(0);
return crVerElement.getTextContent();
} else {
return ""; // should throw error or exception
}
}
/**
* Gets the Autopsy Saved Version from the document handler
*
* @return savedVersion the latest version of autopsy when this case is
* saved
*/
protected String getSavedVersion() {
if (doc != null) {
Element mVerElement = (Element) getRootElement().getElementsByTagName(AUTOPSY_MVERSION_NAME).item(0);
return mVerElement.getTextContent();
} else {
return ""; // should throw error or exception
}
}
/**
* Gets the Schema Version from the document handler
*
* @return schemaVersion the schema version of this XML configuration file
*/
protected String getSchemaVersion() {
if (doc != null) {
Element schemaVerElement = (Element) getRootElement().getElementsByTagName(SCHEMA_VERSION_NAME).item(0);
return schemaVerElement.getTextContent();
} else {
return ""; // should throw error or exception
}
}
/**
* Gets the Case Element from the document handler
*
* @return caseElement the "Case" element
*/
private Element getCaseElement() {
if (doc != null) {
return (Element) doc.getElementsByTagName(CASE_ROOT_NAME).item(0);
} else {
return null; // should throw error or exception
}
}
/**
* Gets the full path to the log directory
*
* @return logDir the full path of the "Log" directory
*/
protected String getLogDir() {
if (doc != null) {
Element logElement = (Element) getCaseElement().getElementsByTagName(LOG_FOLDER_NAME).item(0);
if (logElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)) {
return caseDirPath + File.separator + logElement.getTextContent();
} else {
return logElement.getTextContent();
}
} else {
return ""; // should throw error or exception
}
}
/**
* Gets the full path to the temp directory
*
* @return tempDir the full path of the "Temp" directory
*/
protected String getTempDir() {
if (doc != null) {
Element tempElement = (Element) getCaseElement().getElementsByTagName(TEMP_FOLDER_NAME).item(0);
if (tempElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)) {
return caseDirPath + File.separator + tempElement.getTextContent();
} else {
return tempElement.getTextContent();
}
} else {
return ""; // should throw error or exception
}
}
/**
* Gets the full path to the Export directory
*
* @return exportDir the full path of the "Export" directory
*/
protected String getExportDir() {
if (doc != null) {
Element exportElement = (Element) getCaseElement().getElementsByTagName(EXPORT_FOLDER_NAME).item(0);
if (exportElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)) {
return caseDirPath + File.separator + exportElement.getTextContent();
} else {
return exportElement.getTextContent();
}
} else {
return ""; // should throw error or exception
}
}
/**
* Gets the full path to the Cache directory
*
* @return cacheDir the full path of the "Cache" directory
*/
protected String getCacheDir() {
if (doc != null) {
Element cacheElement = (Element) getCaseElement().getElementsByTagName(CACHE_FOLDER_NAME).item(0);
if (cacheElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)) {
return caseDirPath + File.separator + cacheElement.getTextContent();
} else {
return cacheElement.getTextContent();
}
} else {
return ""; // should throw error or exception
}
}
/**
* Initialize the basic values for a new case management file. Note: this is
* the schema version 1.0
*
* @param dirPath case directory path
* @param caseName the name of the config file to be located in the
* case directory
* @param examiner examiner for the case (optional, can be empty string
* @param caseNumber case number (optional), can be empty
* @param dbName the name of the database. Could be a local path,
* could be a Postgre db name.
* @param textIndexName The name of the index where extracted text is
* stored.
*/
public void create(String dirPath, String caseName, String examiner, String caseNumber, CaseType caseType, String dbName, String textIndexName) throws CaseActionException {
clear(); // clear the previous data
// set the case Name and Directory and the parent directory
setCaseDirPath(dirPath);
setName(caseName);
setExaminer(examiner);
setNumber(caseNumber);
setCaseType(caseType);
setDatabaseName(dbName);
setTextIndexName(textIndexName);
DocumentBuilder docBuilder;
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
// throw an error here
try {
docBuilder = docFactory.newDocumentBuilder();
} catch (ParserConfigurationException ex) {
clear();
throw new CaseActionException(
NbBundle.getMessage(this.getClass(), "XMLCaseManagement.create.exception.msg"), ex);
}
doc = docBuilder.newDocument();
Element rootElement = doc.createElement(TOP_ROOT_NAME); // <AutopsyCase> ... </AutopsyCase>
doc.appendChild(rootElement);
Element crDateElement = doc.createElement(CREATED_DATE_NAME); // <CreatedDate> ... </CreatedDate>
crDateElement.appendChild(doc.createTextNode(dateFormat.format(new Date())));
rootElement.appendChild(crDateElement);
Element mDateElement = doc.createElement(MODIFIED_DATE_NAME); // <ModifedDate> ... </ModifedDate>
mDateElement.appendChild(doc.createTextNode(dateFormat.format(new Date())));
rootElement.appendChild(mDateElement);
Element autVerElement = doc.createElement(AUTOPSY_CRVERSION_NAME); // <AutopsyVersion> ... </AutopsyVersion>
autVerElement.appendChild(doc.createTextNode(autopsySavedVersion));
rootElement.appendChild(autVerElement);
Element autSavedVerElement = doc.createElement(AUTOPSY_MVERSION_NAME); // <AutopsySavedVersion> ... </AutopsySavedVersion>
autSavedVerElement.appendChild(doc.createTextNode(autopsySavedVersion));
rootElement.appendChild(autSavedVerElement);
Element schVerElement = doc.createElement(SCHEMA_VERSION_NAME); // <SchemaVersion> ... </SchemaVersion>
schVerElement.appendChild(doc.createTextNode(schemaVersion));
rootElement.appendChild(schVerElement);
Element caseElement = doc.createElement(CASE_ROOT_NAME); // <Case> ... </Case>
rootElement.appendChild(caseElement);
Element nameElement = doc.createElement(NAME); // <Name> ... </Name>
nameElement.appendChild(doc.createTextNode(caseName));
caseElement.appendChild(nameElement);
Element numberElement = doc.createElement(NUMBER); // <Number> ... </Number>
numberElement.appendChild(doc.createTextNode(String.valueOf(caseNumber)));
caseElement.appendChild(numberElement);
Element examinerElement = doc.createElement(EXAMINER); // <Examiner> ... </Examiner>
examinerElement.appendChild(doc.createTextNode(examiner));
caseElement.appendChild(examinerElement);
Element exportElement = doc.createElement(EXPORT_FOLDER_NAME); // <ExportFolder> ... </ExportFolder>
exportElement.appendChild(doc.createTextNode(EXPORT_FOLDER_RELPATH));
exportElement.setAttribute(RELATIVE_NAME, "true"); //NON-NLS
caseElement.appendChild(exportElement);
Element logElement = doc.createElement(LOG_FOLDER_NAME); // <LogFolder> ... </LogFolder>
logElement.appendChild(doc.createTextNode(LOG_FOLDER_RELPATH));
logElement.setAttribute(RELATIVE_NAME, "true"); //NON-NLS
caseElement.appendChild(logElement);
Element tempElement = doc.createElement(TEMP_FOLDER_NAME); // <TempFolder> ... </TempFolder>
tempElement.appendChild(doc.createTextNode(TEMP_FOLDER_RELPATH));
tempElement.setAttribute(RELATIVE_NAME, "true"); //NON-NLS
caseElement.appendChild(tempElement);
Element cacheElement = doc.createElement(CACHE_FOLDER_NAME); // <CacheFolder> ... </CacheFolder>
cacheElement.appendChild(doc.createTextNode(CACHE_FOLDER_RELPATH));
cacheElement.setAttribute(RELATIVE_NAME, "true"); //NON-NLS
caseElement.appendChild(cacheElement);
Element typeElement = doc.createElement(CASE_TYPE); // <CaseType> ... </CaseType>
typeElement.appendChild(doc.createTextNode(caseType.toString()));
caseElement.appendChild(typeElement);
Element dbNameElement = doc.createElement(DATABASE_NAME); // <DatabaseName> ... </DatabaseName>
dbNameElement.appendChild(doc.createTextNode(dbName));
caseElement.appendChild(dbNameElement);
Element indexNameElement = doc.createElement(CASE_TEXT_INDEX_NAME); // <TextIndexName> ... </TextIndexName>
indexNameElement.appendChild(doc.createTextNode(textIndexName));
caseElement.appendChild(indexNameElement);
// write more code if needed ...
}
/**
* Writes the case management file to disk (from document handler to .aut
* file)
*
*/
@Override
public void writeFile() throws CaseActionException {
if (doc == null || caseName.equals("")) {
throw new CaseActionException(
NbBundle.getMessage(this.getClass(), "XMLCaseManagement.writeFile.exception.noCase.msg"));
}
// Prepare the DOM document for writing
Source source = new DOMSource(doc);
// Prepare the data for the output file
StringWriter sw = new StringWriter();
Result result = new StreamResult(sw);
// Write the DOM document to the file
Transformer xformer;// = TransformerFactory.newInstance().newTransformer();
TransformerFactory tfactory = TransformerFactory.newInstance();
try {
xformer = tfactory.newTransformer();
} catch (TransformerConfigurationException ex) {
logger.log(Level.SEVERE, "Could not setup tranformer and write case file"); //NON-NLS
throw new CaseActionException(
NbBundle.getMessage(this.getClass(), "XMLCaseManagement.writeFile.exception.errWriteToFile.msg"), ex);
}
//Setup indenting to "pretty print"
xformer.setOutputProperty(OutputKeys.INDENT, "yes"); //NON-NLS
xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); //NON-NLS
try {
xformer.transform(source, result);
} catch (TransformerException ex) {
logger.log(Level.SEVERE, "Could not run tranformer and write case file"); //NON-NLS
throw new CaseActionException(
NbBundle.getMessage(this.getClass(), "XMLCaseManagement.writeFile.exception.errWriteToFile.msg"), ex);
}
// preparing the output file
String xmlString = sw.toString();
File file = new File(caseDirPath + File.separator + caseName + ".aut");
// write the file
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
bw.write(xmlString);
bw.flush();
bw.close();
} catch (IOException ex) {
logger.log(Level.SEVERE, "Error writing to case file"); //NON-NLS
throw new CaseActionException(
NbBundle.getMessage(this.getClass(), "XMLCaseManagement.writeFile.exception.errWriteToFile.msg"), ex);
}
}
/**
* Opens the configuration file and load the document handler Note: this is
* for the schema version 1.0
*
* @param conFilePath the path of the XML case configuration file path
*/
@Override
public void open(String conFilePath) throws CaseActionException {
clear();
File file = new File(conFilePath);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db;
try {
db = dbf.newDocumentBuilder();
doc = db.parse(file);
} catch (ParserConfigurationException | SAXException | IOException ex) {
throw new CaseActionException(
NbBundle.getMessage(this.getClass(), "XMLCaseManagement.open.exception.errReadXMLFile.msg",
conFilePath), ex);
}
doc.getDocumentElement().normalize();
doc.getDocumentElement().normalize();
// TODO: Restore later
// if (!XMLUtil.xmlIsValid(doc, XMLCaseManagement.class, XSDFILE)) {
// logger.log(Level.WARNING, "Could not validate against [" + XSDFILE + "], results may not accurate"); //NON-NLS
// }
Element rootEl = doc.getDocumentElement();
String rootName = rootEl.getNodeName();
// check if it's the autopsy case, if not, throws an error
if (!rootName.equals(TOP_ROOT_NAME)) {
// throw an error ...
clear();
if (RuntimeProperties.coreComponentsAreActive()) {
JOptionPane.showMessageDialog(caller,
NbBundle.getMessage(this.getClass(),
"XMLCaseManagement.open.msgDlg.notAutCase.msg",
file.getName(), className),
NbBundle.getMessage(this.getClass(),
"XMLCaseManagement.open.msgDlg.notAutCase.title"),
JOptionPane.ERROR_MESSAGE);
}
} else {
/*
* Autopsy Created Version
*/
String createdVersion = getCreatedVersion(); // get the created version
// check if it has the same autopsy version as the current one
if (!createdVersion.equals(autopsySavedVersion)) {
// if not the same version, update the saved version in the xml to the current version
getRootElement().getElementsByTagName(AUTOPSY_MVERSION_NAME).item(0).setTextContent(autopsySavedVersion);
}
/*
* Schema Version
*/
String schemaVer = getSchemaVersion();
// check if it has the same schema version as the current one
if (!schemaVer.equals(schemaVersion)) {
// do something here if not the same version
// ... @Override
}
// set the case Directory and Name
setCaseDirPath(file.getParent());
String fullFileName = file.getName();
String fileName = fullFileName.substring(0, fullFileName.lastIndexOf(".")); // remove the extension
setName(fileName);
}
}
/**
* When user wants to close the case. This method writes any changes to the
* XML case configuration file, closes it and the document handler, and
* clears all the local variables / fields.
*
*/
@Override
public void close() throws CaseActionException {
writeFile(); // write any changes to xml
clear();
}
/**
* Clear the internal structures / variables
*/
private void clear() {
doc = null;
caseDirPath = "";
caseName = "";
caseNumber = "";
examiner = "";
caseType = CaseType.SINGLE_USER_CASE;
dbName = "";
textIndexName = "";
}
}
@@ -1,7 +1,7 @@
/*
* Sleuth Kit Data Model
*
* Copyright 2011-2015 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.casemodule.services;
import java.io.Closeable;
import java.io.IOException;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.datamodel.BlackboardArtifact;
@@ -30,87 +29,102 @@ import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskDataException;
/**
* Provides utility methods for blackboard artifact indexing.
* Represents the blackboard, a place where artifacts and their attributes are
* posted.
*
* NOTE: This API of this class is under development.
*/
public final class Blackboard implements Closeable {
/**
* Index the text associated with the given artifact.
* Indexes the text associated with the an artifact.
*
* @param artifact The artifact to be indexed.
*
* @throws
* org.sleuthkit.autopsy.casemodule.services.Blackboard.BlackboardException
* @throws BlackboardException If there is a problem indexing the artifact.
*/
public void indexArtifact(BlackboardArtifact artifact) throws BlackboardException {
KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
if (null == searchService) {
throw new BlackboardException(NbBundle.getMessage(this.getClass(), "Blackboard.keywordSearchNotFound.exception.msg"));
throw new BlackboardException("Keyword search service not found");
}
try {
searchService.indexArtifact(artifact);
} catch (TskCoreException ex) {
throw new BlackboardException(NbBundle.getMessage(this.getClass(), "Blackboard.unableToIndexArtifact.exception.msg"), ex);
throw new BlackboardException("Error indexing artifact", ex);
}
}
/**
* Adds a new artifact type based upon the parameters given
* Gets an artifact type, creating it if it does not already exist. Use this
* method to define custom artifact types.
*
* @param typeName The name of the new artifact type
* @param displayName The name displayed for the new attribute type
* @return A type object representing the artifact type added
* @throws
* org.sleuthkit.autopsy.casemodule.services.Blackboard.BlackboardException
* @param typeName The type name of the artifact type.
* @param displayName The display name of the artifact type.
*
* @return A type object representing the artifact type.
*
* @throws BlackboardBlackboardException If there is a problem getting or
* adding the artifact type.
*/
public BlackboardArtifact.Type addArtifactType(String typeName, String displayName) throws BlackboardException {
public BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName) throws BlackboardException {
try {
return Case.getCurrentCase().getSleuthkitCase().addBlackboardArtifactType(typeName, displayName);
} catch (TskCoreException | TskDataException ex) {
throw new BlackboardException("New artifact type could not be added", ex);
} catch (TskDataException typeExistsEx) {
try {
return Case.getCurrentCase().getSleuthkitCase().getArtifactType(typeName);
} catch (TskCoreException ex) {
throw new BlackboardException("Failed to get or add artifact type", ex);
}
} catch (TskCoreException ex) {
throw new BlackboardException("Failed to get or add artifact type", ex);
}
}
/**
* Adds a new attribute type based upon the parameters given
* Gets an attribute type, creating it if it does not already exist. Use
* this method to define custom attribute types.
*
* @param attrTypeString The type name of the attribute type
* @param valueType The type of any attribute of this type's value
* @param displayName The name displayed for the new attribute type
* @throws
* org.sleuthkit.autopsy.casemodule.services.Blackboard.BlackboardException
* @param typeName The type name of the attribute type.
* @param valueType The value type of the attribute type.
* @param displayName The display name of the attribute type.
*
* @return A type object representing the attribute type.
*
* @throws BlackboardBlackboardException If there is a problem getting or
* adding the attribute type.
*/
public BlackboardAttribute.Type addAttributeType(String attrTypeString, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName) throws BlackboardException {
public BlackboardAttribute.Type getOrAddAttributeType(String typeName, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName) throws BlackboardException {
try {
return Case.getCurrentCase().getSleuthkitCase().addArtifactAttributeType(attrTypeString, valueType, displayName);
} catch (TskDataException ex) {
throw new BlackboardException("New attribute type could not be added", ex);
return Case.getCurrentCase().getSleuthkitCase().addArtifactAttributeType(typeName, valueType, displayName);
} catch (TskDataException typeExistsEx) {
try {
return Case.getCurrentCase().getSleuthkitCase().getAttributeType(typeName);
} catch (TskCoreException ex) {
throw new BlackboardException("Failed to get or add attribute type", ex);
}
} catch (TskCoreException ex) {
throw new BlackboardException("New attribute type could not be added", ex);
throw new BlackboardException("Failed to get or add attribute type", ex);
}
}
/**
* Cloese this blackboard and releases any resources associated with it.
* @throws IOException
*/
@Override
public void close() throws IOException {
}
/**
* Provides a system exception for the Keyword Search package.
* A blackboard exception.
*/
public static final class BlackboardException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs a new exception with null as its message.
*/
public BlackboardException() {
super();
}
/**
* Constructs a new exception with the specified message.
* Constructs a blackboard exception with the specified message.
*
* @param message The message.
*/
@@ -119,10 +133,11 @@ public final class Blackboard implements Closeable {
}
/**
* Constructs a new exception with the specified message and cause.
* Constructs a blackboard exception with the specified message and
* cause.
*
* @param message The message.
* @param cause The cause.
* @param cause The cause.
*/
public BlackboardException(String message, Throwable cause) {
super(message, cause);
@@ -19,6 +19,4 @@ TagsManager.addContentTag.noCaseWarning=Failed to publish new content tag event.
TagsManager.deleteContentTag.noCaseWarning=Failed to publish content tag deleted event. There is no case open.
TagsManager.addBlackboardArtifactTag.noCaseWarning=Failed to publish new blackboard artifact tag event. There is no case open.
TagsManager.deleteBlackboardArtifactTag.noCaseWarning=Failed to publish blackboard artifact tag deleted event. There is no case open.
Blackboard.keywordSearchNotFound.exception.msg=Keyword search service not found.
Blackboard.unableToIndexArtifact.exception.msg=Unable to index blackboard artifact
Blackboard.unableToIndexArtifact.error.msg=Unable to index blackboard artifact {0}
@@ -1,24 +1,22 @@
FileManager.findFiles.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.findFiles2.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.findFiles3.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.openFiles.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.addDerivedFile.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.addCarvedFile.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.addLocalFilesDirs.exception.notReadable.msg=\u8FFD\u52A0\u3059\u308B\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u4E2D\u306B\u8AAD\u307F\u53D6\u308C\u306A\u3044\u3082\u306E\u304C\uFF11\u500B\u3042\u308A\u307E\u3059\uFF1A{0}\u3001\u30D5\u30A1\u30A4\u30EB\u304C\u8FFD\u52A0\u3055\u308C\u308B\u524D\u306B\u51E6\u7406\u3092\u4E2D\u6B62\u3057\u307E\u3059
FileManager.addLocalFilesDirs.exception.cantAdd.msg=\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\uFF11\u500B\u306F\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF1A{0}
FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg=\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u30BB\u30C3\u30C8\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u4F5C\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u8D77\u3053\u308A\u307E\u3057\u305F\uFF1A {0}
FileManager.addLocalDirInt.exception.closed.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.addLocalDirInt.exception.doesntExist.msg=\u5B58\u5728\u3057\u306A\u3044\u30ED\u30FC\u30AB\u30EB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u8FFD\u52A0\u3092\u8A66\u307F\u307E\u3057\u305F\: {0}
FileManager.addLocalDirInt.exception.notReadable.msg=\u8AAD\u307F\u53D6\u308A\u3067\u304D\u306A\u3044\u30ED\u30FC\u30AB\u30EB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u8FFD\u52A0\u3092\u8A66\u307F\u307E\u3057\u305F\: {0}
FileManager.addLocalDirInt2.exception.closed.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} \u30B3\u30F3\u30C6\u30F3\u30C4\u30B5\u30A4\u30BA\u7BC4\u56F2(0 - {1})\u306E\u5916\u3067\u3059
TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} \u30B3\u30F3\u30C6\u30F3\u30C4\u30B5\u30A4\u30BA\u7BC4\u56F2(0 - {1})\u306E\u5916\u3067\u3059
FileManager.findFiles.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
FileManager.findFiles2.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
FileManager.findFiles3.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
FileManager.openFiles.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
FileManager.addDerivedFile.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
FileManager.addCarvedFile.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
FileManager.addLocalFilesDirs.exception.notReadable.msg=\u8ffd\u52a0\u3059\u308b\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u4e2d\u306b\u8aad\u307f\u53d6\u308c\u306a\u3044\u3082\u306e\u304c\uff11\u500b\u3042\u308a\u307e\u3059\uff1a{0}\u3001\u30d5\u30a1\u30a4\u30eb\u304c\u8ffd\u52a0\u3055\u308c\u308b\u524d\u306b\u51e6\u7406\u3092\u4e2d\u6b62\u3057\u307e\u3059
FileManager.addLocalFilesDirs.exception.cantAdd.msg=\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\uff11\u500b\u306f\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\uff1a{0}
FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg=\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u8d77\u3053\u308a\u307e\u3057\u305f\uff1a {0}
FileManager.addLocalDirInt.exception.closed.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
FileManager.addLocalDirInt.exception.doesntExist.msg=\u5b58\u5728\u3057\u306a\u3044\u30ed\u30fc\u30ab\u30eb\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u8ffd\u52a0\u3092\u8a66\u307f\u307e\u3057\u305f\: {0}
FileManager.addLocalDirInt.exception.notReadable.msg=\u8aad\u307f\u53d6\u308a\u3067\u304d\u306a\u3044\u30ed\u30fc\u30ab\u30eb\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u8ffd\u52a0\u3092\u8a66\u307f\u307e\u3057\u305f\: {0}
FileManager.addLocalDirInt2.exception.closed.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} \u30b3\u30f3\u30c6\u30f3\u30c4\u30b5\u30a4\u30ba\u7bc4\u56f2(0 - {1})\u306e\u5916\u3067\u3059
TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} \u30b3\u30f3\u30c6\u30f3\u30c4\u30b5\u30a4\u30ba\u7bc4\u56f2(0 - {1})\u306e\u5916\u3067\u3059
TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset
TagsManager.predefTagNames.bookmark.text=\u30D6\u30C3\u30AF\u30DE\u30FC\u30AF
TagsManager.addContentTag.noCaseWarning=\u65B0\u3057\u3044\u30BF\u30B0\u30A4\u30D9\u30F3\u30C8\u3092\u30D1\u30D6\u30EA\u30C3\u30B7\u30E5\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u958B\u3044\u3066\u3044\u308B\u30B1\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093\u3002
TagsManager.deleteContentTag.noCaseWarning=\u524A\u9664\u3055\u308C\u305F\u30A4\u30D9\u30F3\u30C8\u306E\u30BF\u30B0\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u3092\u30D1\u30D6\u30EA\u30C3\u30B7\u30E5\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u958B\u3044\u3066\u3044\u308B\u30B1\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093\u3002
TagsManager.addBlackboardArtifactTag.noCaseWarning=\u30A4\u30D9\u30F3\u30C8\u306E\u30BF\u30B0\u306E\u65B0\u3057\u3044blackboard\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u3092\u30D1\u30D6\u30EA\u30C3\u30B7\u30E5\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u958B\u3044\u3066\u3044\u308B\u30B1\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093\u3002
TagsManager.deleteBlackboardArtifactTag.noCaseWarning=\u524A\u9664\u3055\u308C\u305F\u30A4\u30D9\u30F3\u30C8\u306E\u30BF\u30B0\u306E\u65B0\u3057\u3044blackboard\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u3092\u30D1\u30D6\u30EA\u30C3\u30B7\u30E5\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u958B\u3044\u3066\u3044\u308B\u30B1\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093\u3002
Blackboard.keywordSearchNotFound.exception.msg=\u30AD\u30FC\u30EF\u30FC\u30C9\u691C\u7D22\u30B5\u30FC\u30D3\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002
Blackboard.unableToIndexArtifact.exception.msg=blackboard\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002
Blackboard.unableToIndexArtifact.error.msg=blackboard\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8{0}\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002
TagsManager.predefTagNames.bookmark.text=\u30d6\u30c3\u30af\u30de\u30fc\u30af
TagsManager.addContentTag.noCaseWarning=\u65b0\u3057\u3044\u30bf\u30b0\u30a4\u30d9\u30f3\u30c8\u3092\u30d1\u30d6\u30ea\u30c3\u30b7\u30e5\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002
TagsManager.deleteContentTag.noCaseWarning=\u524a\u9664\u3055\u308c\u305f\u30a4\u30d9\u30f3\u30c8\u306e\u30bf\u30b0\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u30d1\u30d6\u30ea\u30c3\u30b7\u30e5\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002
TagsManager.addBlackboardArtifactTag.noCaseWarning=\u30a4\u30d9\u30f3\u30c8\u306e\u30bf\u30b0\u306e\u65b0\u3057\u3044blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30d1\u30d6\u30ea\u30c3\u30b7\u30e5\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002
TagsManager.deleteBlackboardArtifactTag.noCaseWarning=\u524a\u9664\u3055\u308c\u305f\u30a4\u30d9\u30f3\u30c8\u306e\u30bf\u30b0\u306e\u65b0\u3057\u3044blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30d1\u30d6\u30ea\u30c3\u30b7\u30e5\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002
Blackboard.unableToIndexArtifact.error.msg=blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8{0}\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
@@ -3,9 +3,13 @@
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="iconImage" type="java.awt.Image" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="default"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
@@ -27,7 +27,7 @@ Format_OperatingSystem_Value={0} version {1} running on {2}
LBL_Copyright=<div style\="font-size\: 12pt; font-family\: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style\="color\: \#1E2A60;" href\="http\://www.sleuthkit.org">http\://www.sleuthkit.org</a>.</li><li>Training: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/autopsy-training">http://www.basistech.com/autopsy-training</a></li><li>Commercial Support: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/digital-forensics/autopsy/support/">http://www.basistech.com/digital-forensics/autopsy/support/</a></li></ul>Copyright &copy; 2003-2016. </div>
URL_ON_IMG=http://www.sleuthkit.org/
URL_ON_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.0/
URL_ON_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.1/
FILE_FOR_LOCAL_HELP=file:///
INDEX_FOR_LOCAL_HELP=/docs/index.html
@@ -35,6 +35,7 @@ import org.openide.util.Lookup;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.casemodule.OpenFromArguments;
import org.sleuthkit.autopsy.coreutils.Logger;
@@ -78,7 +79,7 @@ public class Installer extends ModuleInstall {
if (processor instanceof OpenFromArguments) {
OpenFromArguments argsProcessor = (OpenFromArguments) processor;
final String caseFile = argsProcessor.getDefaultArg();
if (caseFile != null && !caseFile.equals("") && caseFile.endsWith(".aut") && new File(caseFile).exists()) { //NON-NLS
if (caseFile != null && !caseFile.equals("") && caseFile.endsWith(CaseMetadata.getFileExtension()) && new File(caseFile).exists()) { //NON-NLS
new Thread(() -> {
try {
Case.open(caseFile);
@@ -26,10 +26,12 @@ import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import org.apache.commons.lang3.StringUtils;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content;
@@ -58,14 +60,12 @@ class ThumbnailViewNode extends FilterNode {
@Override
public String getDisplayName() {
if (super.getDisplayName().length() > 15) {
return super.getDisplayName().substring(0, 15).concat("...");
} else {
return super.getDisplayName();
}
return StringUtils.abbreviate(super.getDisplayName(), 18);
}
@Override
@NbBundle.Messages({"# {0} - file name",
"ThumbnailViewNode.progressHandle.text=Generating thumbnail for {0}"})
public Image getIcon(int type) {
Image icon = null;
@@ -82,7 +82,7 @@ class ThumbnailViewNode extends FilterNode {
}
if (swingWorker == null || swingWorker.isDone()) {
swingWorker = new SwingWorker<Image, Object>() {
final private ProgressHandle progressHandle = ProgressHandleFactory.createHandle("generating thumbnail for video file " + content.getName());
final private ProgressHandle progressHandle = ProgressHandleFactory.createHandle(Bundle.ThumbnailViewNode_progressHandle_text(content.getName()));
@Override
protected Image doInBackground() throws Exception {
@@ -97,7 +97,7 @@ class ThumbnailViewNode extends FilterNode {
iconCache = new SoftReference<>(super.get());
fireIconChange();
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(ThumbnailViewNode.class.getName()).log(Level.SEVERE, "Error getting thumbnail icon", ex); //NON-NLS
Logger.getLogger(ThumbnailViewNode.class.getName()).log(Level.SEVERE, "Error getting thumbnail icon for " + content.getName(), ex); //NON-NLS
} finally {
progressHandle.finish();
if (timer != null) {
@@ -90,26 +90,21 @@ public final class Logger extends java.util.logging.Logger {
fileHandler.setFormatter(new Formatter() {
@Override
public String format(LogRecord record) {
if (record.getThrown() != null) {
String stackTrace = ""; //NON-NLS
Throwable thrown = record.getThrown();
String stackTrace = ""; //NON-NLS
while (thrown != null) {
stackTrace += thrown.toString() + "\n";
for (StackTraceElement traceElem : record.getThrown().getStackTrace()) {
stackTrace += "\t" + traceElem.toString() + "\n"; //NON-NLS
}
return (new Timestamp(record.getMillis())).toString() + " " //NON-NLS
+ record.getSourceClassName() + " " //NON-NLS
+ record.getSourceMethodName() + "\n" //NON-NLS
+ record.getLevel() + ": " //NON-NLS
+ this.formatMessage(record) + "\n" //NON-NLS
+ record.getThrown().toString() + ":\n" //NON-NLS
+ stackTrace
+ "\n"; //NON-NLS
} else {
return (new Timestamp(record.getMillis())).toString() + " " //NON-NLS
+ record.getSourceClassName() + " " //NON-NLS
+ record.getSourceMethodName() + "\n" //NON-NLS
+ record.getLevel() + ": " //NON-NLS
+ this.formatMessage(record) + "\n"; //NON-NLS
thrown = thrown.getCause();
}
return (new Timestamp(record.getMillis())).toString() + " " //NON-NLS
+ record.getSourceClassName() + " " //NON-NLS
+ record.getSourceMethodName() + "\n" //NON-NLS
+ record.getLevel() + ": " //NON-NLS
+ this.formatMessage(record) + "\n" //NON-NLS
+ stackTrace;
}
});
return fileHandler;
@@ -23,7 +23,7 @@ IngestJob.progress.fileIngest.displayName=Analyzing files from {0}
IngestJob.progress.fileIngest.cancelMessage=Waiting for {0} on {1}
IngestJob.progress.cancelling={0} (Cancelling...)
IngestJob.cancellationDialog.title=Cancel Ingest
IngestDialog.title.text=Ingest Modules
IngestDialog.title.text=Run Ingest Modules
IngestDialog.startButton.title=Start
IngestDialog.closeButton.title=Close
IngestManager.moduleErr=Module Error
@@ -85,9 +85,6 @@ DataSourceIngestCancellationPanel.cancelCurrentModuleRadioButton.text=Cancel cur
FileIngestCancellationPanel.cancelIngestJobRadioButton.text=Cancel data source ingest and file ingest
FileIngestCancellationPanel.cancelFileIngestRadioButton.text=Cancel file ingest only
DataSourceIngestCancellationPanel.cancelAllModulesRadioButton.text=Cancel all ingest modules
IngestJobSettingsPanel.advancedButton.actionCommand=Advanced
IngestJobSettingsPanel.advancedButton.text=Advanced
IngestJobSettingsPanel.descriptionLabel.text=
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.jobID=Job ID
IngestJobTableModel.colName.jobID=Job ID
IngestJobTableModel.colName.dataSource=Data Source
@@ -117,3 +114,8 @@ IngestJob.cancelReason.ingestModStartFail.text=Ingest modules startup failed
IngestJob.cancelReason.outOfDiskSpace.text=Out of disk space
IngestJob.cancelReason.servicesDown.text=Services Down
IngestJob.cancelReason.caseClosed.text=Case closed
IngestJobSettingsPanel.globalSettingsButton.text=Global Settings
gest
IngestJobSettingsPanel.globalSettingsButton.actionCommand=Advanced
IngestJobSettingsPanel.globalSettingsButton.text=Global Settings
IngestJobSettingsPanel.descriptionLabel.text=dummmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy texxxxxxxxxxxxxxxttttttttttttttttttttttttttttttttttttttttttt
@@ -68,8 +68,6 @@ IngestProgressSnapshotDialog.title.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30
IngestProgressSnapshotPanel.closeButton.text=\u9589\u3058\u308b
IngestProgressSnapshotPanel.refreshButton.text=\u30ea\u30d5\u30ec\u30c3\u30b7\u30e5
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3
IngestJobSettingsPanel.advancedButton.actionCommand=\u30a2\u30c9\u30d0\u30f3\u30b9
IngestJobSettingsPanel.advancedButton.text=\u30a2\u30c9\u30d0\u30f3\u30b9
ModuleTableModel.colName.duration=\u6240\u8981\u6642\u9593
IngestJob.cancellationDialog.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u30ad\u30e3\u30f3\u30bb\u30eb
IngestJobSettings.missingModule.warning=\u4ee5\u524d\u306b\u8aad\u307f\u8fbc\u3093\u3060{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002
@@ -113,3 +111,5 @@ IngestJob.cancelReason.cancelledByUser.text=\u30e6\u30fc\u30b6\u30fc\u304c\u30ad
IngestJob.cancelReason.ingestModStartFail.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u8d77\u52d5\u306b\u5931\u6557
IngestJob.cancelReason.outOfDiskSpace.text=\u30c7\u30a3\u30b9\u30af\u30b9\u30da\u30fc\u30b9\u304c\u8db3\u308a\u307e\u305b\u3093
IngestJob.cancelReason.caseClosed.text=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u307e\u3057\u305f
IngestJobSettingsPanel.globalSettingsButton.actionCommand=\u30a2\u30c9\u30d0\u30f3\u30b9
IngestJobSettingsPanel.globalSettingsButton.text=\u30a2\u30c9\u30d0\u30f3\u30b9
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -288,7 +288,7 @@ final class DataSourceIngestJob {
String getExecutionContext() {
return this.settings.getExecutionContext();
}
/**
* Gets the data source to be ingested by this job.
*
@@ -379,38 +379,45 @@ final class DataSourceIngestJob {
private List<IngestModuleError> startUpIngestPipelines() {
List<IngestModuleError> errors = new ArrayList<>();
// Start up the first stage data source ingest pipeline.
/*
* Start the data-source-level ingest module pipelines.
*/
errors.addAll(this.firstStageDataSourceIngestPipeline.startUp());
// Start up the second stage data source ingest pipeline.
errors.addAll(this.secondStageDataSourceIngestPipeline.startUp());
// Start up the file ingest pipelines (one per file ingest thread).
for (FileIngestPipeline pipeline : this.fileIngestPipelinesQueue) {
errors.addAll(pipeline.startUp());
if (!errors.isEmpty()) {
// If there are start up errors, the ingest job will not proceed
// and the errors will ultimately be reported to the user for
// possible remedy so shut down the pipelines now that an
// attempt has been made to start up the data source ingest
// pipeline and at least one copy of the file ingest pipeline.
// pipeline. There is no need to complete starting up all of the
// file ingest pipeline copies since any additional start up
// errors are likely redundant.
while (!this.fileIngestPipelinesQueue.isEmpty()) {
pipeline = this.fileIngestPipelinesQueue.poll();
if (pipeline.isRunning()) {
List<IngestModuleError> shutDownErrors = pipeline.shutDown();
if (!shutDownErrors.isEmpty()) {
logIngestModuleErrors(shutDownErrors);
/*
* If the data-source-level ingest pipelines were successfully started,
* start the Start the file-level ingest pipelines (one per file ingest
* thread).
*/
if (errors.isEmpty()) {
for (FileIngestPipeline pipeline : this.fileIngestPipelinesQueue) {
errors.addAll(pipeline.startUp());
if (!errors.isEmpty()) {
/*
* If there are start up errors, the ingest job will not
* proceed, so shut down any file ingest pipelines that did
* start up.
*/
while (!this.fileIngestPipelinesQueue.isEmpty()) {
FileIngestPipeline startedPipeline = this.fileIngestPipelinesQueue.poll();
if (startedPipeline.isRunning()) {
List<IngestModuleError> shutDownErrors = startedPipeline.shutDown();
if (!shutDownErrors.isEmpty()) {
/*
* The start up errors will ultimately be
* reported to the user for possible remedy, but
* the shut down errors are logged here.
*/
logIngestModuleErrors(shutDownErrors);
}
}
}
break;
}
break;
}
}
logIngestModuleErrors(errors);
return errors;
}
@@ -10,10 +10,10 @@
<Dimension value="[5750, 3000]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[522, 257]"/>
<Dimension value="[0, 0]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[575, 300]"/>
<Dimension value="[625, 450]"/>
</Property>
</Properties>
<AuxValues>
@@ -31,11 +31,11 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="modulesScrollPane" max="32767" attributes="1"/>
<Group type="102" attributes="0">
<Component id="modulesScrollPane" pref="271" max="32767" attributes="1"/>
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
@@ -48,33 +48,33 @@
<Component id="jButtonDeselectAll" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace pref="30" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="32" max="-2" attributes="0"/>
</Group>
</Group>
<Component id="jPanel1" pref="310" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jPanel1" pref="324" 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" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jPanel1" pref="278" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="modulesScrollPane" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jButtonDeselectAll" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonSelectAll" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="processUnallocCheckbox" min="-2" pref="23" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="jPanel1" pref="428" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
@@ -90,6 +90,9 @@
</LineBorder>
</Border>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 0]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[160, 160]"/>
</Property>
@@ -129,50 +132,49 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jSeparator2" alignment="1" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="jScrollPane1" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="descriptionLabel" min="-2" pref="203" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="advancedButton" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="descriptionLabel" pref="302" max="32767" attributes="0"/>
<Component id="jScrollPane1" alignment="1" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="globalSettingsButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="211" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="330" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="jSeparator2" min="-2" pref="2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
<Component id="descriptionLabel" min="-2" pref="20" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="descriptionLabel" min="-2" pref="24" max="-2" attributes="0"/>
<Component id="advancedButton" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="globalSettingsButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="advancedButton">
<Component class="javax.swing.JButton" name="globalSettingsButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestJobSettingsPanel.advancedButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestJobSettingsPanel.globalSettingsButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestJobSettingsPanel.advancedButton.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestJobSettingsPanel.globalSettingsButton.actionCommand" 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="advancedButtonActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="globalSettingsButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator2">
@@ -196,7 +198,12 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="simplePanel">
<Container class="javax.swing.JPanel" name="ingestSettingsPanel">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 300]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
<Property name="axis" type="int" value="3"/>
@@ -25,6 +25,7 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
@@ -32,6 +33,7 @@ import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog;
/**
@@ -78,6 +80,7 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
return this.settings;
}
@Messages({"IngestJobSettingsPanel.noPerRunSettings=The selected module has no per-run settings."})
private void customizeComponents() {
modulesTable.setModel(new IngestModulesTableModel());
modulesTable.setTableHeader(null);
@@ -108,19 +111,21 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
if (!listSelectionModel.isSelectionEmpty()) {
int index = listSelectionModel.getMinSelectionIndex();
selectedModule = modules.get(index);
simplePanel.removeAll();
ingestSettingsPanel.removeAll();
if (null != selectedModule.getModuleSettingsPanel()) {
simplePanel.add(selectedModule.getModuleSettingsPanel());
ingestSettingsPanel.add(selectedModule.getModuleSettingsPanel());
} else {
ingestSettingsPanel.add(new JLabel(Bundle.IngestJobSettingsPanel_noPerRunSettings()));
}
simplePanel.revalidate();
simplePanel.repaint();
advancedButton.setEnabled(null != selectedModule.getGlobalSettingsPanel());
ingestSettingsPanel.revalidate();
ingestSettingsPanel.repaint();
globalSettingsButton.setEnabled(null != selectedModule.getGlobalSettingsPanel());
descriptionLabel.setText(selectedModule.getDescription());
descriptionLabel.setToolTipText(selectedModule.getDescription());
}
}
});
modulesTable.setRowSelectionInterval(0, 0);
processUnallocCheckbox.setSelected(this.settings.getProcessUnallocatedSpace());
}
@@ -137,20 +142,21 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
modulesScrollPane = new javax.swing.JScrollPane();
modulesTable = new javax.swing.JTable();
jPanel1 = new javax.swing.JPanel();
advancedButton = new javax.swing.JButton();
globalSettingsButton = new javax.swing.JButton();
jSeparator2 = new javax.swing.JSeparator();
descriptionLabel = new javax.swing.JLabel();
jScrollPane1 = new javax.swing.JScrollPane();
simplePanel = new javax.swing.JPanel();
ingestSettingsPanel = new javax.swing.JPanel();
jButtonSelectAll = new javax.swing.JButton();
jButtonDeselectAll = new javax.swing.JButton();
processUnallocCheckbox = new javax.swing.JCheckBox();
setMaximumSize(new java.awt.Dimension(5750, 3000));
setMinimumSize(new java.awt.Dimension(522, 257));
setPreferredSize(new java.awt.Dimension(575, 300));
setMinimumSize(new java.awt.Dimension(0, 0));
setPreferredSize(new java.awt.Dimension(625, 450));
modulesScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160)));
modulesScrollPane.setMinimumSize(new java.awt.Dimension(0, 0));
modulesScrollPane.setPreferredSize(new java.awt.Dimension(160, 160));
modulesTable.setBackground(new java.awt.Color(240, 240, 240));
@@ -169,12 +175,12 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160)));
jPanel1.setPreferredSize(new java.awt.Dimension(338, 257));
advancedButton.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.advancedButton.text")); // NOI18N
advancedButton.setActionCommand(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.advancedButton.actionCommand")); // NOI18N
advancedButton.setEnabled(false);
advancedButton.addActionListener(new java.awt.event.ActionListener() {
globalSettingsButton.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.globalSettingsButton.text")); // NOI18N
globalSettingsButton.setActionCommand(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.globalSettingsButton.actionCommand")); // NOI18N
globalSettingsButton.setEnabled(false);
globalSettingsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
advancedButtonActionPerformed(evt);
globalSettingsButtonActionPerformed(evt);
}
});
@@ -183,36 +189,37 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
jScrollPane1.setBorder(null);
jScrollPane1.setPreferredSize(new java.awt.Dimension(250, 180));
simplePanel.setLayout(new javax.swing.BoxLayout(simplePanel, javax.swing.BoxLayout.PAGE_AXIS));
jScrollPane1.setViewportView(simplePanel);
ingestSettingsPanel.setMinimumSize(new java.awt.Dimension(0, 300));
ingestSettingsPanel.setLayout(new javax.swing.BoxLayout(ingestSettingsPanel, javax.swing.BoxLayout.PAGE_AXIS));
jScrollPane1.setViewportView(ingestSettingsPanel);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 203, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(advancedButton)))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 302, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(globalSettingsButton)))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 211, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 330, Short.MAX_VALUE)
.addGap(18, 18, 18)
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(8, 8, 8)
.addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(advancedButton))
.addContainerGap())
.addComponent(globalSettingsButton)
.addGap(8, 8, 8))
);
jButtonSelectAll.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.jButtonSelectAll.text")); // NOI18N
@@ -244,8 +251,8 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 271, Short.MAX_VALUE)
.addGap(10, 10, 10))
.addGroup(layout.createSequentialGroup()
.addGap(24, 24, 24)
@@ -255,8 +262,8 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
.addComponent(jButtonSelectAll, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jButtonDeselectAll)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 30, Short.MAX_VALUE)))
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 310, Short.MAX_VALUE)
.addGap(32, 32, 32)))
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 324, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
@@ -264,9 +271,6 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE)
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@@ -274,11 +278,14 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
.addComponent(jButtonDeselectAll)
.addComponent(jButtonSelectAll))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(processUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addComponent(processUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 428, Short.MAX_VALUE)
.addContainerGap())))
);
}// </editor-fold>//GEN-END:initComponents
private void advancedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_advancedButtonActionPerformed
private void globalSettingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_globalSettingsButtonActionPerformed
final AdvancedConfigurationDialog dialog = new AdvancedConfigurationDialog();
dialog.addApplyButtonListener(new ActionListener() {
@@ -299,7 +306,7 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
});
dialog.display(selectedModule.getGlobalSettingsPanel());
}//GEN-LAST:event_advancedButtonActionPerformed
}//GEN-LAST:event_globalSettingsButtonActionPerformed
private void jButtonSelectAllActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonSelectAllActionPerformed
SelectAllModules(true);
@@ -321,8 +328,9 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton advancedButton;
private javax.swing.JLabel descriptionLabel;
private javax.swing.JButton globalSettingsButton;
private javax.swing.JPanel ingestSettingsPanel;
private javax.swing.JButton jButtonDeselectAll;
private javax.swing.JButton jButtonSelectAll;
private javax.swing.JPanel jPanel1;
@@ -331,7 +339,6 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
private javax.swing.JScrollPane modulesScrollPane;
private javax.swing.JTable modulesTable;
private javax.swing.JCheckBox processUnallocCheckbox;
private javax.swing.JPanel simplePanel;
private javax.swing.ButtonGroup timeGroup;
// End of variables declaration//GEN-END:variables
@@ -556,9 +556,9 @@ public class IngestManager {
this.jobsById.remove(job.getId());
}
for (IngestModuleError error : errors) {
logger.log(Level.SEVERE, String.format("Error starting %s ingest module", error.getModuleDisplayName()), error.getModuleError()); //NON-NLS
logger.log(Level.SEVERE, String.format("Error starting %s ingest module for job %d", error.getModuleDisplayName(), job.getId()), error.getModuleError()); //NON-NLS
}
IngestManager.logger.log(Level.INFO, "Ingest job {0} could not be started", job.getId()); //NON-NLS
IngestManager.logger.log(Level.SEVERE, "Ingest job {0} could not be started", job.getId()); //NON-NLS
if (RuntimeProperties.coreComponentsAreActive()) {
EventQueue.invokeLater(new Runnable() {
@@ -20,20 +20,25 @@ package org.sleuthkit.autopsy.ingest;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Directory;
@@ -49,7 +54,6 @@ public final class RunIngestModulesDialog extends JDialog {
private static final long serialVersionUID = 1L;
private static final String TITLE = NbBundle.getMessage(RunIngestModulesDialog.class, "IngestDialog.title.text");
private final IngestType ingestType;
private static Dimension DIMENSIONS = new Dimension(500, 300);
private final List<Content> dataSources = new ArrayList<>();
private IngestJobSettingsPanel ingestJobSettingsPanel;
@@ -75,7 +79,7 @@ public final class RunIngestModulesDialog extends JDialog {
* @param dataSources The data sources to be processed.
*/
public RunIngestModulesDialog(List<Content> dataSources) {
this(new JFrame(TITLE), TITLE, true, dataSources);
this((JFrame) WindowManager.getDefault().getMainWindow(), TITLE, true, dataSources);
}
/**
@@ -98,11 +102,7 @@ public final class RunIngestModulesDialog extends JDialog {
/**
* Center the dialog.
*/
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
setSize(DIMENSIONS);
int width = this.getSize().width;
int height = this.getSize().height;
setLocation((screenDimension.width - width) / 2, (screenDimension.height - height) / 2);
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();;
/**
* Get the default or saved ingest job settings for this context and use
@@ -111,7 +111,8 @@ public final class RunIngestModulesDialog extends JDialog {
IngestJobSettings ingestJobSettings = new IngestJobSettings(RunIngestModulesDialog.class.getCanonicalName(), this.ingestType);
RunIngestModulesDialog.showWarnings(ingestJobSettings);
this.ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
add(this.ingestJobSettingsPanel, BorderLayout.PAGE_START);
setPreferredSize(this.ingestJobSettingsPanel.getPreferredSize());
add(this.ingestJobSettingsPanel, BorderLayout.CENTER);
// Add a start ingest button.
JButton startButton = new JButton(NbBundle.getMessage(this.getClass(), "IngestDialog.startButton.title"));
@@ -133,12 +134,13 @@ public final class RunIngestModulesDialog extends JDialog {
// Put the buttons in their own panel, under the settings panel.
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
buttonPanel.add(new javax.swing.Box.Filler(new Dimension(10, 10), new Dimension(10, 10), new Dimension(10, 10)));
buttonPanel.setLayout(new FlowLayout(FlowLayout.TRAILING));
buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
buttonPanel.add(startButton);
buttonPanel.add(new javax.swing.Box.Filler(new Dimension(10, 10), new Dimension(10, 10), new Dimension(10, 10)));
buttonPanel.add(new javax.swing.Box.Filler(new Dimension(5, 10), new Dimension(5, 10), new Dimension(5, 10)));
buttonPanel.add(closeButton);
add(buttonPanel, BorderLayout.LINE_START);
add(buttonPanel, BorderLayout.SOUTH);
/**
* Add a handler for when the dialog window is closed directly,
@@ -154,8 +156,10 @@ public final class RunIngestModulesDialog extends JDialog {
/**
* Show the dialog.
*/
int width = this.getPreferredSize().width;
int height = this.getPreferredSize().height;
setLocation((screenDimension.width - width) / 2, (screenDimension.height - height) / 2);
pack();
setResizable(false);
setVisible(true);
}
@@ -196,7 +200,7 @@ public final class RunIngestModulesDialog extends JDialog {
JOptionPane.showMessageDialog(null, warningMessage.toString());
}
}
/**
* Constructs a dialog box that allows a user to configure and execute
* analysis of one or more data sources with ingest modules.
@@ -236,5 +240,5 @@ public final class RunIngestModulesDialog extends JDialog {
this.dataSources.clear();
this.dataSources.addAll(dataSources);
}
}
@@ -23,7 +23,7 @@
<Component id="skipNoExtCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="skipKnownFiles" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="138" max="32767" attributes="0"/>
<EmptySpace min="0" pref="10" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@@ -93,7 +93,7 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett
.addComponent(skipTextPlain)
.addComponent(skipNoExtCheckBox)
.addComponent(skipKnownFiles))
.addGap(0, 138, Short.MAX_VALUE))
.addGap(0, 10, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -0,0 +1,58 @@
/*
* 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.modules.filetypeid;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
/**
* Ingest job options for the file type identifier ingest module instances.
*
* @deprecated This class is obsolete (files are no longer skipped for any
* reason by file typing) but it is retained for backwards compatibility because
* it was erroneously made part of the public API and so that old settings files
* can be deserialized successfully (and ignored).
*/
@Deprecated
public class FileTypeIdModuleSettings implements IngestModuleIngestJobSettings {
private static final long serialVersionUID = 1L;
private boolean skipKnownFiles = true;
private final boolean skipSmallFiles = false; // No longer used.
FileTypeIdModuleSettings() {
}
FileTypeIdModuleSettings(boolean skipKnownFiles) {
this.skipKnownFiles = skipKnownFiles;
}
@Override
public long getVersionNumber() {
return serialVersionUID;
}
void setSkipKnownFiles(boolean enabled) {
skipKnownFiles = enabled;
}
boolean skipKnownFiles() {
return skipKnownFiles;
}
}
@@ -26,7 +26,7 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="knownHashDbsLabel" min="-2" pref="272" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<EmptySpace min="0" pref="18" max="32767" attributes="0"/>
</Group>
<Component id="knownBadHashDbsLabel" max="32767" attributes="0"/>
<Group type="102" attributes="0">
@@ -47,15 +47,15 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
<Component id="knownHashDbsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" min="-2" pref="58" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="54" max="32767" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="knownBadHashDbsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane2" pref="53" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane2" min="-2" pref="58" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="alwaysCalcHashesCheckbox" min="-2" pref="35" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="alwaysCalcHashesCheckbox" min="-2" pref="27" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@@ -120,9 +120,6 @@
<Property name="verticalAlignment" type="int" value="1"/>
<Property name="verticalTextPosition" type="int" value="1"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="alwaysCalcHashesCheckboxActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<Properties>
@@ -321,7 +321,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(knownHashDbsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 272, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
.addGap(0, 18, Short.MAX_VALUE))
.addComponent(knownBadHashDbsLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
@@ -337,14 +337,14 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
.addGap(2, 2, 2)
.addComponent(knownHashDbsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 54, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(knownBadHashDbsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(alwaysCalcHashesCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(alwaysCalcHashesCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0))
);
}// </editor-fold>//GEN-END:initComponents
@@ -23,7 +23,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.logging.Level;
import javafx.beans.Observable;
@@ -150,11 +149,7 @@ public final class FilteredEventsModel {
final ZoomParams zoomParams = requestedZoomParamters.get();
if (zoomParams != null) {
if (zoomParams.getTypeZoomLevel().equals(requestedTypeZoom.get()) == false
|| zoomParams.getDescriptionLOD().equals(requestedLOD.get()) == false
|| zoomParams.getFilter().equals(requestedFilter.get()) == false
|| Objects.equals(zoomParams.getTimeRange(), requestedTimeRange.get()) == false) {
synchronized (FilteredEventsModel.this) {
requestedTypeZoom.set(zoomParams.getTypeZoomLevel());
requestedFilter.set(zoomParams.getFilter());
requestedTimeRange.set(zoomParams.getTimeRange());
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014-15 Basis Technology Corp.
* Copyright 2014-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,10 +33,7 @@ import javafx.collections.ObservableList;
* a {@link CompoundFilter} uses listeners to enforce the following
* relationships between it and its sub-filters:
* <ol>
* <le>if a filter becomes active, and all its sub-filters were inactive, make
* them all active</le>
* <le>if a filter becomes inactive and all its sub-filters were active, make
* them all inactive</le>
* <le>if a filter becomes inactive disable all of its subfilters</le>
* <le>if a sub-filter changes active state set the parent filter active if any
* of its sub-filters are active.</le>
* </ol>
@@ -93,9 +90,7 @@ public abstract class CompoundFilter<SubFilterType extends Filter> extends Abstr
for (int i = 0; i < oneFilter.getSubFilters().size(); i++) {
final SubFilterType subFilter = oneFilter.getSubFilters().get(i);
final SubFilterType otherSubFilter = otherFilter.getSubFilters().get(i);
if (subFilter.equals(otherSubFilter) == false
|| subFilter.isDisabled() != otherSubFilter.isDisabled()
|| subFilter.isSelected() != otherSubFilter.isSelected()) {
if (subFilter.equals(otherSubFilter) == false) {
return false;
}
}
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -37,6 +37,7 @@ public class DataSourcesFilter extends UnionFilter<DataSourceFilter> {
public DataSourcesFilter copyOf() {
final DataSourcesFilter filterCopy = new DataSourcesFilter();
filterCopy.setSelected(isSelected());
filterCopy.setDisabled(isDisabled());
//add a copy of each subfilter
this.getSubFilters().forEach((DataSourceFilter t) -> {
filterCopy.addSubFilter(t.copyOf());
@@ -87,7 +88,7 @@ public class DataSourcesFilter extends UnionFilter<DataSourceFilter> {
}
final DataSourcesFilter other = (DataSourcesFilter) obj;
if (isSelected() != other.isSelected()) {
if (isActive() != other.isActive()) {
return false;
}
@@ -1,7 +1,20 @@
/*
* 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.
* Autopsy Forensic Browser
*
* Copyright 2015-16 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.timeline.filters;
@@ -30,6 +43,7 @@ public class HashHitsFilter extends UnionFilter<HashSetFilter> {
public HashHitsFilter copyOf() {
HashHitsFilter filterCopy = new HashHitsFilter();
filterCopy.setSelected(isSelected());
filterCopy.setDisabled(isDisabled());
//add a copy of each subfilter
this.getSubFilters().forEach((HashSetFilter t) -> {
filterCopy.addSubFilter(t.copyOf());
@@ -65,7 +79,7 @@ public class HashHitsFilter extends UnionFilter<HashSetFilter> {
}
final HashHitsFilter other = (HashHitsFilter) obj;
if (isSelected() != other.isSelected()) {
if (isActive() != other.isActive()) {
return false;
}
@@ -1,7 +1,20 @@
/*
* 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.
* Autopsy Forensic Browser
*
* Copyright 2015-16 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.timeline.filters;
@@ -31,6 +44,7 @@ public class TagsFilter extends UnionFilter<TagNameFilter> {
public TagsFilter copyOf() {
TagsFilter filterCopy = new TagsFilter();
filterCopy.setSelected(isSelected());
filterCopy.setDisabled(isDisabled());
//add a copy of each subfilter
this.getSubFilters().forEach((TagNameFilter t) -> {
filterCopy.addSubFilter(t.copyOf());
@@ -66,7 +80,7 @@ public class TagsFilter extends UnionFilter<TagNameFilter> {
}
final TagsFilter other = (TagsFilter) obj;
if (isSelected() != other.isSelected()) {
if (isActive() != other.isActive()) {
return false;
}
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-15 Basis Technology Corp.
* Copyright 2013-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -126,7 +126,7 @@ public class TypeFilter extends UnionFilter<TypeFilter> {
}
final TypeFilter other = (TypeFilter) obj;
if (isSelected() != other.isSelected()) {
if (isActive() != other.isActive()) {
return false;
}
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014-15 Basis Technology Corp.
* Copyright 2014-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2015 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,12 +22,14 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.BlackboardResultWriter;
@@ -110,33 +112,60 @@ public class KeywordSearch {
}
/**
* Listener to swap cores when the case changes
* Listener to create/open and close Solr cores when cases are
* created/opened and closed.
*/
static class CaseChangeListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
/*
* TODO (AUT-2081): There is a Solr core unloading bug, fixed in
* Solr 5.4, that results in the co-existence of a core.properties
* file and a core.properties.unloaded file in the core instance
* directory when a core is closed/unloaded. When this happens,
* subsequent core open/load attempts will fail. The workaround for
* single-user cases is to close and reopen Autopsy so that a new
* server instance gets spun up.
*/
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
if (null != evt.getOldValue()) {
/*
* A case is being closed.
*/
Case closedCase = (Case) evt.getOldValue();
try {
BlackboardResultWriter.stopAllWriters();
Thread.sleep(2000); // TODO (RC): This is a fragile way to wait here.
/*
* TODO (AUT-2084): The following code
* KeywordSearch.CaseChangeListener gambles that any
* BlackboardResultWriters (SwingWorkers) will complete
* in less than roughly two seconds
*/
Thread.sleep(2000);
server.closeCore();
} catch (Exception ex) {
String caseName = closedCase.getName();
logger.log(Level.SEVERE, String.format("Failed to close core for %s", caseName), ex); //NON-NLS
MessageNotifyUtil.Notify.error(NbBundle.getMessage(KeywordSearch.class, "KeywordSearch.closeCore.notification.msg"), ex.getMessage());
String caseId = Paths.get(closedCase.getCaseDirectory(), closedCase.getName()).toString();
logger.log(Level.SEVERE, String.format("Failed to close core for %s", caseId), ex); //NON-NLS
if (RuntimeProperties.coreComponentsAreActive()) {
MessageNotifyUtil.Notify.error(NbBundle.getMessage(KeywordSearch.class, "KeywordSearch.closeCore.notification.msg"), ex.getMessage());
}
}
}
if (null != evt.getNewValue()) {
/*
* A case is being created/opened.
*/
Case openedCase = (Case) evt.getNewValue();
try {
server.openCoreForCase(openedCase);
} catch (Exception ex) {
String caseName = openedCase.getName();
logger.log(Level.SEVERE, String.format("Failed to open or create core for %s", caseName), ex); //NON-NLS
MessageNotifyUtil.Notify.error(NbBundle.getMessage(KeywordSearch.class, "KeywordSearch.openCore.notification.msg"), ex.getMessage());
String caseId = Paths.get(openedCase.getCaseDirectory(), openedCase.getName()).toString();
logger.log(Level.SEVERE, String.format("Failed to open or create core for %s", caseId), ex); //NON-NLS
if (RuntimeProperties.coreComponentsAreActive()) {
MessageNotifyUtil.Notify.error(NbBundle.getMessage(KeywordSearch.class, "KeywordSearch.openCore.notification.msg"), ex.getMessage());
}
}
}
}
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2015 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -66,14 +66,16 @@ import org.apache.solr.common.SolrException;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.coreutils.UNCPathUtilities;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
/**
* Handles for keeping track of a Solr server and its cores
* Handles management of a either a local or centralized Solr server and its
* cores.
*/
public class Server {
// field names that are used in SOLR schema
/**
* Solr document field names.
*/
public static enum Schema {
ID {
@@ -148,6 +150,7 @@ public class Server {
}
},
};
public static final String HL_ANALYZE_CHARS_UNLIMITED = "500000"; //max 1MB in a chunk. use -1 for unlimited, but -1 option may not be supported (not documented)
//max content size we can send to Solr
public static final long MAX_CONTENT_SIZE = 1L * 1024 * 1024 * 1024;
@@ -196,7 +199,7 @@ public class Server {
*/
Server() {
initSettings();
this.localSolrServer = new HttpSolrServer("http://localhost:" + currentSolrServerPort + "/solr"); //NON-NLS
serverAction = new ServerAction();
solrFolder = InstalledFileLocator.getDefault().locate("solr", Server.class.getPackage().getName(), false); //NON-NLS
@@ -204,7 +207,7 @@ public class Server {
currentCoreLock = new ReentrantReadWriteLock(true);
uncPathUtilities = new UNCPathUtilities();
logger.log(Level.INFO, "Created Server instance"); //NON-NLS
}
@@ -596,11 +599,13 @@ public class Server {
* ** Convenience methods for use while we only open one case at a time ***
*/
/**
* Opens or creates a core (index) for a case.
* Creates/opens a Solr core (index) for a case.
*
* @param theCase the case for which the core is to be opened or created.
* @param theCase The case for which the core is to be created/opened.
*
* @throws KeywordSearchModuleException
*
* @throws KeywordSearchModuleException If an error occurs while
* creating/opening the core.
*/
void openCoreForCase(Case theCase) throws KeywordSearchModuleException {
currentCoreLock.writeLock().lock();
@@ -630,6 +635,15 @@ public class Server {
currentCoreLock.writeLock().lock();
try {
if (null != currentCore) {
/*
* TODO (AUT-2081): There is a Solr core unloading bug, fixed in
* Solr 5.4, that will result in the co-existence of a
* core.properties file and a core.properties.unloaded file in
* the core instance directory when the following code executes.
* When this happens, subsequent open/load attempts will fail.
* The workaround for single-user cases is to close and reopen
* Autopsy so that a new server instance gets spun up.
*/
currentCore.close();
currentCore = null;
serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STOPPED);
@@ -655,7 +669,7 @@ public class Server {
*
* @return absolute path to index dir
*/
String getIndexDirPath(Case theCase) {
String geCoreDataDirPath(Case theCase) {
String indexDir = theCase.getModuleDirectory() + File.separator + "keywordsearch" + File.separator + "data"; //NON-NLS
if (uncPathUtilities != null) {
// if we can check for UNC paths, do so, otherwise just return the indexDir
@@ -676,11 +690,14 @@ public class Server {
* ** end single-case specific methods ***
*/
/**
* Open a core for the given case
* Creates/opens a Solr core (index) for a case.
*
* @param theCase the case to open core for
* @param theCase The case for which the core is to be created/opened.
*
* @return
* @return An object representing the created/opened core.
*
* @throws KeywordSearchModuleException If an error occurs while
* creating/opening the core.
*/
private Core openCore(Case theCase) throws KeywordSearchModuleException {
try {
@@ -692,11 +709,12 @@ public class Server {
currentSolrServer = new HttpSolrServer("http://" + host + ":" + port + "/solr"); //NON-NLS
}
connectToSolrServer(currentSolrServer);
} catch (SolrServerException | IOException ex) {
throw new KeywordSearchModuleException(NbBundle.getMessage(Server.class, "Server.connect.exception.msg"), ex);
}
String dataDir = getIndexDirPath(theCase);
String dataDir = geCoreDataDirPath(theCase);
String coreName = theCase.getTextIndexName();
return this.openCore(coreName.isEmpty() ? DEFAULT_CORE_NAME : coreName, new File(dataDir), theCase.getCaseType());
}
@@ -1050,12 +1068,17 @@ public class Server {
}
/**
* Open a new core
* Creates/opens a Solr core (index) for a case.
*
* @param coreName name to refer to the core by in Solr
* @param dataDir directory to load/store the core data from/to
* @param coreName The core name.
* @param dataDir The data directory for the core.
* @param caseType The type of the case (single-user or multi-user) for
* which the core is being created/opened.
*
* @return new core
* @return An object representing the created/opened core.
*
* @throws KeywordSearchModuleException If an error occurs while
* creating/opening the core.
*/
private Core openCore(String coreName, File dataDir, CaseType caseType) throws KeywordSearchModuleException {
@@ -1064,14 +1087,25 @@ public class Server {
dataDir.mkdirs();
}
//handle a possible scenario when server process might not be fully started
if (!this.isRunning()) {
logger.log(Level.WARNING, "Core open requested, but server not yet running"); //NON-NLS
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.openCore.exception.msg"));
logger.log(Level.SEVERE, "Core create/open requested, but server not yet running"); //NON-NLS
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.msg"));
}
if (!coreExistsOnServer(coreName)) {
if (!coreIsLoaded(coreName)) {
/*
* The core either does not exist or it is not loaded. Make a
* request that will cause the core to be created if it does not
* exist or loaded if it already exists.
*
* TODO (AUT-2081): There is a Solr core unloading bug, fixed in
* Solr 5.4, that results in the co-existence of a
* core.properties file and a core.properties.unloaded file in
* the core instance directory when a core is unloaded. When
* this happens, this code will fail. The workaround for
* single-user cases is to close and reopen Autopsy so that a
* new server instance gets spun up.
*/
CoreAdminRequest.Create createCoreRequest = new CoreAdminRequest.Create();
createCoreRequest.setDataDir(dataDir.getAbsolutePath());
createCoreRequest.setCoreName(coreName);
@@ -1088,8 +1122,7 @@ public class Server {
return new Core(coreName, caseType);
} catch (SolrServerException | SolrException | IOException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex);
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex);
}
}
@@ -1106,17 +1139,19 @@ public class Server {
}
/**
* Determines whether or not a Solr core instance exists on the current Solr
* server.
* Determines whether or not a particular Solr core exists and is loaded.
*
* @param coreName the name of the core.
* @param coreName The name of the core.
*
* @return true or false.
* @return True if the core exists and is loaded, false if the core does not
* exist or is not loaded
*
* @throws SolrServerException
* @throws IOException
* @throws SolrServerException If there is a problem communicating with the
* Solr server.
* @throws IOException If there is a problem communicating with the
* Solr server.
*/
private boolean coreExistsOnServer(String coreName) throws SolrServerException, IOException {
private boolean coreIsLoaded(String coreName) throws SolrServerException, IOException {
CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer);
return response.getCoreStatus(coreName).get("instanceDir") != null; //NON-NLS
}
+1
View File
@@ -2,6 +2,7 @@
Improvements:
- VMWare virtual machine files (vmdk) and Microsoft Virtual Hard Drives (vhd) can be added as data sources.
- New core ingest module detects vmdk and vhd files embedded in other data sources and adds them as data sources.
- Text associated with artifacts posted to the blackboard is indexed and searched for keywords.
- Custom (user-defined) blackboard artifact and attribute types displayed in UI and included reports.
- File size and MIME type conditions can be specified for interesting files rules.
- File size and MIME type conditions can be specified for file search by attributes.
@@ -277,8 +277,8 @@ class SearchEngineURLQueryAnalyzer extends Extract {
int totalQueries = 0;
try {
//from blackboard_artifacts
Collection<BlackboardArtifact> listArtifacts = currentCase.getSleuthkitCase().getMatchingArtifacts("WHERE (artifact_type_id = '" + ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() //NON-NLS
+ "' OR artifact_type_id = '" + ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID() + "') "); //List of every 'web_history' and 'bookmark' artifact NON-NLS
Collection<BlackboardArtifact> listArtifacts = currentCase.getSleuthkitCase().getMatchingArtifacts("WHERE (blackboard_artifacts.artifact_type_id = '" + ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() //NON-NLS
+ "' OR blackboard_artifacts.artifact_type_id = '" + ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID() + "') "); //List of every 'web_history' and 'bookmark' artifact NON-NLS
logger.log(Level.INFO, "Processing {0} blackboard artifacts.", listArtifacts.size()); //NON-NLS
for (BlackboardArtifact artifact : listArtifacts) {
@@ -1,5 +1,5 @@
#Updated by build script
#Mon, 22 Feb 2016 16:37:47 -0500
#Wed, 06 Apr 2016 23:58:02 -0400
LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314
SPLASH_WIDTH=538
@@ -1,4 +1,4 @@
#Updated by build script
#Mon, 22 Feb 2016 16:37:47 -0500
#Wed, 06 Apr 2016 23:58:02 -0400
CTL_MainWindow_Title=Autopsy 4.1.0
CTL_MainWindow_Title_No_Project=Autopsy 4.1.0
+2 -2
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 4.0
PROJECT_NUMBER = 4.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -1025,7 +1025,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = 4.0
HTML_OUTPUT = 4.1
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 40 KiB

+1 -1
View File
@@ -4,7 +4,7 @@
Overview
-----
This is the User's Guide for the <a href="http://www.sleuthkit.org/autopsy/">open source Autopsy platform</a>. Autopsy allows you to examine a hard drive or mobile device and recover evidence from it. This guide should help you with using Autopsy. The <a href="http://www.sleuthkit.org/autopsy/docs/api-docs/4.0/"> developer's guide</a> will help you develop your own Autopsy modules.
This is the User's Guide for the <a href="http://www.sleuthkit.org/autopsy/">open source Autopsy platform</a>. Autopsy allows you to examine a hard drive or mobile device and recover evidence from it. This guide should help you with using Autopsy. The <a href="http://www.sleuthkit.org/autopsy/docs/api-docs/4.1/"> developer's guide</a> will help you develop your own Autopsy modules.
Autopsy 4 (and 3) are a complete rewrite from Autopsy 2, and none of this document is relevant to Autopsy 2.
+2 -2
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 4.0
PROJECT_NUMBER = 4.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -1063,7 +1063,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = api-docs/4.0/
HTML_OUTPUT = api-docs/4.1/
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).