Merge branch 'master' of github.com:sleuthkit/autopsy

This commit is contained in:
Brian Carrier 2012-08-15 17:06:46 -04:00
commit d88829a1a9
293 changed files with 16691 additions and 9700 deletions

6
.gitignore vendored
View File

@ -22,8 +22,12 @@ Bundle_*.properties
genfiles.properties
/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties
/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties
/CoreUtils/src/org/sleuthkit/autopsy/coreutils/Bundle.properties
/CoreUtils/src/org/sleuthkit/autopsy/coreutils/Version.properties
/Testing/script/input/
/Testing/script/output/
/Testing/script/gold/
*~
/netbeans-plat
/docs/doxygen/doxygen_docs

View File

@ -10,12 +10,15 @@ correct C libraries.
STEPS:
1) Get Java Setup
1a) Download and install 32-bit version of JDK (32-bit is currently
needed even if you have a 64-bit system).
1b) Ensure that JDK_HOME is set to the root JDK directory.
1c) Download and install Netbeans IDE 7.0.1 (http://netbeans.org/)
1c) (optional) Download and install Netbeans IDE (http://netbeans.org/)
Note: Netbeans IDE is not required to build and run Autopsy,
but it is a recommended IDE to use for development of Autopsy modules.
2) Get Sleuth Kit Setup
@ -51,11 +54,18 @@ yet, so we don't have instructions for that yet.
4) Compile Autopsy
4a) Start NetBean IDE and open the Autopsy project.
4b) Choose to build the Autopsy project / module. It is the highest
4a) using Netbeans IDE:
- Start NetBeans IDE and open the Autopsy project.
- Choose to build the Autopsy project / module. It is the highest
level project that will then cause the other modules to be compiled.
4b) without Netbeans IDE (requires JDK and ant >= 1.7.1):
- from root directory of Autopsy source execute:
ant build
(to build Autopsy)
ant run
(to run Autopsy)
BACKGROUND:
Here are some notes to shed some light on what is going on during

View File

@ -6,15 +6,7 @@
<code-name-base>org.sleuthkit.autopsy.casemodule</code-name-base>
<suite-component/>
<module-dependencies>
<dependency>
<code-name-base>org.jdesktop.beansbinding</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.11.1.121</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.modules.settings</code-name-base>
<build-prerequisite/>

View File

@ -60,7 +60,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
// String: time zone that the image is from
static final String TIMEZONE_PROP = "timeZone";
// String[]: array of paths to each image selected
static final String IMGPATHS_PROP = "imgPaths";
static final String IMGPATH_PROP = "imgPath";
// CleanupTask: task to clean up the database file if wizard errors/is cancelled after it is created
static final String IMAGECLEANUPTASK_PROP = "finalFileCleanup";
// int: the next availble id for a new image

View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageErrorsDialog.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="iconImage" type="java.awt.Image" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="null"/>
</Property>
<Property name="iconImages" type="java.util.List" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="null"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" pref="485" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Component id="copyButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane1" pref="219" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="closeButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="copyButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="errorsText">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="f0" green="f0" red="f0" type="rgb"/>
</Property>
<Property name="columns" type="int" value="20"/>
<Property name="editable" type="boolean" value="false"/>
<Property name="rows" type="int" value="5"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="copyButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageErrorsDialog.copyButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageErrorsDialog.copyButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="copyButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="closeButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageErrorsDialog.closeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageErrorsDialog.closeButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,121 @@
/*
* 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;
/**
* Dialog to show add image error messages
*/
public class AddImageErrorsDialog extends javax.swing.JDialog {
/**
* Creates new form AddImageErrorsDialog
*/
public AddImageErrorsDialog(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
errorsText = new javax.swing.JTextArea();
copyButton = new javax.swing.JButton();
closeButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle(org.openide.util.NbBundle.getMessage(AddImageErrorsDialog.class, "AddImageErrorsDialog.title")); // NOI18N
setIconImage(null);
setIconImages(null);
errorsText.setBackground(new java.awt.Color(240, 240, 240));
errorsText.setColumns(20);
errorsText.setEditable(false);
errorsText.setRows(5);
jScrollPane1.setViewportView(errorsText);
org.openide.awt.Mnemonics.setLocalizedText(copyButton, org.openide.util.NbBundle.getMessage(AddImageErrorsDialog.class, "AddImageErrorsDialog.copyButton.text")); // NOI18N
copyButton.setToolTipText(org.openide.util.NbBundle.getMessage(AddImageErrorsDialog.class, "AddImageErrorsDialog.copyButton.toolTipText")); // NOI18N
copyButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
copyButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(closeButton, org.openide.util.NbBundle.getMessage(AddImageErrorsDialog.class, "AddImageErrorsDialog.closeButton.text")); // NOI18N
closeButton.setToolTipText(org.openide.util.NbBundle.getMessage(AddImageErrorsDialog.class, "AddImageErrorsDialog.closeButton.toolTipText")); // NOI18N
closeButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
closeButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 485, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(copyButton)
.addGap(18, 18, 18)
.addComponent(closeButton))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 219, Short.MAX_VALUE)
.addGap(0, 0, 0)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(closeButton)
.addComponent(copyButton)))
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void copyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyButtonActionPerformed
errorsText.selectAll();
errorsText.copy();
}//GEN-LAST:event_copyButtonActionPerformed
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
setVisible(false);
}//GEN-LAST:event_closeButtonActionPerformed
void setErrors(String errors) {
errorsText.setText(errors);
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton closeButton;
private javax.swing.JButton copyButton;
private javax.swing.JTextArea errorsText;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration//GEN-END:variables
}

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
@ -6,9 +6,6 @@
</Component>
</NonVisualComponents>
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[559, 328]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[588, 328]"/>
</Property>
@ -31,22 +28,7 @@
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="10" attributes="0"/>
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="imgTypeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="10" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="rawSplit" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="rawSingle" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="encase" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Component id="multipleSelectLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="imgInfoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
<Group type="102" alignment="0" attributes="1">
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/>
@ -63,6 +45,10 @@
</Group>
<Component id="optionsLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace pref="39" max="32767" attributes="0"/>
</Group>
@ -73,85 +59,29 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="imgInfoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
<Component id="imgTypeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="rawSingle" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="rawSplit" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="encase" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="imgPathLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="imgPathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="imgPathBrowserButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="multipleSelectLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="timeZoneLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="timeZoneComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="optionsLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="18" max="32767" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" pref="117" max="32767" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="25" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JRadioButton" name="rawSingle">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.rawSingle.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="rawSingleActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="10"/>
</AuxValues>
</Component>
<Component class="javax.swing.JRadioButton" name="rawSplit">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.rawSplit.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="rawSplitActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="imgTypeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.imgTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JRadioButton" name="encase">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.encase.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="encaseActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="imgPathLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
@ -159,13 +89,6 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="multipleSelectLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.multipleSelectLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="imgPathTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
@ -199,16 +122,6 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="33" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="timeZoneComboBox">
<Properties>
<Property name="maximumRowCount" type="int" value="30"/>

View File

@ -19,19 +19,17 @@
package org.sleuthkit.autopsy.casemodule;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import javax.swing.JCheckBox;
import javax.swing.event.DocumentEvent;
import javax.swing.filechooser.FileFilter;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
/**
* The "Add Image" wizard panel 1. This class is used to design the "form" of
@ -42,17 +40,19 @@ import org.openide.NotifyDescriptor;
final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
private JFileChooser fc = new JFileChooser();
private FileFilter filter;
static final String[] imgExt = {".img", ".dd"};
static final String imgDesc = "Raw Images (*.img, *.dd)";
static GeneralFilter imgFilter = new GeneralFilter(imgExt, imgDesc, false);
static final String[] splitExt = {".*\\.[0-9][0-9][0-9]", ".*\\.[a-z][a-z]"};
static final String splitDesc = "Split Part (*.001, *.002, etc)";
static GeneralFilter splitFilter = new GeneralFilter(splitExt, splitDesc, true);
static final String[] encasExt = {".*\\.e[0-9][0-9]", ".*\\.e[a-z][a-z]"};
static final String encaseDesc = "Encase Images (*.e01, *.eAA)";
static GeneralFilter encaseFilter = new GeneralFilter(encasExt, encaseDesc, true);
private boolean multi = false;
static final List<String> rawExt = Arrays.asList(new String[]{".img", ".dd", ".001", ".aa"});
static final String rawDesc = "Raw Images (*.img, *.dd, *.001, *.aa)";
static GeneralFilter rawFilter = new GeneralFilter(rawExt, rawDesc);
static final List<String> encaseExt = Arrays.asList(new String[]{".e01"});
static final String encaseDesc = "Encase Images (*.e01)";
static GeneralFilter encaseFilter = new GeneralFilter(encaseExt, encaseDesc);
static final List<String> allExt = new ArrayList<String>();
{
allExt.addAll(rawExt);
allExt.addAll(encaseExt);
}
static final String allDesc = "All Supported Types";
static GeneralFilter allFilter = new GeneralFilter(allExt, allDesc);
private AddImageWizardPanel1 wizPanel;
/**
@ -62,20 +62,15 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
AddImageVisualPanel1(AddImageWizardPanel1 wizPanel) {
initComponents();
this.wizPanel = wizPanel;
fc.setDragEnabled(multi);
fc.setDragEnabled(false);
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setMultiSelectionEnabled(multi);
fc.addChoosableFileFilter(imgFilter);
filter = imgFilter;
buttonGroup1.add(encase);
buttonGroup1.add(rawSingle);
buttonGroup1.add(rawSplit);
fc.setMultiSelectionEnabled(false);
fc.addChoosableFileFilter(allFilter);
fc.addChoosableFileFilter(rawFilter);
fc.addChoosableFileFilter(encaseFilter);
fc.setFileFilter(allFilter);
imgPathTextField.getDocument().addDocumentListener(this);
imgPathTextField.setText("");
jLabel1.setText("");
rawSingle.setSelected(true);
rawSplit.setSelected(false);
encase.setSelected(false);
createTimeZoneList();
}
@ -91,17 +86,12 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
}
/**
* Gets the array of image paths from the Image Path Text Field.
* Gets the image path from the Image Path Text Field.
*
* @return imagePaths the array of image paths
* @return imagePath the image path
*/
public String[] getImagePaths() {
String[] imgPath = Case.convertImgPath(imgPathTextField.getText());
if (Case.checkMultiplePathExist(imgPath)) {
return imgPath;
} else {
return new String[0];
}
public String getImagePath() {
return imgPathTextField.getText();
}
public JTextField getImagePathTextField() {
@ -116,27 +106,6 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
return noFatOrphansCheckbox.isSelected();
}
/**
* Gets the type of the image that's selected.
*
* @return imgType the type of the image that selected
*/
public String getImgType() {
if (rawSingle.isSelected()) {
return "Raw Single";
}
if (rawSplit.isSelected()) {
return "Raw Split";
}
if (encase.isSelected()) {
return "EnCase";
} else {
return "Nothing Selected";
}
}
/**
* Gets the time zone that selected on the drop down list.
*
@ -197,57 +166,22 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
private void initComponents() {
buttonGroup1 = new javax.swing.ButtonGroup();
rawSingle = new javax.swing.JRadioButton();
rawSplit = new javax.swing.JRadioButton();
imgTypeLabel = new javax.swing.JLabel();
encase = new javax.swing.JRadioButton();
imgPathLabel = new javax.swing.JLabel();
multipleSelectLabel = new javax.swing.JLabel();
imgPathTextField = new javax.swing.JTextField();
imgPathBrowserButton = new javax.swing.JButton();
this.imgPathBrowserButton.setDefaultCapable(true);
this.imgPathBrowserButton.requestFocus();
imgInfoLabel = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
timeZoneComboBox = new javax.swing.JComboBox();
timeZoneLabel = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
noFatOrphansCheckbox = new javax.swing.JCheckBox();
optionsLabel1 = new javax.swing.JLabel();
setMinimumSize(new java.awt.Dimension(559, 328));
setPreferredSize(new java.awt.Dimension(588, 328));
org.openide.awt.Mnemonics.setLocalizedText(rawSingle, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.rawSingle.text")); // NOI18N
rawSingle.setRequestFocusEnabled(false);
rawSingle.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
rawSingleActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(rawSplit, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.rawSplit.text")); // NOI18N
rawSplit.setRequestFocusEnabled(false);
rawSplit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
rawSplitActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(imgTypeLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgTypeLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(encase, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.encase.text")); // NOI18N
encase.setRequestFocusEnabled(false);
encase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
encaseActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(imgPathLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgPathLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(multipleSelectLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.multipleSelectLabel.text")); // NOI18N
imgPathTextField.setText(org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgPathTextField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(imgPathBrowserButton, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgPathBrowserButton.text")); // NOI18N
@ -257,12 +191,9 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
}
});
imgInfoLabel.setFont(new java.awt.Font("Tahoma", 1, 14));
imgInfoLabel.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(imgInfoLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgInfoLabel.text")); // NOI18N
jLabel1.setForeground(new java.awt.Color(255, 0, 51));
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.jLabel1.text")); // NOI18N
timeZoneComboBox.setMaximumRowCount(30);
org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.timeZoneLabel.text")); // NOI18N
@ -281,19 +212,7 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addComponent(noFatOrphansCheckbox))
.addComponent(imgTypeLabel)
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(rawSplit)
.addComponent(rawSingle)
.addComponent(encase)))
.addComponent(multipleSelectLabel)
.addComponent(imgInfoLabel)
.addComponent(jLabel1)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(timeZoneLabel)
@ -306,7 +225,10 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(imgPathBrowserButton)))
.addComponent(optionsLabel1)
.addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addComponent(noFatOrphansCheckbox)))
.addContainerGap(39, Short.MAX_VALUE))
);
layout.setVerticalGroup(
@ -314,84 +236,25 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(imgInfoLabel)
.addGap(19, 19, 19)
.addComponent(imgTypeLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rawSingle)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(rawSplit)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(encase)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(imgPathLabel)
.addComponent(imgPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(imgPathBrowserButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(multipleSelectLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGap(26, 26, 26)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(timeZoneLabel)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addComponent(optionsLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(noFatOrphansCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel1)
.addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(25, 25, 25))
.addGap(18, 18, Short.MAX_VALUE)
.addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(20, 20, 20))
);
}// </editor-fold>//GEN-END:initComponents
/**
* When the "rawSingle" radio button is selected.
*
* @param evt the action event
*/
private void rawSingleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rawSingleActionPerformed
rawSingle.setSelected(true);
rawSplit.setSelected(false);
encase.setSelected(false);
multipleSelectLabel.setText("Single Image: Multiple Select Disabled");
filter = imgFilter;
multi = false;
this.updateUI(null);
}//GEN-LAST:event_rawSingleActionPerformed
/**
* When the "rawSplit" radio button is selected.
*
* @param evt the action event
*/
private void rawSplitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rawSplitActionPerformed
rawSingle.setSelected(false);
rawSplit.setSelected(true);
encase.setSelected(false);
multipleSelectLabel.setText("Split Image: Multiple Select Enabled. Use Ctrl, Shift, "
+ "or Drag to select multiple image parts");
filter = splitFilter;
multi = true;
updateUI(null);
}//GEN-LAST:event_rawSplitActionPerformed
/**
* When the "encase" radio button is selected.
*
* @param evt the action event
*/
private void encaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_encaseActionPerformed
rawSingle.setSelected(false);
rawSplit.setSelected(false);
encase.setSelected(true);
multipleSelectLabel.setText("EnCase Image: Multiple Select Enabled. Use Ctrl, Shift, "
+ "or Drag to select multiple image parts");
filter = encaseFilter;
multi = true;
updateUI(null);
}//GEN-LAST:event_encaseActionPerformed
/**
* When the "Browse" button is pressed, open the file chooser window to
* select the images.
@ -399,11 +262,6 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
* @param evt the action event
*/
private void imgPathBrowserButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_imgPathBrowserButtonActionPerformed
fc.resetChoosableFileFilters();
fc.addChoosableFileFilter(filter);
fc.setFileFilter(filter);
fc.setMultiSelectionEnabled(multi);
fc.setDragEnabled(multi);
String oldText = imgPathTextField.getText();
// set the current directory of the FileChooser if the ImagePath Field is valid
@ -414,39 +272,8 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
int retval = fc.showOpenDialog(this);
if (retval == JFileChooser.APPROVE_OPTION) {
File[] files = fc.getSelectedFiles();
String path = "";
if (multi) {
for (File file : files) {
path = path + "\"" + file.getPath() + "\" ";
}
String path = fc.getSelectedFile().getPath();
imgPathTextField.setText(path);
} else {
path = fc.getSelectedFile().getPath();
imgPathTextField.setText(path);
}
//if split image, and 1 chunk given, verify it's the first chunk
boolean invalidChunk = false;
String[] imgPath = Case.convertImgPath(imgPathTextField.getText());
if (imgPath.length == 1 && multi == true) {
if (!imgPath[0].matches(".*\\.0.*1$") //001
&& !imgPath[0].matches(".*\\.[aA]{1,}$") //aaa
&& !imgPath[0].matches(".*\\.[eE]{1}0.*1$") //E01
) {
NotifyDescriptor nd = new NotifyDescriptor.Confirmation("You need to select either all chunks or only the first chunk of a split image to add the entire image correctly. Are you sure you want to use this selection?", "Warning: First image chunk not selected", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
nd.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(nd);
if (res != null && res == DialogDescriptor.NO_OPTION) {
invalidChunk = true;
}
}
}
if (invalidChunk) {
imgPathTextField.setText(oldText);
return;
}
}
@ -455,19 +282,13 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.ButtonGroup buttonGroup1;
private javax.swing.JRadioButton encase;
private javax.swing.JLabel imgInfoLabel;
private javax.swing.JButton imgPathBrowserButton;
private javax.swing.JLabel imgPathLabel;
private static javax.swing.JTextField imgPathTextField;
private javax.swing.JLabel imgTypeLabel;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel multipleSelectLabel;
private javax.swing.JCheckBox noFatOrphansCheckbox;
private javax.swing.JLabel optionsLabel1;
private static javax.swing.JRadioButton rawSingle;
private javax.swing.JRadioButton rawSplit;
private javax.swing.JComboBox timeZoneComboBox;
private javax.swing.JLabel timeZoneLabel;
// End of variables declaration//GEN-END:variables
@ -514,50 +335,15 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
* @param e the document event
*/
public void updateUI(DocumentEvent e) {
String[] imgPath = Case.convertImgPath(imgPathTextField.getText());
boolean isExist = Case.checkMultiplePathExist(imgPath);
File imgFile = new File(imgPath[0]);
String imgPath = imgPathTextField.getText();
boolean isExist = Case.pathExists(imgPath);
File imgFile = new File(imgPath);
// check if the given paths exist and those are paths to image files
boolean isImagePath = true;
for (int i = 0; i < imgPath.length; i++) {
File tempImgFile = new File(imgPath[i]);
isImagePath = isImagePath && (Case.isPhysicalDrive(imgPath[i]) || (tempImgFile.exists() && !tempImgFile.isDirectory()
&& (imgFilter.accept(tempImgFile) || splitFilter.accept(tempImgFile)
|| encaseFilter.accept(tempImgFile))));
}
// check if the given path is to an image file
boolean isImagePath = allFilter.accept(imgFile);
// check if the given path is to a physical drive
boolean isPhysicalDrive = Case.isPhysicalDrive(imgPath);
if (isImagePath) {
Case currentCase = Case.getCurrentCase();
File dbFile = new File(currentCase.getCaseDirectory() + File.separator + imgFile.getName() + ".db");
if (dbFile.exists()) {
String dbExist = "This database already exists. Do you want to overwrite the database?";
NotifyDescriptor d = new NotifyDescriptor.Confirmation(dbExist, "Warning: Overwrite Database", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
d.setValue(NotifyDescriptor.NO_OPTION);
isExist = false;
Object res = DialogDisplayer.getDefault().notify(d);
if (res != null && res == DialogDescriptor.YES_OPTION) {
isExist = dbFile.delete();
if (!isExist) {
jLabel1.setText("*Database for this image is already created and it can't be deleted because it's being used.");
}
}
if (res != null && res == DialogDescriptor.NO_OPTION) {
jLabel1.setText("*Database for this image exist. Either delete it or select another image.");
}
}
} else {
isExist = false;
}
if (isExist) {
jLabel1.setText("");
}
this.wizPanel.enableNextButton(isExist);
this.wizPanel.enableNextButton((isExist && isImagePath) || isPhysicalDrive);
}
}

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
@ -25,10 +25,10 @@
<Component id="jLabel1" alignment="0" min="-2" pref="552" max="-2" attributes="1"/>
<Component id="jLabel5" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="16" max="32767" attributes="0"/>
<EmptySpace min="0" pref="36" max="32767" attributes="0"/>
</Group>
<Component id="crDbProgressBar" alignment="0" pref="568" max="32767" attributes="1"/>
<Component id="progressLabel" alignment="0" pref="568" max="32767" attributes="0"/>
<Component id="crDbProgressBar" alignment="0" pref="588" max="32767" attributes="1"/>
<Component id="infoPanel" alignment="0" min="-2" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -46,8 +46,8 @@
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="crDbProgressBar" min="-2" pref="24" max="-2" attributes="1"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="progressLabel" pref="12" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="infoPanel" min="-2" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="24" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -72,13 +72,6 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="progressLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel2.progressLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
@ -86,5 +79,20 @@
</Property>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="infoPanel">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="588" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="47" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
</SubComponents>
</Form>

View File

@ -16,15 +16,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule;
import java.awt.Color;
import javax.swing.JPanel;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
/**
* The "Add Image" wizard panel 2. Provides checkbox to enable indexing, button
@ -32,9 +37,31 @@ import javax.swing.JProgressBar;
*/
final class AddImageVisualPanel2 extends JPanel {
/** Creates new form AddImageVisualPanel2 */
private String nonCriticalErrors = null;
private JLabel progressLabel = null;
private JButton errorButton = null;
/**
* Creates new form AddImageVisualPanel2
*/
AddImageVisualPanel2() {
initComponents();
customizeComponents();
}
private void customizeComponents() {
progressLabel = new JLabel();
infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.PAGE_AXIS));
infoPanel.add(progressLabel);
infoPanel.add(Box.createRigidArea(new Dimension(10, 10))); //spacer
}
void resetInfoPanel() {
if (errorButton != null) {
infoPanel.remove(errorButton);
errorButton = null;
}
progressLabel.setText("");
}
/**
@ -69,6 +96,31 @@ final class AddImageVisualPanel2 extends JPanel {
crDbProgressBar.setValue(value);
}
void setErrors(final String errors, boolean critical) {
crDbProgressBar.setValue(100); //always invoked when process completed
if (critical) {
progressLabel.setText("*Failed to add image (critical errors encountered). Click below to view the Add Image Log.");
}
else {
progressLabel.setText("*Image added (non-critical image errors encountered). Click below to view the Add Image Log.");
}
errorButton = new JButton();
errorButton.setText("View Log");
infoPanel.add(errorButton);
errorButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//JOptionPane.showMessageDialog(null, errors, "Add image non-critical errors", JOptionPane.WARNING_MESSAGE);
AddImageErrorsDialog dialog = new AddImageErrorsDialog(null, true);
dialog.setErrors(errors);
dialog.setVisible(true);
}
});
}
/**
* 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
@ -80,18 +132,27 @@ final class AddImageVisualPanel2 extends JPanel {
crDbProgressBar = new javax.swing.JProgressBar();
jLabel5 = new javax.swing.JLabel();
crDbLabel = new javax.swing.JLabel();
progressLabel = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
infoPanel = new javax.swing.JPanel();
org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(AddImageVisualPanel2.class, "AddImageVisualPanel2.jLabel5.text")); // NOI18N
crDbLabel.setFont(new java.awt.Font("Tahoma", 1, 14));
crDbLabel.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(crDbLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel2.class, "AddImageVisualPanel2.crDbLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(progressLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel2.class, "AddImageVisualPanel2.progressLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AddImageVisualPanel2.class, "AddImageVisualPanel2.jLabel1.text")); // NOI18N
javax.swing.GroupLayout infoPanelLayout = new javax.swing.GroupLayout(infoPanel);
infoPanel.setLayout(infoPanelLayout);
infoPanelLayout.setHorizontalGroup(
infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 588, Short.MAX_VALUE)
);
infoPanelLayout.setVerticalGroup(
infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 47, Short.MAX_VALUE)
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@ -104,9 +165,9 @@ final class AddImageVisualPanel2 extends JPanel {
.addComponent(crDbLabel)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 552, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel5))
.addGap(0, 16, Short.MAX_VALUE))
.addComponent(crDbProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 568, Short.MAX_VALUE)
.addComponent(progressLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 568, Short.MAX_VALUE))
.addGap(0, 36, Short.MAX_VALUE))
.addComponent(crDbProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 588, Short.MAX_VALUE)
.addComponent(infoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
@ -121,16 +182,15 @@ final class AddImageVisualPanel2 extends JPanel {
.addGap(18, 18, 18)
.addComponent(crDbProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(progressLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 12, Short.MAX_VALUE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(infoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(24, 24, 24))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel crDbLabel;
private javax.swing.JProgressBar crDbProgressBar;
private javax.swing.JPanel infoPanel;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel progressLabel;
// End of variables declaration//GEN-END:variables
}

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>

View File

@ -51,7 +51,7 @@ public class AddImageVisualPanel3 extends javax.swing.JPanel {
*/
@Override
public String getName() {
return "Ingest Image";
return "Configure Ingest Modules";
}
/** This method is called from within the constructor to
@ -80,11 +80,11 @@ public class AddImageVisualPanel3 extends javax.swing.JPanel {
configPanel.setLayout(configPanelLayout);
configPanelLayout.setHorizontalGroup(
configPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 596, Short.MAX_VALUE)
.addGap(0, 569, Short.MAX_VALUE)
);
configPanelLayout.setVerticalGroup(
configPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 266, Short.MAX_VALUE)
.addGap(0, 246, Short.MAX_VALUE)
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
@ -97,8 +97,8 @@ public class AddImageVisualPanel3 extends javax.swing.JPanel {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(subtitleLabel)))
.addContainerGap(159, Short.MAX_VALUE))
.addComponent(configPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 596, Short.MAX_VALUE)
.addContainerGap(132, Short.MAX_VALUE))
.addComponent(configPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -107,7 +107,7 @@ public class AddImageVisualPanel3 extends javax.swing.JPanel {
.addGap(5, 5, 5)
.addComponent(subtitleLabel)
.addGap(18, 18, 18)
.addComponent(configPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 266, Short.MAX_VALUE))
.addComponent(configPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
@ -22,6 +22,7 @@
<Component id="crDbLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="0" min="-2" pref="549" max="-2" attributes="0"/>
<Component id="addImgButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
@ -34,9 +35,11 @@
<Component id="crDbLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="addImgButton" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="31" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -69,5 +72,12 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel4.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -43,7 +43,7 @@ final class AddImageVisualPanel4 extends JPanel {
*/
@Override
public String getName() {
return "Done";
return "Finish";
}
/** This method is called from within the constructor to
@ -57,6 +57,7 @@ final class AddImageVisualPanel4 extends JPanel {
addImgButton = new javax.swing.JButton();
crDbLabel = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
org.openide.awt.Mnemonics.setLocalizedText(addImgButton, org.openide.util.NbBundle.getMessage(AddImageVisualPanel4.class, "AddImageVisualPanel4.addImgButton.text")); // NOI18N
addImgButton.addActionListener(new java.awt.event.ActionListener() {
@ -65,11 +66,13 @@ final class AddImageVisualPanel4 extends JPanel {
}
});
crDbLabel.setFont(new java.awt.Font("Tahoma", 1, 14));
crDbLabel.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(crDbLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel4.class, "AddImageVisualPanel4.crDbLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AddImageVisualPanel4.class, "AddImageVisualPanel4.jLabel1.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(AddImageVisualPanel4.class, "AddImageVisualPanel4.jLabel2.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@ -79,7 +82,8 @@ final class AddImageVisualPanel4 extends JPanel {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(crDbLabel)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 549, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(addImgButton))
.addComponent(addImgButton)
.addComponent(jLabel2))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
@ -89,9 +93,11 @@ final class AddImageVisualPanel4 extends JPanel {
.addComponent(crDbLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel2)
.addGap(18, 18, 18)
.addComponent(addImgButton)
.addContainerGap(31, Short.MAX_VALUE))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
@ -110,5 +116,6 @@ final class AddImageVisualPanel4 extends JPanel {
private javax.swing.JButton addImgButton;
private javax.swing.JLabel crDbLabel;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
// End of variables declaration//GEN-END:variables
}

View File

@ -22,20 +22,17 @@ package org.sleuthkit.autopsy.casemodule;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JCheckBox;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.coreutils.AutopsyPropFile;
import org.sleuthkit.autopsy.coreutils.Log;
/**
* The "Add Image" wizard panel1 handling the logic of selecting image file(s)
@ -211,19 +208,17 @@ class AddImageWizardPanel1 implements WizardDescriptor.Panel<WizardDescriptor>,
*/
@Override
public void storeSettings(WizardDescriptor settings) {
settings.putProperty(AddImageAction.IMGPATHS_PROP, getComponent().getImagePaths());
settings.putProperty(AddImageAction.IMGPATH_PROP, getComponent().getImagePath());
settings.putProperty(AddImageAction.TIMEZONE_PROP, getComponent().getSelectedTimezone()); // store the timezone
settings.putProperty(AddImageAction.NOFATORPHANS_PROP, Boolean.valueOf(getComponent().getNoFatOrphans()));
//settings.putProperty(AddImageAction.LOOKUPFILES_PROP, getComponent().getLookupFilesCheckboxChecked());
//settings.putProperty(AddImageAction.SOLR_PROP, getComponent().getIndexImageCheckboxChecked());
// Store the path to the first image selected into the properties file
if(getComponent().getImagePaths().length > 0){
String firstImage = getComponent().getImagePaths()[0];
String firstImagePath = firstImage.substring(0, firstImage.lastIndexOf(File.separator)+1);
String firstImage = getComponent().getImagePath();
String firstImagePath = firstImage.substring(0, firstImage.lastIndexOf(File.separator) + 1);
AutopsyPropFile.getInstance().setProperty(PROP_LASTIMAGE, firstImagePath);
}
}
/**

View File

@ -50,7 +50,7 @@ import org.sleuthkit.datamodel.TskException;
class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
// the paths of the image files to be added
private String[] imgPaths;
private String imgPath;
// the time zone where the image is added
private String timeZone;
//whether to not process FAT filesystem orphans
@ -166,8 +166,8 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
}
/**
* This method is auto-generated. It seems that this method is used to listen
* to any change in this wizard panel.
* This method is auto-generated. It seems that this method is used to
* listen to any change in this wizard panel.
*/
protected final void fireChangeEvent() {
Iterator<ChangeListener> it;
@ -190,11 +190,11 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
public void readSettings(WizardDescriptor settings) {
cleanupImage = null;
imgAdded = false;
imgPaths = (String[]) settings.getProperty(AddImageAction.IMGPATHS_PROP);
imgPath = (String) settings.getProperty(AddImageAction.IMGPATH_PROP);
timeZone = settings.getProperty(AddImageAction.TIMEZONE_PROP).toString();
noFatOrphans = ((Boolean) settings.getProperty(AddImageAction.NOFATORPHANS_PROP)).booleanValue();
component.changeProgressBarTextAndColor("", 0, Color.black);
getComponent().resetInfoPanel();
startAddImage();
}
@ -213,6 +213,8 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
// be cancelled if all goes well, and availble if we return to this
// panel so the the previously added image can be reverted
settings.putProperty(AddImageAction.IMAGECLEANUPTASK_PROP, cleanupImage);
getComponent().resetInfoPanel();
}
/**
@ -246,7 +248,6 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
// Add a cleanup task to interupt the backgroud process if the
// wizard exits while the background process is running.
AddImageAction.CleanupTask cancelledWhileRunning = action.new CleanupTask() {
@Override
void cleanup() throws Exception {
logger.log(Level.INFO, "Add image process interrupted.");
@ -259,7 +260,6 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
//lock DB for writes in EWT thread
//wait until lock acquired in EWT
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
SleuthkitCase.dbWriteLock();
@ -278,14 +278,14 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
process = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans);
cancelledWhileRunning.enable();
try {
process.run(imgPaths);
process.run(new String[]{imgPath});
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Errors occurred while running add image. ", ex);
logger.log(Level.WARNING, "Core errors occurred while running add image. ", ex);
//critical core/system error and process needs to be interrupted
hasCritError = true;
errorString = ex.getMessage();
} catch (TskDataException ex) {
logger.log(Level.WARNING, "Errors occurred while running add image. ", ex);
logger.log(Level.WARNING, "Data errors occurred while running add image. ", ex);
errorString = ex.getMessage();
} finally {
// process is over, doesn't need to be dealt with if cancel happens
@ -317,15 +317,14 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
logger.log(Level.INFO, "Handling errors or interruption that occured in add image process");
revert();
if (hasCritError) {
StringBuilder errMsgB = new StringBuilder();
errMsgB.append("<html>*Failed to add image");
if (errorString != null) {
errMsgB.append(": <br />").append(errorString);
}
errMsgB.append("</html>");
getComponent().changeProgressBarTextAndColor(errMsgB.toString(), 0, Color.black);
//core error
getComponent().setErrors(errorString, true);
}
return;
} else if (errorString != null) {
//data error (non-critical)
logger.log(Level.INFO, "Handling non-critical errors that occured in add image process");
getComponent().setErrors(errorString, false);
}
}
@ -344,6 +343,7 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
};
cleanupImage.enable();
if (errorString == null)
getComponent().changeProgressBarTextAndColor("*Image added.", 100, Color.black); // complete progress bar
// Get attention for the process finish

View File

@ -178,7 +178,7 @@ class AddImageWizardPanel3 implements WizardDescriptor.Panel<WizardDescriptor> {
*/
private void commitImage(WizardDescriptor settings) throws Exception {
String[] imgPaths = (String[]) settings.getProperty(AddImageAction.IMGPATHS_PROP);
String imgPath = (String) settings.getProperty(AddImageAction.IMGPATH_PROP);
String timezone = settings.getProperty(AddImageAction.TIMEZONE_PROP).toString();
settings.putProperty(AddImageAction.IMAGEID_PROP, "");
SleuthkitJNI.CaseDbHandle.AddImageProcess process = (SleuthkitJNI.CaseDbHandle.AddImageProcess) settings.getProperty(AddImageAction.PROCESS_PROP);
@ -196,7 +196,7 @@ class AddImageWizardPanel3 implements WizardDescriptor.Panel<WizardDescriptor> {
SleuthkitCase.dbWriteUnlock();
if (imageId != 0) {
newImage = Case.getCurrentCase().addImage(imgPaths, imageId, timezone);
newImage = Case.getCurrentCase().addImage(imgPath, imageId, timezone);
settings.putProperty(AddImageAction.IMAGEID_PROP, imageId);
}

View File

@ -90,16 +90,9 @@ OpenRecentCasePanel.jLabel1.text=Recent Cases
AddImageVisualPanel1.imgInfoLabel.text=Enter Disk Image Information:
AddImageVisualPanel2.crDbLabel.text=Adding Image
AddImageVisualPanel2.jLabel5.text=Processing Image and Adding to Database :
AddImageVisualPanel2.progressLabel.text=
AddImageVisualPanel2.jLabel1.text=<html> We are now analyzing the disk image to extract volume and file system data and populate a local database. </html>
AddImageVisualPanel1.jLabel1.text=
AddImageVisualPanel1.timeZoneLabel.text=Please select the image timezone:
AddImageVisualPanel1.rawSingle.text=Raw Single (*.img, *.dd, etc)
AddImageVisualPanel1.rawSplit.text=Raw Split (*.001, *.002, *.aa, *.ab, etc)
AddImageVisualPanel1.imgTypeLabel.text=Image Type:
AddImageVisualPanel1.multipleSelectLabel.text=Single Image: Multiple Select Disabled
AddImageVisualPanel1.imgPathTextField.text=
AddImageVisualPanel1.encase.text=EnCase (*.e01, *.e02, etc)
AddImageVisualPanel1.imgPathLabel.text=Image Path:
AddImageVisualPanel1.imgPathBrowserButton.text=Browse
NewJPanel.jLabel1.text=
@ -110,10 +103,10 @@ NewJPanel.jButton1.text=Rename
NewJPanel.jLabel4.text=Database:
AddImageVisualPanel2.indexImageCheckBox.text=Index image for keyword search
AddImageVisualPanel1.jLabel2.text=<html> Press 'Next' to analyze the disk image to extract volume and file system data and populate a local database.</html>
AddImageVisualPanel4.jLabel1.text=Image successfully processed and added to the case. You can add another image or return to the case.
AddImageVisualPanel4.crDbLabel.text=Finish or Add More Images
AddImageVisualPanel4.jLabel1.text=Image was successfully added to the case and is being processed.
AddImageVisualPanel4.crDbLabel.text=Image Added and Being Processed
AddImageVisualPanel4.addImgButton.text=Add Another Image
AddImageVisualPanel3.titleLabel.text=Add image to ingest
AddImageVisualPanel3.titleLabel.text=Configure Ingest Modules
AddImageVisualPanel3.subtitleLabel.text=Image has been commited. You can configure and run ingest modules on the new image.
CasePropertiesForm.caseNumberLabel.text=Case Number:
CasePropertiesForm.examinerLabel.text=Examiner:
@ -127,3 +120,9 @@ NewCaseVisualPanel2.optionalLabel.text=Optional: Set Case Number and Examiner
AddImageVisualPanel1.noFatOrphansCheckbox.toolTipText=
AddImageVisualPanel1.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems
AddImageVisualPanel1.optionsLabel1.text=Options to produce results faster (although some data will not be searched):
AddImageErrorsDialog.title=Add Image Log
AddImageErrorsDialog.copyButton.toolTipText=Copy errors to clipboard
AddImageErrorsDialog.copyButton.text=Copy
AddImageErrorsDialog.closeButton.toolTipText=Close this window
AddImageErrorsDialog.closeButton.text=Close
AddImageVisualPanel4.jLabel2.text=You can add another image or click Finish to return to the case and view results.

View File

@ -44,13 +44,16 @@ import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.SystemAction;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Log;
import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.datamodel.*;
import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess;
/**
* Class to store the case information
* Stores all information for a given case. Only a single case can
* currently be open at a time. Use getCurrentCase() to retrieve the
* object for the current case.
*/
public class Case {
@ -113,6 +116,8 @@ public class Case {
// Track the current case (only set with changeCase() method)
private static Case currentCase = null;
private static final Logger logger = Logger.getLogger(Case.class.getName());
/**
* Constructor for the Case class
*/
@ -242,10 +247,15 @@ public class Case {
}
}
Map<Long, List<String>> getImagePaths() {
Map<Long, List<String>> imgPaths = new HashMap<Long, List<String>>();
static Map<Long, String> getImagePaths(SleuthkitCase db) { //TODO: clean this up
Map<Long, String> imgPaths = new HashMap<Long, String>();
try {
imgPaths = db.getImagePaths();
Map<Long, List<String>> imgPathsList = db.getImagePaths();
for(Map.Entry<Long, List<String>> entry : imgPathsList.entrySet()) {
if(entry.getValue().size() > 0) {
imgPaths.put(entry.getKey(), entry.getValue().get(0));
}
}
} catch (TskException ex) {
Logger.getLogger(Case.class.getName()).log(Level.WARNING, "Error getting image paths", ex);
}
@ -256,55 +266,34 @@ public class Case {
* Ensure that all image paths point to valid image files
*/
private static void checkImagesExist(SleuthkitCase db) {
Map<Long, List<String>> imgPaths = new HashMap<Long, List<String>>();
try {
imgPaths = db.getImagePaths();
} catch (TskException ex) {
Logger.getLogger(Case.class.getName()).log(Level.WARNING, "Error getting image paths", ex);
}
for (Map.Entry<Long, List<String>> entry : imgPaths.entrySet()) {
Map<Long, String> imgPaths = getImagePaths(db);
for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
JFileChooser fc = new JFileChooser();
FileFilter filter;
long obj_id = entry.getKey();
List<String> paths = entry.getValue();
boolean allFilesExist = true;
String pathString = "";
for (String s : paths) {
allFilesExist &= isPhysicalDrive(s) || new File(s).exists();
pathString += s + "\n";
}
if (!allFilesExist) {
File f = new File(paths.get(0));
if (AddImageVisualPanel1.encaseFilter.accept(f)) {
filter = AddImageVisualPanel1.encaseFilter;
} else if (AddImageVisualPanel1.splitFilter.accept(f)) {
filter = AddImageVisualPanel1.splitFilter;
} else {
filter = AddImageVisualPanel1.imgFilter;
}
fc.setMultiSelectionEnabled(true);
String path = entry.getValue();
boolean fileExists = pathExists(path);
if (!fileExists) {
filter = AddImageVisualPanel1.allFilter;
fc.setMultiSelectionEnabled(false);
fc.setFileFilter(filter);
int ret = JOptionPane.showConfirmDialog(null, appName + " has detected that one or more of the images associated with \n"
int ret = JOptionPane.showConfirmDialog(null, appName + " has detected that one of the images associated with \n"
+ "this case are missing. Would you like to search for them now?\n"
+ "Previously, the image(s) were located at:\n" + pathString
+ "Previously, the image was located at:\n" + path
+ "\nPlease note that you will still be able to browse directories and generate reports\n"
+ "if you choose No, but you will not be able to view file content or run the ingest process.", "Missing Images", JOptionPane.YES_NO_OPTION);
+ "if you choose No, but you will not be able to view file content or run the ingest process.", "Missing Image", JOptionPane.YES_NO_OPTION);
if (ret == JOptionPane.YES_OPTION) {
fc.showOpenDialog(null);
if (fc.getSelectedFiles().length == paths.size()) { //TODO: this is the extent of our equality checking...we should do more.
List<String> newPaths = new ArrayList<String>();
for (File newFile : fc.getSelectedFiles()) {
newPaths.add(newFile.getPath());
}
String newPath = fc.getSelectedFile().getPath();
try {
db.setImagePaths(obj_id, newPaths);
db.setImagePaths(obj_id, Arrays.asList(new String[]{newPath}));
} catch (TskException ex) {
Logger.getLogger(Case.class.getName()).log(Level.WARNING, "Error setting image paths", ex);
}
} else {
Logger.getLogger(Case.class.getName()).log(Level.WARNING, "Selected image files don't match old files!");
}
}
}
}
}
@ -316,12 +305,10 @@ public class Case {
* @param imgId the ID of the image that being added
* @param timeZone the timeZone of the image where it's added
*/
Image addImage(String[] imgPaths, long imgId, String timeZone) throws Exception {
Log.get(this.getClass()).log(Level.INFO, "Adding image to Case. imgPaths: {0} ID: {1} TimeZone: {2}", new Object[]{Arrays.toString(imgPaths), imgId, timeZone});
Image addImage(String imgPath, long imgId, String timeZone) throws Exception {
Log.get(this.getClass()).log(Level.INFO, "Adding image to Case. imgPath: {0} ID: {1} TimeZone: {2}", new Object[]{imgPath, imgId, timeZone});
try {
xmlcm.addImage(imgPaths, imgId, timeZone); // add the image to the document handler in the XML class and to the config file
xmlcm.writeFile(); // write any changes to the config file
Image newImage = db.getImageById(imgId);
pcs.firePropertyChange(CASE_ADD_IMAGE, null, newImage); // the new value is the instance of the image
doAddImage();
@ -434,46 +421,6 @@ public class Case {
}
}
// Not dealing with removing images for now.
// /**
// * Removes the image from this case
// *
// * @param givenID the ID of the image to be removed
// * @param givenPath the path of the image to be removed
// */
// void removeImage(int givenID, String givenPath) throws Exception {
// Log.get(this.getClass()).log(Level.FINE, "Removing image.\ngivenID: {0}\ngivenPath: {1}", new Object[] {givenID, givenPath});
//
// String[] tempPaths = xmlcm.getImageSet(givenID);
// String tempDb = xmlcm.getImageSetDbPath(givenID);
//
// if (tempPaths[0].equals(givenPath)) {
// xmlcm.removeImageSet(givenID); // make the changes in the config file
// try {
// xmlcm.writeFile();
// } catch (Exception ex) {
// throw new Exception("Error while trying to remove the image from this case.", ex);
// }
//
// Image img = imageIdToData.get(givenID).image; // save the image that we want to delete temporarily
//
// imageIdToData.remove(givenID);
//
// pcs.firePropertyChange(CASE_DEL_IMAGE, givenID, img); // the old value is the image ID that removed, the new value is the instance of the image
//
// img.getSleuthkit().closeConnection(); // to make sure that we close the connection
//
// // need to remove the database as well??
// File database = new File(tempDb);
// boolean test = database.delete(); // delete the database of the image that we remove
// if (!test) {
// database.deleteOnExit(); // delete on exit if the delete is not successful
// }
// } else {
// // throw an error here
// Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Couldn't remove image.", new Exception("Couldn't find the image in this case."));
// }
// }
/**
* Checks whether there is a current case open.
*
@ -597,9 +544,8 @@ public class Case {
return pcs;
}
String[] getImagePaths(Long imgID) {
List<String> paths = getImagePaths().get(imgID);
return paths.toArray(new String[paths.size()]);
String getImagePaths(Long imgID) {
return getImagePaths(db).get(imgID);
}
/**
@ -607,7 +553,7 @@ public class Case {
* @return imageIDs
*/
public Long[] getImageIDs() {
Set<Long> ids = getImagePaths().keySet();
Set<Long> ids = getImagePaths(db).keySet();
return ids.toArray(new Long[ids.size()]);
}
@ -637,12 +583,16 @@ public class Case {
* @return time zones the set of time zones
*/
public Set<TimeZone> getTimeZone() {
if (xmlcm == null) {
return new HashSet<TimeZone>();
} else {
return xmlcm.getTimeZone();
Set<TimeZone> timezones = new HashSet<TimeZone>();
for(Content c : getRootObjects()) {
try {
timezones.add(TimeZone.getTimeZone(c.getImage().getTimeZone()));
} catch (TskException ex) {
Logger.getLogger(Case.class.getName()).log(Level.INFO, "Error getting time zones", ex);
}
}
return timezones;
}
public static synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
@ -653,73 +603,22 @@ public class Case {
}
/**
* convert the image Path to array string
* Check if image from the given image path exists.
* @param imgPath the image path
* @return imgPath the converted image path
* @return isExist whether the path exists
*/
public static String[] convertImgPath(String imgPath) {
String[] result;
String unsplitPaths = imgPath;
int count = 0;
for (int i = 0; i < unsplitPaths.length(); i++) {
if (unsplitPaths.charAt(i) == '\"') {
count++;
}
}
if (count != 0) {
result = new String[count / 2];
int start = 0;
int current = 0;
for (int i = 0; i < count / 2; i++) {
while (unsplitPaths.charAt(current) != '\"') {
current++;
}
start = current;
current++;
while (unsplitPaths.charAt(current) != '\"') {
current++;
}
result[i] = unsplitPaths.substring(start + 1, current);
current++;
}
} else {
result = new String[1];
result[0] = unsplitPaths;
}
return result;
}
/**
* Check if all the images from the given image path exist.
* @param imgPaths the image paths
* @return isExist whether the multiple paths exist
*/
public static boolean checkMultiplePathExist(String[] imgPaths) {
boolean result = false;
int totalLength = imgPaths.length;
if (totalLength > 0) {
result = true;
for (int i = 0; i < totalLength; i++) {
String path = imgPaths[i];
if (!new File(path).exists() && !isPhysicalDrive(path)) {
result = false;
break;
}
}
}
return result;
public static boolean pathExists(String imgPath) {
return new File(imgPath).isFile();
}
/**
* Does the given string refer to a physical drive?
*/
private static String pdisk = "\\\\.\\physicaldrive";
private static final String pdisk = "\\\\.\\physicaldrive";
private static final String dev = "/dev/";
static boolean isPhysicalDrive(String path) {
int endIndex = Math.min(path.length(), pdisk.length());
return path.substring(0, endIndex).toLowerCase().equals(pdisk);
return path.toLowerCase().startsWith(pdisk) ||
path.toLowerCase().startsWith(dev);
}
/**
@ -787,17 +686,8 @@ public class Case {
* @return boolean whether the case directory is successfully deleted or not
*/
static boolean deleteCaseDirectory(File casePath) {
if (casePath.exists()) {
File[] files = casePath.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteCaseDirectory(files[i]);
} else {
files[i].delete();
}
}
}
return (casePath.delete());
logger.log(Level.INFO, "Deleting case directory: " + casePath.getAbsolutePath());
return FileUtil.deleteDir(casePath);
}
/**

View File

@ -23,6 +23,7 @@ import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
@ -43,7 +44,7 @@ public final class CaseOpenAction implements ActionListener {
AutopsyPropFile AutopsyProperties = AutopsyPropFile.getInstance();
JFileChooser fc = new JFileChooser();
GeneralFilter autFilter = new GeneralFilter(new String[]{".aut"}, "AUTOPSY File (*.aut)", false);
GeneralFilter autFilter = new GeneralFilter(Collections.<String>singletonList(".aut"), "AUTOPSY File (*.aut)");
/** The constructor */
public CaseOpenAction() {

View File

@ -77,7 +77,7 @@ public final class CasePropertiesAction extends CallableSystemAction {
int totalImage = currentCase.getRootObjectsCount();
// put the image paths information into hashmap
Map<Long, List<String>> imgPaths = currentCase.getImagePaths();
Map<Long, String> imgPaths = currentCase.getImagePaths(currentCase.getSleuthkitCase());
// create the case properties form
CasePropertiesForm cpf = new CasePropertiesForm(currentCase, crDate, caseDir, imgPaths);

View File

@ -76,7 +76,7 @@ class CasePropertiesForm extends javax.swing.JPanel{
/** Creates new form CasePropertiesForm */
CasePropertiesForm(Case currentCase, String crDate, String caseDir, Map<Long, List<String>> imgPaths) {
CasePropertiesForm(Case currentCase, String crDate, String caseDir, Map<Long, String> imgPaths) {
initComponents();
caseNameTextField.setText(currentCase.getName());
caseNumberTextField.setText(currentCase.getNumber());
@ -94,7 +94,7 @@ class CasePropertiesForm extends javax.swing.JPanel{
int i = 0;
for(long key : imgPaths.keySet()){
String path = imgPaths.get(key).get(0);
String path = imgPaths.get(key);
String shortenPath = shrinkPath(path, 70);
rows[i++] = new String[]{shortenPath};
}

View File

@ -20,7 +20,7 @@
package org.sleuthkit.autopsy.casemodule;
import java.io.File;
import java.util.regex.Pattern;
import java.util.List;
import javax.swing.filechooser.FileFilter;
/**
@ -28,14 +28,12 @@ import javax.swing.filechooser.FileFilter;
*/
public class GeneralFilter extends FileFilter{
String[] ext;
List<String> extensions;
String desc;
boolean isMultiple; // whether the filter can accept multiple files.
public GeneralFilter(String[] ext, String desc, boolean isMultiple){
this.ext = ext;
public GeneralFilter(List<String> ext, String desc){
this.extensions = ext;
this.desc = desc;
this.isMultiple = isMultiple;
}
/**
@ -48,22 +46,12 @@ public class GeneralFilter extends FileFilter{
public boolean accept(File f) {
if(f.isDirectory()){
return true;
}
else{
} else {
Boolean result = false;
String name = f.getName().toLowerCase();
if(isMultiple){
for(int i = 0; i < ext.length; i++){
String regex = ext[i];
if (Pattern.matches(regex, name)){
result = result || true;
}
}
}
else{
for(int i = 0; i < ext.length; i++){
if (name.endsWith(ext[i]))
for (String ext : extensions) {
if (name.endsWith(ext)) {
result = result || true;
}
}

View File

@ -50,7 +50,7 @@ public interface IngestConfigurator {
/**
* find out if ingest is currently running
*
* @param true if ingest process is running
* @return true if ingest process is running, false otherwise
*/
boolean isIngestRunning();

View File

@ -42,6 +42,8 @@ public final class NewCaseWizardAction extends CallableSystemAction {
private WizardDescriptor.Panel<WizardDescriptor>[] panels;
private static final Logger logger = Logger.getLogger(NewCaseWizardAction.class.getName());
@Override
public void performAction() {
Log.noteAction(this.getClass());
@ -92,8 +94,10 @@ public final class NewCaseWizardAction extends CallableSystemAction {
// if Cancel button is pressed
if (isCancelled) {
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory");
if(createdDirectory != null)
if(createdDirectory != null) {
logger.log(Level.INFO, "Deleting a created case directory due to isCancelled set, dir: " + createdDirectory);
Case.deleteCaseDirectory(new File(createdDirectory));
}
// if there's case opened, close the case
if (Case.existsCurrentCase()) {
// close the previous case if there's any

View File

@ -169,8 +169,9 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
NewCaseVisualPanel1 component = getComponent();
String lastBaseDirectory = AutopsyPropFile.getInstance().getProperty(PROP_BASECASE);
component.getCaseParentDirTextField().setText(lastBaseDirectory);
String createdDirectory = (String) settings.getProperty("createdDirectory");
createdDirectory = (String) settings.getProperty("createdDirectory");
if(createdDirectory != null && !createdDirectory.equals("")) {
logger.log(Level.INFO, "Deleting a case dir in readSettings(): " + createdDirectory);
Case.deleteCaseDirectory(new File(createdDirectory));
}
}

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>

View File

@ -42,6 +42,12 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
private OpenRecentCasePanel() {
initComponents();
}
/**
* Retrieves all the recent cases and adds them to the table.
*/
private void generateRecentCases() {
caseName = RecentCases.getInstance().getRecentCaseNames();
casePaths = RecentCases.getInstance().getRecentCasePaths();
@ -118,6 +124,7 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
if (instance == null) {
instance = new OpenRecentCasePanel();
}
instance.generateRecentCases(); // refresh the case list
return instance;
}

View File

@ -59,19 +59,6 @@ public class XMLCaseManagement implements CaseConfigFileInterface{
final static String AUTOPSY_CRVERSION_NAME = "AutopsyCreatedVersion";
final static String AUTOPSY_MVERSION_NAME = "AutopsySavedVersion";
// disk image paths
final static String IMAGES_NAME = "Images";
final static String IMG_SET_NAME = "ImgSet";
final static String IMG_PATH_NAME = "ImgPath";
final static String IMG_DB_NAME = "ImgDb";
final static String NEXT_ID_NAME = "NextID";
// image attribute
final static String IMG_SET_COUNT = "count";
final static String IMG_SET_ID = "id";
final static String IMG_PATH_ID = "idx";
final static String TIMEZONE = "timezone";
// folders inside case directory
final static String LOG_FOLDER_NAME = "LogFolder";
final static String LOG_FOLDER_RELPATH = "Log";
@ -473,202 +460,14 @@ public class XMLCaseManagement implements CaseConfigFileInterface{
}
}
/**
* Gets image Element from the document handler
*
* @return imageElement the "Image" element
*/
private Element getImagesElement(){
if(doc != null){
return (Element) doc.getElementsByTagName(IMAGES_NAME).item(0);
}
else{
return null; // should throw error or exception
}
}
//
// /**
// * Looks up for the Image Set Element in the document handler with the given
// * image ID.
// *
// * @param id the image ID
// * @return element the "ImageSet" element
// */
// protected Element getImageSetElement(int id){
// if(doc != null){
// Element result = null;
// int totalImageSet = getImageSetCount();
//
// for(int i = 0; i < totalImageSet; i++){
// Element imageSetElement = (Element)getImagesElement().getElementsByTagName(IMG_SET_NAME).item(i);
// int imgSetID = Integer.parseInt(imageSetElement.getAttribute(IMG_SET_ID));
// if(id == imgSetID){
// result = imageSetElement;
// }
// }
// return result;
// }
// else{
// return null; //TODO: should throw error or exception
// }
// }
//
// /**
// * Sets the ImgDb entry for corresponding image set in the document handler
// *
// * @param id the image ID
// * @param path the image path
// */
// protected void setImageSetDbPath(int id, String path){
// Element imgDbElement = (Element) getImageSetElement(id).getElementsByTagName(IMG_DB_NAME).item(0);
// imgDbElement.setTextContent(path);
// imgDbElement.setAttribute(RELATIVE_NAME, RELATIVE_TRUE); // depends on the path (relative or not)
//
// // if need to write the XML file immidiately, uncomment the code below
// // writeFile();
// }
//
/**
* Returns number of image sets in this case
*
* @return imageSetCount total number of imageSet in this case
*/
protected int getImageSetCount(){
return getImagesElement().getElementsByTagName(IMG_SET_NAME).getLength();
}
//
// /**
// * Returns a set of image paths of the given image ID in this case
// *
// * @param id the image ID
// * @return imagePaths the image paths of the given imageID
// */
// protected String[] getImageSet(int id){
// Element imgSetElement = getImageSetElement(id);
// int totalImagePaths = imgSetElement.getElementsByTagName(IMG_PATH_NAME).getLength(); // or use the attribute count
// String[] result = new String[totalImagePaths];
//
// for(int i = 0; i < totalImagePaths; i++){
// Element imgPathElement = (Element) imgSetElement.getElementsByTagName(IMG_PATH_NAME).item(i);
// if(imgPathElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)){
// result[i] = caseDirPath + File.separator + imgPathElement.getTextContent();
// }
// else{
// result[i] = imgPathElement.getTextContent();
// }
// }
// return result;
// }
//
// /**
// * Returns absolute path of image database of the given image ID.
// *
// * @param id the image ID
// * @return dbPath the database path of the given image
// */
// protected String getImageSetDbPath(int id){
// Element imgDbElement = (Element) getImageSetElement(id).getElementsByTagName(IMG_DB_NAME).item(0);
// if(imgDbElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)){
// return caseDirPath + File.separator + imgDbElement.getTextContent();
// }
// else{
// return imgDbElement.getTextContent();
// }
// }
//
// /**
// * Gets the next free image ID and and increments the internal counter
// *
// * @return imageID the next free image ID
// */
// @Override
// public int getNextImageID(){
// Element imgElement = getImagesElement();
// if(imgElement == null){
// return -1; // which indicates the error
// }
// else{
// String nextID = imgElement.getAttribute(NEXT_ID_NAME);
// int result = Integer.parseInt(nextID);
//
// // increment the nextID
// int incNextID = result + 1;
// getImagesElement().setAttribute(NEXT_ID_NAME, Integer.toString(incNextID));
//
// // write the change to the config file immediately
// try{
// writeFile();
// }
// catch(Exception ex){
// // TODO: throw exception further up
// Logger logger = Logger.getLogger(this.className);
// logger.log(Level.WARNING, "Error while trying to write the new NextID to the config file.", ex);
// }
//
// return result;
// }
// }
//
// /**
// * Returns an array of all image ID values in this case.
// *
// * @return imageIDs array of all image IDs in this case
// */
// @Override
// public int[] getImageIDs() {
// int totalImageSet = getImageSetCount();
// int[] result = new int[totalImageSet];
//
// Element imgElement = getImagesElement();
// for(int i = 0; i < totalImageSet; i++){
// Element imgSetElement = (Element)imgElement.getElementsByTagName(IMG_SET_NAME).item(i);
// result[i] = Integer.parseInt(imgSetElement.getAttribute(IMG_SET_ID));
// }
//
// return result;
// }
//
// /**
// * Returns the HashSet of all timezone values of all images in this case.
// *
// * @return imageIDs the HashSet of all timezone values
// */
public HashSet<TimeZone> getTimeZone() {
HashSet<TimeZone> result = new HashSet<TimeZone>();
int totalImageSet = getImageSetCount();
Element imgElement = getImagesElement();
for(int i = 0; i < totalImageSet; i++){
Element imgSetElement = (Element)imgElement.getElementsByTagName(IMG_SET_NAME).item(i);
result.add(TimeZone.getTimeZone(imgSetElement.getAttribute(TIMEZONE)));
}
return result; //TODO: get time zones from db
}
//
// /**
// * Removes the imageSet of the given image ID.
// *
// * @param imgID the image ID of the image that going to be removed
// */
// public void removeImageSet(int imgID) {
// Element imgElement = getImagesElement();
// Element selectedElement = getImageSetElement(imgID);
// imgElement.removeChild(selectedElement); // remove the imagesetElement
// doc.normalize();
//
// // edit the modified data
// String newDate = dateFormat.format(new Date());
// Element rootEl = getRootElement();
// rootEl.getElementsByTagName(MODIFIED_DATE_NAME).item(0).setTextContent(newDate);
// }
/**
* Initialize the basic values for a new case management file.
* Note: this is the schema version 1.0
*
* @param parentPath the name of the parent of the case directory.
* @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
*/
protected void create(String dirPath, String caseName, String examiner, String caseNumber) throws Exception {
clear(); // clear the previous data
@ -748,11 +547,6 @@ public class XMLCaseManagement implements CaseConfigFileInterface{
cacheElement.setAttribute(RELATIVE_NAME, "true");
caseElement.appendChild(cacheElement);
// create the new images
Element imagesElement = doc.createElement(IMAGES_NAME); // <Images> ... </Images>
imagesElement.setAttribute(NEXT_ID_NAME, Integer.toString(0)); // add nextID to 0
rootElement.appendChild(imagesElement);
// write more code if needed ...
}
@ -894,56 +688,4 @@ public class XMLCaseManagement implements CaseConfigFileInterface{
examiner = "";
}
/**
* Adds the image to the current document handler.
*
* @param images the paths of the images that want to be added
* @param currentID the ID of the image that want to be added
* @param timeZone the timeZone where the image is added
*/
protected void addImage(String[] images, long currentID, String timeZone) throws Exception {
//String dbName = "image-" + currentID + ".db";
if (doc == null) {
throw new Exception("No case open.");
} else {
Element rootEl = getRootElement();
int imgCount = images.length; // how many given images to add to the config file
Element imagesElement = getImagesElement();
//int currentID = Integer.parseInt(imagesElement.getAttribute(NEXT_ID_NAME));
// add the latest image set
Element imgSetElement = doc.createElement(IMG_SET_NAME); // <ImgSet> ... </ImgSet>
imgSetElement.setAttribute(IMG_SET_COUNT, Integer.toString(imgCount));
imgSetElement.setAttribute(IMG_SET_ID, Long.toString(currentID));
imgSetElement.setAttribute(TIMEZONE, timeZone);
imagesElement.appendChild(imgSetElement);
// add all the image Path
// for (int i = 0; i < imgCount; i++) {
// Element imgPathElement = doc.createElement(IMG_PATH_NAME); // <ImgPath> ... </ImgPath>
// imgPathElement.setAttribute(IMG_PATH_ID, Integer.toString(i));
// imgPathElement.setAttribute(RELATIVE_NAME, "false");
// imgPathElement.appendChild(doc.createTextNode(images[i]));
// imgSetElement.appendChild(imgPathElement);
// }
//
// // add the database
// Element imgDbElement = doc.createElement(IMG_DB_NAME); // <ImgDb> ... </ImgDb>
// imgDbElement.setAttribute(RELATIVE_NAME, "true");
// imgDbElement.appendChild(doc.createTextNode(dbName));
// //imgDbElement.appendChild(doc.createTextNode("image-" + currentID + ".db"));
// imgSetElement.appendChild(imgDbElement);
// edit the modified data
String newDate = dateFormat.format(new Date());
rootEl.getElementsByTagName(MODIFIED_DATE_NAME).item(0).setTextContent(newDate);
}
// JOptionPane.showMessageDialog(caller, "Error while trying to add the image to XML config file.\n \nDetail: \n" + e.getMessage() + " (at " + className + ").", "Error", JOptionPane.ERROR_MESSAGE);
}
}

View File

@ -0,0 +1,61 @@
// @@@ VERIFY THAT we mention add case wizard in here
/**
\package org.sleuthkit.autopsy.casemodule
The org.sleuthkit.autopsy.casemodule Module is responsible for organizing a case. A case contains one or more disk images and is the highest-level unit of an investigation.
\section casemodule_contents Package Contents
The important classes in this case are:
- Case
\section casemodule_overview Overview
All data in a case will be stored in a single database and configuration file. A case must be open before analysis can occur. You will use a Case object to get access to the data being analyzed.
Case settings are stored in an XML file. See the XMLCaseManagement class for more details.
Currently, only one case can be opened at a time. To determine the open case, use the Case.getCurrentCase() method.
Do not cache the case handle object obtained from this method (for example, in member variables) unless you are sure your are acting within case context;
It is safer to call the method more frequently to ensure the validity of the case handle object as new cases are opened.
Once you have the object for the currently open case, Case.getRootObjects() will return the top-level Sleuth Kit Content modules. You can then get their children to go down the tree of data types.
\section casemodule_events Case Events
To receive an event when cases are opened, closed, or changed, use the Case.addPropertyChangeListener(PropertyChangeListener) method to register your class as a PropertyChangeListener. This is most commonly required when developing a new module that needs to get data about the currently opened case.
\section casemodule_add_image Add Image Process
The sleuthkit library performs most the actual work of adding the image to the database and Autopsy provides the user interface, calls methods to set up and control and finalize the process.
Add image process is first invoked by AddImageAction.
AddImageWizardIterator instantiates and manages the wizard panels.
A background worker thread is spawned in AddImgTask class. The work is delegated to org.sleuthkit.datamodel.AddImageProcess, which calls into native sleuthkit methods via SleuthkitJNI interface.
The entire process is enclosed within a database transaction and the transaction is not committed until user finalizes the process.
User can also interrupt the ongoing add image process, which results in a special stop call in sleuthkit. The stop call sets a special stop flag internally in sleuthkit.
The flag is checked by the sleutkit code as it is processing the image and,
if set, it will result in breaking out of any current processing loops and methods, and return from sleuthkit.
The worker thread in Autopsy will terminate and revert will be called to back out of the current transaction.
During add image process, sleuthkit library reads the image and populates the TSK SQLite database with the image meta-data.
The resulting database will have the TSK schema (http://wiki.sleuthkit.org/index.php?title=SQLite_Database_v2_Schema).
After image has been processed successfully and after the user confirmation, the transaction is committed to the database.
Errors from processing the image in sleuthkit are propagated using org.sleuthkit.datamodel.TskCoreException and org.sleuthkit.datamodel.TskDataException java exceptions.
The errors are logged and can be reviewed by the user from the wizard.
org.sleuthkit.datamodel.TskCoreException is handled by the wizard as a critical, unrecoverable error condition with TSK core, resulting in the interruption of the add image process.
org.sleuthkit.datamodel.TskDataException, pertaining to an error associated with the data itself (such as invalid volume offset), is treated as a warning - the process still continues because there are likely data image that can be still read.
\section casemodule_concurrency Concurrency and locking
Autopsy is a multi-threaded application; besides threads associated with the GUI, event dispatching and Netbeans RCP framework,
the application uses threads to support concurrent user-driven processes.
For instance, user can add another image to the database while ingest is running on previously added images.
During the add image process, a database lock is acquired using org.sleuthkit.datamodel.SleuthkitCase.dbWriteLock() to ensure exclusive access to the database resource.
Once the lock is acquired by the add image process, other Autopsy threads trying to access the database as acquire the lock (such as ingest modules) will block for the duration of add image process.
The database lock is implemented with SQLite database in mind, which does not support concurrent writes. The database lock is released with org.sleuthkit.datamodel.SleuthkitCase.dbWriteUnlock() when the add image process has ended. The database lock is used for all database access methods in org.sleuthkit.datamodel.SleuthkitCase.
*/

View File

@ -1,10 +0,0 @@
<body>
<p>A case contains one or more disk images and is the highest-level unit of an investigation. All data in a case will be stored in a single database and configuration file. A case must be open before analysis can occur. You will use a {@link org.sleuthkit.autopsy.casemodule.Case#Case Case} object to get access to the data being analyzed.</p>
<p>Case settings are stored in an XML file. See the {@link org.sleuthkit.autopsy.casemodule.XMLCaseManagement#XMLCaseManagement() XMLCaseManagement} class for more details.</p>
<p>Currently, only one case can be opened at a time. To determine the open case, use the static {@link org.sleuthkit.autopsy.casemodule.Case#getCurrentCase() Case.getCurrentCase()} method. Once you have the object for the currently open case, {@link org.sleuthkit.autopsy.casemodule.Case#getRootObjects() Case.getRootObjects()} will return the top-level Sleuth Kit Content modules. You can then get their children to go down the tree of data types. </p>
<p>To receive an event when cases are opened, closed, or changed, use the {@link org.sleuthkit.autopsy.casemodule.Case#addPropertyChangeListener(PropertyChangeListener) addPropertyChangeListener} method to register your class as a PropertyChangeListener. THis is most commonly required when developing a new {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer#DataExplorer() DataExplorer} module that needs to get data about the currently opened case. </p>
</body>

View File

@ -71,11 +71,15 @@ public interface DataContentViewer {
/**
* Checks whether the given viewer is preferred for the Node
*
* @param node Node to check for preference
* @param isSupported, true if the viewer is supported by the node
* @param isSupported true if the viewer is supported by the node, false otherwise
* as determined by a previous check
* @return True if viewer preferred, else false
* @return an int (0-10) higher return means the viewer has higher priority
* 0 means not supported
* 1/2 means will display all supported
* 3-10 are prioritized by Content viewer developer
*/
public boolean isPreferred(Node node, boolean isSupported);
public int isPreferred(Node node, boolean isSupported);
}

View File

@ -0,0 +1,93 @@
/**
* \package org.sleuthkit.autopsy.corecomponentinterfaces
* This package contains the interface classes that define the core components in Autopsy. These components are used in the difference zones of the GUI.
*
<em>NOTE: Much of this data may be out of date. It has not been updated
since a major redesign was done. </em>
\section corecomponentinterface_contents Package Contents
The following are imporant classes in this package
- TODO
* <h2>Autopsy Zones</h2>
* There are three major zones in the Autopsy UI. The left hand side has the org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer zone. This area is where you can search for and explore data. It has all of the analysis smarts. An example of a DataExplorer is the directory tree that shows the hierarchy of directories (and hides the files from view).
* The DataExplorer area identifies a subset of the data to show the user and passes the data to the org.sleuthkit.autopsy.corecomponentinterfaces.DataResult area in the upper right. In the previous example, the contents of a specific folder would be passed to this area and displayed in a table or thumbnail form.</p>
* When a file or object is selected in the DataResult, it is passed to the org.sleuthkit.autopsy.corecomponentinterfaces.DataContent zone in the lower right. This is where file content can be viewed in hex form, strings, etc.
* <h2>Data Flow</h2>
* <h3>Creating Nodes in DataExplorer</h3>
* Data flows between the areas inside of a NetBeans node. The DataExplorer modules create the NetBeans nodes. They query the SQLite database or do whatever they want to identify the set of files that are of interest. They create the NetBeans nodes based on Sleuthkit data model objects. See the org.sleuthkit.autopsy.datamodel package for more details on this.
* <h3>Getting Nodes to DataResult</h3>
* Each DataExplorer TopComponent is responsible for creating its own DataResult TopComponent to display its results. It can choose to re-use the same TopComponent for multiple searches (as DirectoryTree does) or it can choose to make a new one each time (as FileSearch does). The setNode() method on the DataResult object is used to set the root node to display. A dummy root node must be created as the parent if a parent does not already exist.
* The DataExplorer is responsible for setting the double-click and right-click actions associated with the node. The default single click action is to pass data to DataContent. To override this, you must create a new DataResultViewer instance that overrides the propertyChange() method. The DataExplorer adds actions to wrapping the node in a FilterNode variant. The FilterNode then defines the actions for the node by overriding the getPreferredAction() and getActions() methods. As an example, org.sleuthkit.autopsy.directorytree.DataResultFilterNode and org.sleuthkit.autopsy.directorytree.DataResultFilterChildren wraps the nodes that are passed over by the DirectoryTree DataExplorer.
* DataResult can send data back to its DataExplorer by making a custom action that looks up it's instance (DataExplorer.getInstance()).
* <h3>Getting Nodes to DataContent </h3>
* A default DataContent viewer is created when a case is opened. To display the contents of a node, it must be passed to a DataContent instance. The default single-click behavior of the DataResultViewers is to lookup the default DataContent TopComponent and pass the selected node to it. See org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer.propertyChange(PropertyChangeEvent) for details.
* <h2>Creating new Functionality</h2>
* <h3>Creating a DataExplorer</h3>
* <ol>
* <li>Create a module from within NetBeans. It must be dependent on these modules:
* <ul>
* <li>Case
* <li>CoreComponentInterfaces
* <li>CoreComponents
* <li>DataModel
* <li>DialogsAPI (if pop-ups and such are going to be used)
* <li>Explorer & Property Sheet API
* <li>Lookup
* <li>Nodes API
* <li>Setting API
* <li>UI Utilities API
* <li>Utilities API
* <li>Window System API
* </ul>
* <li> Create a class that implements org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer. We have been making the TopComponent class be the one that implements DataExplorer. Register this class as a DataExplorer service provider by specifying "@ServiceProvider(service=DataExplorer.class)" in the class or using layer.xml.
* <li>Implement the methods required by the DataExplorer interface.
* <li>Register the class to receive property change events from the org.sleuthkit.autopsy.Case module by using its addPropertyChangeListener() method.
* <li>Access case data using the org.sleuthkit.autopsy.Case module.
* <li>Create Nodes for the data objects using the techniques outlined in the previous section.
* <li>Wrap the nodes in FilterNodes to define actions as outlined in the previous section.
* <li>Send results to DataResults using the techniques outlined in the previous section.
* </ol>
* <h3>Creating a DataResultViewer</h3>
* <p>DataResultTopComponent is the high-level window in the DataResult area. Each instance of this loads up all instances of DataResultViewers that have been registered with the system. Example viewers include the table and thumbnail views. If you want to make your own type of viewer, follow the steps below. Note that the table and thumbnail viewers come with Autopsy by default and can be used by all DataExplorers.
* <ol>
* <li>Create a module from within NetBeans. It must be dependent on these modules:
* <ul>
* <li>Case
* <li>CoreComponentInterfaces
* <li>CoreComponents
* <li>DataModel
* <li>DialogsAPI (if pop-ups and such are going to be used)
* <li>Explorer & Property Sheet API
* <li>Lookup
* <li>Nodes API
* <li>Setting API
* <li>UI Utilities API
* <li>Utilities API
* <li>Window System API
* </ul>
* <li>Make a class that extends org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer and is registered as a service provider for the org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer class by specifying "@ServiceProvider(service = DataResultViewer.class)" or by using layer.xml. This class will extend JPanel. </li>
* <li>See the previous sections on default actions.</li>
* </ol>
* <h3>Creating a DataContentViewer</h3>
* DataContentTopComponent is the high-level window in the DataContent area. Each instance of this loads up all instances of DataContentViewers that have been registered with the system. Example viewers include the strings and hexdump views. If you want to make your own type of viewer, follow the steps below. Note that the strings, hexdump, and image viewers come with Autopsy by default and can be used by all DataExplorers and DataResults. You only need to make a new DataContentViewer if these viewers do not satisfy your needs.
* <ol>
* <li>Create a module from within NetBeans. It must be dependent on these modules:
* <ul>
* <li>Case
* <li>CoreComponentInterfaces
* <li>CoreComponents
* <li>DataModel
* <li>DialogsAPI (if pop-ups and such are going to be used)
* <li>Explorer & Property Sheet API
* <li>Lookup
* <li>Nodes API
* <li>Setting API
* <li>UI Utilities API
* <li>Utilities API
* <li>Window System API
* </ul>
* <li>Make a class that implements org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer and is registered as a service provider for DataContentViewer.class by specifying "@ServiceProvider(service = DataContentViewer.class)" or by using layer.xml. This class must extend JPanel. </li>
* </ol>
*/

View File

@ -1,106 +0,0 @@
<body>
<p>This package contains the interface classes that define the core components in Autopsy. These components are used in the difference zones of the GUI.</p>
<h2>Autopsy Zones</h2>
<p>There are three major zones in the Autopsy UI. The left hand side has the {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer DataExplorer} zone. This area is where you can search for and explore data. It has all of the analysis smarts. An example of a DataExplorer is the directory tree that shows the hierarchy of directories (and hides the files from view).</p>
<p>The DataExplorer area identifies a subset of the data to show the user and passes the data to the {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataResult DataResult}s area in the upper right. In the previous example, the contents of a specific folder would be passed to this area and displayed in a table or thumbnail form.</p>
<p>When a file or object is selected in the DataResult, it is passed to the {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataContent DataContent} zone in the lower right. This is where file content can be viewed in hex form, strings, etc. </p>
<h2>Data Flow</h2>
<h3>Creating Nodes in DataExplorer</h3>
<p>Data flows between the areas inside of a NetBeans node. The DataExplorer modules create the NetBeans nodes. They query the SQLite database or do whatever they want to identify the set of files that are of interest. They create the NetBeans nodes based on Sleuthkit data model objects. See the org.sleuthkit.autopsy.datamodel package for more details on this. </p>
<h3>Getting Nodes to DataResult</h3>
<p>Each DataExplorer TopComponent is responsible for creating its own DataResult TopComponent to display its results. It can choose to re-use the same TopComponent for multiple searches (as DirectoryTree does) or it can choose to make a new one each time (as FileSearch does). The setNode() method on the DataResult object is used to set the root node to display. A dummy root node must be created as the parent if a parent does not already exist. </p>
<p>The DataExplorer is responsible for setting the double-click and right-click actions associated with the node. The default single click action is to pass data to DataContent. To override this, you must create a new DataResultViewer instance that overrides the propertyChange() method. The DataExplorer adds actions to wrapping the node in a FilterNode variant. The FilterNode then defines the actions for the node by overriding the getPreferredAction() and getActions() methods. As an example, org.sleuthkit.autopsy.directorytree.DataResultFilterNode and org.sleuthkit.autopsy.directorytree.DataResultFilterChildren wraps the nodes that are passed over by the DirectoryTree DataExplorer.</p>
DataResult can send data back to its DataExplorer by making a custom action that looks up it's instance (DataExplorer.getInstance()).
<h3>Getting Nodes to DataContent </h3>
<p> A default DataContent viewer is created when a case is opened. To display the contents of a node, it must be passed to a DataContent instance. The default single-click behavior of the DataResultViewers is to lookup the default DataContent TopComponent and pass the selected node to it. See {@link org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer#propertyChange(PropertyChangeEvent) AbstractDataResultViewer.propertyChange()} for details. </p>
<h2>Creating new Functionality</h2>
<h3>Creating a DataExplorer</h3>
<ol>
<li>Create a module from within NetBeans. It must be dependent on these modules:
<ul>
<li>Case
<li>CoreComponentInterfaces
<li>CoreComponents
<li>DataModel
<li>DialogsAPI (if pop-ups and such are going to be used)
<li>Explorer & Property Sheet API
<li>Lookup
<li>Nodes API
<li>Setting API
<li>UI Utilities API
<li>Utilities API
<li>Window System API
</ul>
<li> Create a class that implements {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer DataExplorer}. We have been making the TopComponent class be the one that implements DataExplorer. Register this class as a DataExplorer service provider by specifying "@ServiceProvider(service=DataExplorer.class)" in the class or using layer.xml.
<li>Implement the methods required by the DataExplorer interface.
<li>Register the class to receive property change events from the org.sleuthkit.autopsy.Case module by using its addPropertyChangeListener() method.
<li>Access case data using the org.sleuthkit.autopsy.Case module.
<li>Create Nodes for the data objects using the techniques outlined in the previous section.
<li>Wrap the nodes in FilterNodes to define actions as outlined in the previous section.
<li>Send results to DataResults using the techniques outlined in the previous section.
</ol>
<h3>Creating a DataResultViewer</h3>
<p>DataResultTopComponent is the high-level window in the DataResult area. Each instance of this loads up all instances of DataResultViewers that have been registered with the system. Example viewers include the table and thumbnail views. If you want to make your own type of viewer, follow the steps below. Note that the table and thumbnail viewers come with Autopsy by default and can be used by all DataExplorers. </p>
<ol>
<li>Create a module from within NetBeans. It must be dependent on these modules:
<ul>
<li>Case
<li>CoreComponentInterfaces
<li>CoreComponents
<li>DataModel
<li>DialogsAPI (if pop-ups and such are going to be used)
<li>Explorer & Property Sheet API
<li>Lookup
<li>Nodes API
<li>Setting API
<li>UI Utilities API
<li>Utilities API
<li>Window System API
</ul>
<li>Make a class that extends {@link org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer#AbstractDataResultViewer() AbstractDataResultViewer} and is registered as a service provider for the {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer DataResultViewer} class by specifying "@ServiceProvider(service = DataResultViewer.class)" or by using layer.xml. This class will extend JPanel. </li>
<li>See the previous sections on default actions.</li>
</ol>
<h3>Creating a DataContentViewer</h3>
<p>DataContentTopComponent is the high-level window in the DataContent area. Each instance of this loads up all instances of DataContentViewers that have been registered with the system. Example viewers include the strings and hexdump views. If you want to make your own type of viewer, follow the steps below. Note that the strings, hexdump, and image viewers come with Autopsy by default and can be used by all DataExplorers and DataResults. You only need to make a new DataContentViewer if these viewers do not satisfy your needs.</p>
<ol>
<li>Create a module from within NetBeans. It must be dependent on these modules:
<ul>
<li>Case
<li>CoreComponentInterfaces
<li>CoreComponents
<li>DataModel
<li>DialogsAPI (if pop-ups and such are going to be used)
<li>Explorer & Property Sheet API
<li>Lookup
<li>Nodes API
<li>Setting API
<li>UI Utilities API
<li>Utilities API
<li>Window System API
</ul>
<li>Make a class that implements {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer DataContentViewer} and is registered as a service provider for DataContentViewer.class by specifying "@ServiceProvider(service = DataContentViewer.class)" or by using layer.xml. This class must extend JPanel. </li>
</ol>
</body>

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 B

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,49,0,0,1,-109"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
</Form>

View File

@ -0,0 +1,81 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.corecomponents;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* Displays a panel in a new clean dialog. A clean dialog contains nothing
* but the panel given to it. No additional buttons or features, except
* the default close operation, which is set to dispose.
*/
public class AdvancedConfigurationCleanDialog extends javax.swing.JDialog {
/** Creates new form AdvancedConfigurationDialog */
public AdvancedConfigurationCleanDialog() {
this(false);
}
/** Creates new form AdvancedConfigurationDialog */
public AdvancedConfigurationCleanDialog(boolean resizable) {
super(new JFrame(), true);
setResizable(resizable);
if(resizable) {
this.setIconImage(null);
}
initComponents();
}
/**
* Display the given panel on a clean dialog.
* @param panel the panel to display
*/
public void display(JPanel panel) {
this.setTitle(panel.getName());
panel.setAlignmentX(Component.CENTER_ALIGNMENT);
this.add(panel, 0);
this.pack();
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
// set the popUp window / JFrame
int w = this.getSize().width;
int h = this.getSize().height;
// set the location of the popUp Window on the center of the screen
setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
this.setVisible(true);
}
/**
* Close the dialog.
*/
public void close() {
this.dispose();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.LINE_AXIS));
pack();
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
}

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>

View File

@ -54,8 +54,14 @@ public class AdvancedConfigurationDialog extends javax.swing.JDialog {
public void display(JPanel panel) {
this.setTitle(panel.getName());
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
panel.setAlignmentX(Component.CENTER_ALIGNMENT);
applyButton.setAlignmentX(Component.CENTER_ALIGNMENT);
this.add(panel, 0);
this.pack();
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
// set the popUp window / JFrame
int w = this.getSize().width;
int h = this.getSize().height;
@ -63,10 +69,6 @@ public class AdvancedConfigurationDialog extends javax.swing.JDialog {
// set the location of the popUp Window on the center of the screen
setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
panel.setAlignmentX(Component.CENTER_ALIGNMENT);
applyButton.setAlignmentX(Component.CENTER_ALIGNMENT);
this.add(panel, 0);
this.pack();
this.setVisible(true);
}

View File

@ -85,3 +85,7 @@ DataContentViewerString.goToPageLabel.text=Go to Page:
DataContentViewerString.goToPageTextField.text=
DataContentViewerHex.goToPageTextField.text=
DataContentViewerHex.goToPageLabel.text=Go to Page:
DataContentViewerString.languageLabel.toolTipText=
DataContentViewerString.languageLabel.text=Script:
DataContentViewerString.languageCombo.toolTipText=Language to attempt when interpreting (extracting and decoding) strings from binary data
DataContentViewerString.noTextLabel.text=offset info

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>

View File

@ -98,7 +98,7 @@ public final class DataContentTopComponent extends TopComponent implements DataC
return this.wrapped.isSupported(node);
}
boolean isPreferred(Node node, boolean isSupported) {
int isPreferred(Node node, boolean isSupported) {
return this.wrapped.isPreferred(node, isSupported);
}
}
@ -293,17 +293,10 @@ public final class DataContentTopComponent extends TopComponent implements DataC
int totalTabs = dataContentTabbedPane.getTabCount();
List<DataContentViewer> dcvs = new ArrayList<DataContentViewer>();
dcvs.addAll(Lookup.getDefault().lookupAll(DataContentViewer.class));
for (int i = 0; i<dcvs.size(); i++){
DataContentViewer dcv = dcvs.get(i);
if(dcv.getTitle().equals("String View") && dataContentTabbedPane.getTabCount() > i){
dataContentTabbedPane.setSelectedIndex(i);
}
}
int maxPreferred = 0;
int indexOfPreferred = 0;
if (totalTabs > 0) { // make sure there are tabs to reset
int tempIndex = dataContentTabbedPane.getSelectedIndex();
for (int i = 0; i < totalTabs; i++) {
UpdateWrapper dcv = viewers.get(i);
dcv.resetComponent();
@ -312,31 +305,25 @@ public final class DataContentTopComponent extends TopComponent implements DataC
boolean dcvSupported = dcv.isSupported(selectedNode);
if (! dcvSupported) {
dataContentTabbedPane.setEnabledAt(i, false);
// change the tab selection if it's the current selection
if (tempIndex == i) {
if (i > 0) {
dataContentTabbedPane.setSelectedIndex(0);
} else {
dataContentTabbedPane.setSelectedIndex(1);
}
}
} else {
dataContentTabbedPane.setEnabledAt(i, true);
if (dcv.isPreferred(selectedNode, dcvSupported))
dataContentTabbedPane.setSelectedIndex(i);
int currentPreferred = dcv.isPreferred(selectedNode, dcvSupported);
if (currentPreferred > maxPreferred) {
indexOfPreferred = i;
maxPreferred = currentPreferred;
}
}
}
int newIndex = dataContentTabbedPane.getSelectedIndex();
// set the display of the tab
viewers.get(newIndex).setNode(selectedNode);
dataContentTabbedPane.setSelectedIndex(indexOfPreferred);
viewers.get(indexOfPreferred).setNode(selectedNode);
}
}
/**
* Get the tab pane
* @return tab pane with individual {@link DataContentViewer}s
* @return tab pane with individual DataContentViewers
*/
public JTabbedPane getTabPanels() {
return this.dataContentTabbedPane;

View File

@ -46,7 +46,7 @@ import org.sleuthkit.datamodel.TskException;
/**
* Viewer displays Artifacts associated with Contents
*/
@ServiceProvider(service = DataContentViewer.class)
@ServiceProvider(service = DataContentViewer.class, position=3)
public class DataContentViewerArtifact extends javax.swing.JPanel implements DataContentViewer{
private static int currentPage = 1;
@ -314,12 +314,17 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
}
@Override
public boolean isPreferred(Node node, boolean isSupported) {
public int isPreferred(Node node, boolean isSupported) {
BlackboardArtifact art = node.getLookup().lookup(BlackboardArtifact.class);
if(art != null && art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID())
return true;
else
return false;
if(isSupported) {
if(art == null) {
return 3;
} else {
return 5;
}
} else {
return 0;
}
}
private void customizeComponents(){

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>

View File

@ -39,7 +39,7 @@ import org.sleuthkit.datamodel.TskException;
/**
* Hex view of file contents.
*/
@ServiceProvider(service = DataContentViewer.class)
@ServiceProvider(service = DataContentViewer.class, position=1)
public class DataContentViewerHex extends javax.swing.JPanel implements DataContentViewer {
private static long currentOffset = 0;
@ -257,7 +257,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
private void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToPageTextFieldActionPerformed
String pageNumberStr = goToPageTextField.getText();
int pageNumber = 0;
int maxPage = (int) (dataSource.getSize() / pageLength) + 1;
int maxPage = Math.round((dataSource.getSize()-1) / pageLength) + 1;
try {
pageNumber = Integer.parseInt(pageNumberStr);
} catch (NumberFormatException ex) {
@ -333,7 +333,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
}
if (setVisible) {
int totalPage = (int) (dataSource.getSize() / pageLength) + 1;
int totalPage = Math.round((dataSource.getSize()-1) / pageLength) + 1;
totalPageLabel.setText(Integer.toString(totalPage));
currentPageLabel.setText(Integer.toString(currentPage));
setComponentsVisibility(true); // shows the components that not needed
@ -361,6 +361,10 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
@Override
public void setNode(Node selectedNode) {
if(!isSupported(selectedNode)) {
setDataView(null, 0, true);
return;
}
if (selectedNode != null) {
Content content = (selectedNode).getLookup().lookup(Content.class);
if (content != null) {
@ -413,6 +417,8 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
nextPageButton.setVisible(isVisible);
pageLabel.setVisible(isVisible);
pageLabel2.setVisible(isVisible);
goToPageTextField.setVisible(isVisible);
goToPageLabel.setVisible(isVisible);
}
@Override
@ -430,8 +436,12 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
}
@Override
public boolean isPreferred(Node node, boolean isSupported) {
return false;
public int isPreferred(Node node, boolean isSupported) {
if(isSupported) {
return 1;
} else {
return 0;
}
}
@Override

View File

@ -45,7 +45,7 @@ import org.sleuthkit.datamodel.TskData;
*
* @author dfickling
*/
@ServiceProvider(service = DataContentViewer.class)
@ServiceProvider(service = DataContentViewer.class, position=5)
public class DataContentViewerMedia extends javax.swing.JPanel implements DataContentViewer {
private static final String[] IMAGES = new String[]{ ".jpg", ".jpeg", ".png", ".gif", ".jpe", ".bmp"};
@ -172,6 +172,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
}
File file = selectedNode.getLookup().lookup(File.class);
setDataView(file);
if(file == null) {
return;
}
boolean isVidOrAud = containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS);
pauseButton.setVisible(isVidOrAud);
progressLabel.setVisible(isVidOrAud);
@ -179,8 +182,12 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
}
private void setDataView(File file) {
if(file == null)
if(file == null) {
setComponentsVisibility(false);
return;
} else {
setComponentsVisibility(true);
}
this.currentFile = file;
if (containsExt(file.getName(), IMAGES)) {
@ -196,6 +203,17 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
playbin2.play();
}
}
/**
* To set the visibility of specific components in this class.
*
* @param isVisible whether to show or hide the specific components
*/
private void setComponentsVisibility(boolean isVisible) {
pauseButton.setVisible(isVisible);
progressLabel.setVisible(isVisible);
progressSlider.setVisible(isVisible);
videoPanel.setVisible(isVisible);
}
@Override
public String getTitle() {
@ -283,8 +301,12 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
}
@Override
public boolean isPreferred(Node node, boolean isSupported) {
return isSupported;
public int isPreferred(Node node, boolean isSupported) {
if(isSupported) {
return 7;
} else {
return 0;
}
}
private static boolean containsExt(String name, String[] exts) {

View File

@ -178,8 +178,12 @@ public class DataContentViewerPicture extends javax.swing.JPanel implements Data
}
@Override
public boolean isPreferred(Node node, boolean isSupported) {
return isSupported;
public int isPreferred(Node node, boolean isSupported) {
if(isSupported) {
return 1;
} else {
return 0;
}
}
@Override

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
@ -55,7 +55,7 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
@ -74,9 +74,14 @@
<Component id="goToPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="goToPageTextField" min="-2" pref="79" max="-2" attributes="0"/>
<EmptySpace pref="205" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="noTextLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="languageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="languageCombo" min="-2" pref="229" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="1" pref="622" max="32767" attributes="0"/>
<Component id="jScrollPane1" pref="756" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
@ -93,7 +98,12 @@
<Component id="nextPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="prevPageButton" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
<Component id="goToPageLabel" min="-2" max="-2" attributes="0"/>
<Component id="goToPageTextField" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="goToPageTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="languageCombo" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="languageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="noTextLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="401" max="32767" attributes="0"/>
@ -252,6 +262,36 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="goToPageTextFieldActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="languageCombo">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.languageCombo.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="languageComboActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="languageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.languageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.languageLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="noTextLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerString.noTextLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>

View File

@ -22,6 +22,7 @@ import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JMenuItem;
@ -30,7 +31,10 @@ import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.datamodel.DataConversion;
import org.sleuthkit.autopsy.coreutils.StringExtract;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractResult;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
import org.sleuthkit.autopsy.datamodel.StringContent;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.FsContent;
@ -40,7 +44,7 @@ import org.sleuthkit.datamodel.TskException;
/**
* Viewer displays strings extracted from contents.
*/
@ServiceProvider(service = DataContentViewer.class)
@ServiceProvider(service = DataContentViewer.class, position=2)
public class DataContentViewerString extends javax.swing.JPanel implements DataContentViewer {
private static long currentOffset = 0;
@ -51,6 +55,9 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
// for error handling
private String className = this.getClass().toString();
//string extract utility
private final StringExtract stringExtract = new StringExtract();
/** Creates new form DataContentViewerString */
public DataContentViewerString() {
initComponents();
@ -72,6 +79,12 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
};
copyMenuItem.addActionListener(actList);
selectAllMenuItem.addActionListener(actList);
List<SCRIPT> supportedScripts = StringExtract.getSupportedScripts();
for (SCRIPT s : supportedScripts) {
languageCombo.addItem(s);
}
}
/** This method is called from within the constructor to
@ -98,6 +111,9 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
prevPageButton = new javax.swing.JButton();
goToPageLabel = new javax.swing.JLabel();
goToPageTextField = new javax.swing.JTextField();
languageCombo = new javax.swing.JComboBox();
languageLabel = new javax.swing.JLabel();
noTextLabel = new javax.swing.JLabel();
copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerString.class, "DataContentViewerString.copyMenuItem.text")); // NOI18N
rightClickMenu.add(copyMenuItem);
@ -166,6 +182,18 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
}
});
languageCombo.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerString.class, "DataContentViewerString.languageCombo.toolTipText")); // NOI18N
languageCombo.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
languageComboActionPerformed(evt);
}
});
languageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerString.class, "DataContentViewerString.languageLabel.text")); // NOI18N
languageLabel.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerString.class, "DataContentViewerString.languageLabel.toolTipText")); // NOI18N
noTextLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerString.class, "DataContentViewerString.noTextLabel.text")); // NOI18N
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
@ -189,8 +217,13 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
.addComponent(goToPageLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(205, Short.MAX_VALUE))
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 622, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(noTextLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(languageLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(languageCombo, javax.swing.GroupLayout.PREFERRED_SIZE, 229, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 756, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -205,7 +238,11 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
.addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(goToPageLabel)
.addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(languageCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(languageLabel)
.addComponent(noTextLabel)))
.addGap(0, 0, 0)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE))
);
@ -240,8 +277,8 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
private void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToPageTextFieldActionPerformed
String pageNumberStr = goToPageTextField.getText();
int pageNumber = 0;
int maxPage = (int) (dataSource.getSize() / pageLength) + 1;
int pageNumber;
int maxPage = Math.round((dataSource.getSize()-1) / pageLength) + 1;
try {
pageNumber = Integer.parseInt(pageNumberStr);
} catch (NumberFormatException ex) {
@ -258,6 +295,13 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
setDataView(dataSource, currentOffset, false);
}//GEN-LAST:event_goToPageTextFieldActionPerformed
private void languageComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_languageComboActionPerformed
if (dataSource != null) {
setDataView(dataSource, currentOffset, false);
}
}//GEN-LAST:event_languageComboActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JMenuItem copyMenuItem;
private javax.swing.JLabel currentPageLabel;
@ -265,7 +309,10 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
private javax.swing.JTextField goToPageTextField;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JComboBox languageCombo;
private javax.swing.JLabel languageLabel;
private javax.swing.JButton nextPageButton;
private javax.swing.JLabel noTextLabel;
private javax.swing.JLabel ofLabel;
private javax.swing.JTextPane outputViewPane;
private javax.swing.JLabel pageLabel;
@ -301,7 +348,18 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
Boolean setVisible = false;
if (bytesRead > 0) {
text = DataConversion.getString(data, bytesRead, 4);
//text = DataConversion.getString(data, bytesRead, 4);
final SCRIPT selScript = (SCRIPT) languageCombo.getSelectedItem();
stringExtract.setEnabledScript(selScript);
StringExtractResult res = stringExtract.extract(data, bytesRead, 0);
text = res.getText();
if (text.trim().isEmpty()) {
noTextLabel.setText("(offset " + currentOffset + "-" + (currentOffset + pageLength)
+ " contains no text)");
}
else {
noTextLabel.setText("");
}
setVisible = true;
}
@ -320,7 +378,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
}
if (setVisible) {
int totalPage = (int) (dataSource.getSize() / pageLength) + 1;
int totalPage = Math.round((dataSource.getSize()-1) / pageLength) + 1;
totalPageLabel.setText(Integer.toString(totalPage));
currentPageLabel.setText(Integer.toString(currentPage));
outputViewPane.setText(text); // set the output view
@ -355,10 +413,16 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
nextPageButton.setVisible(isVisible);
pageLabel.setVisible(isVisible);
pageLabel2.setVisible(isVisible);
goToPageTextField.setVisible(isVisible);
goToPageLabel.setVisible(isVisible);
}
@Override
public void setNode(Node selectedNode) {
if(!isSupported(selectedNode)) {
setDataView(null, 0, true);
return;
}
if (selectedNode != null) {
Lookup lookup = selectedNode.getLookup();
Content content = lookup.lookup(Content.class);
@ -404,6 +468,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
prevPageButton.setEnabled(false);
nextPageButton.setEnabled(false);
setComponentsVisibility(false); // hides the components that not needed
noTextLabel.setText("");
}
@Override
@ -421,15 +486,13 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
}
@Override
public boolean isPreferred(Node node, boolean isSupported) {
public int isPreferred(Node node, boolean isSupported) {
if(node != null && isSupported){
StringContent scontent = node.getLookup().lookup(StringContent.class);
if(scontent != null){
return true;
return 2;
} else {
return 0;
}
}
return false;
}
@Override
public Component getComponent() {

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>

View File

@ -171,36 +171,6 @@ public final class DataResultTopComponent extends TopComponent implements DataRe
private javax.swing.JLabel matchLabel;
private javax.swing.JLabel numberMatchLabel;
// End of variables declaration//GEN-END:variables
// /**
// * Gets default instance. Do not use directly: reserved for *.settings files only,
// * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
// * To obtain the singleton instance, use {@link #findInstance}.
// */
// public static synchronized DataResultTopComponent getDefault() {
// if (instance == null) {
// instance = new DataResultTopComponent();
// }
// return instance;
// }
//
// /**
// * Obtain the DataResultTopComponent instance. Never call {@link #getDefault} directly!
// */
// public static synchronized DataResultTopComponent findInstance() {
// TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
// if (win == null) {
// Logger.getLogger(DataResultTopComponent.class.getName()).warning(
// "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system.");
// return getDefault();
// }
// if (win instanceof DataResultTopComponent) {
// return (DataResultTopComponent) win;
// }
// Logger.getLogger(DataResultTopComponent.class.getName()).warning(
// "There seem to be multiple components with the '" + PREFERRED_ID
// + "' ID. That is a potential source of errors and unexpected behavior.");
// return getDefault();
// }
@Override
public int getPersistenceType() {

View File

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>

View File

@ -193,6 +193,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
* Gets regular Bean property set properties from all children and, recursively, subchildren of Node.
* Note: won't work out the box for lazy load - you need to set all children props for the parent by hand
* @param parent Node with at least one child to get properties from
* @param rows max number of rows to retrieve properties for (can be used for memory optimization)
*/
private void getAllChildPropertyHeadersRec(Node parent, int rows) {
for(int i = 0; i < Math.min(rows, parent.getChildren().getNodesCount()); i++){

View File

@ -1,139 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="currentPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ofLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="totalPageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="prevPageButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="nextPageButton" min="-2" pref="99" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="filePathLabel" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="574" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="filePathLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="pageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="currentPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ofLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="totalPageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="prevPageButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="nextPageButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="337" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="nextPageButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="OutputViewPanel.nextPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="nextPageButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextPane" name="outputViewPane">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Courier New" size="11" style="0"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="prevPageButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="OutputViewPanel.prevPageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="prevPageButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="totalPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="OutputViewPanel.totalPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="ofLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="OutputViewPanel.ofLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="currentPageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="OutputViewPanel.currentPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="OutputViewPanel.pageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="filePathLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="OutputViewPanel.filePathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -1,249 +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.corecomponents;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.sleuthkit.autopsy.datamodel.DataConversion;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskException;
/**
* Paging view for DataContentViewer.
*/
public class OutputViewPanel extends javax.swing.JPanel {
private static long currentOffset = 0;
private static final long pageLength = 10240;
private final byte[] data = new byte [(int)pageLength];
private static int currentPage = 1;
private int outputType;
private Content dataSource;
/**
* Creates new form OutputViewPanel
* @param outputType type of panel to display: 1 = hex view, 2 = string view
*/
public OutputViewPanel(int outputType) {
initComponents();
this.outputType = outputType;
this.dataSource = null;
// clear / reset the fields
filePathLabel.setText("");
currentPageLabel.setText("");
totalPageLabel.setText("");
ofLabel.setVisible(false);
prevPageButton.setEnabled(false);
nextPageButton.setEnabled(false);
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
nextPageButton = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
outputViewPane = new javax.swing.JTextPane();
prevPageButton = new javax.swing.JButton();
totalPageLabel = new javax.swing.JLabel();
ofLabel = new javax.swing.JLabel();
currentPageLabel = new javax.swing.JLabel();
pageLabel = new javax.swing.JLabel();
filePathLabel = new javax.swing.JLabel();
nextPageButton.setText(org.openide.util.NbBundle.getMessage(OutputViewPanel.class, "OutputViewPanel.nextPageButton.text")); // NOI18N
nextPageButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
nextPageButtonActionPerformed(evt);
}
});
outputViewPane.setFont(new java.awt.Font("Courier New", 0, 11));
jScrollPane1.setViewportView(outputViewPane);
prevPageButton.setText(org.openide.util.NbBundle.getMessage(OutputViewPanel.class, "OutputViewPanel.prevPageButton.text")); // NOI18N
prevPageButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
prevPageButtonActionPerformed(evt);
}
});
totalPageLabel.setText(org.openide.util.NbBundle.getMessage(OutputViewPanel.class, "OutputViewPanel.totalPageLabel.text")); // NOI18N
ofLabel.setText(org.openide.util.NbBundle.getMessage(OutputViewPanel.class, "OutputViewPanel.ofLabel.text")); // NOI18N
currentPageLabel.setText(org.openide.util.NbBundle.getMessage(OutputViewPanel.class, "OutputViewPanel.currentPageLabel.text")); // NOI18N
pageLabel.setText(org.openide.util.NbBundle.getMessage(OutputViewPanel.class, "OutputViewPanel.pageLabel.text")); // NOI18N
filePathLabel.setText(org.openide.util.NbBundle.getMessage(OutputViewPanel.class, "OutputViewPanel.filePathLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 602, Short.MAX_VALUE)
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addComponent(pageLabel)
.addGap(18, 18, 18)
.addComponent(currentPageLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(ofLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(totalPageLabel)
.addGap(18, 18, 18)
.addComponent(prevPageButton)
.addGap(18, 18, 18)
.addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 99, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(276, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(filePathLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(574, 574, 574))))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(filePathLabel)
.addGap(4, 4, 4)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(pageLabel)
.addComponent(currentPageLabel)
.addComponent(ofLabel)
.addComponent(totalPageLabel)
.addComponent(prevPageButton)
.addComponent(nextPageButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 337, Short.MAX_VALUE)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed
//@@@ this is part of the code dealing with the data viewer. could be copied/removed to implement the scrollbar
currentOffset -= pageLength;
currentPage = currentPage - 1;
currentPageLabel.setText(Integer.toString(currentPage));
setDataView(dataSource, currentOffset, false, outputType);
}//GEN-LAST:event_prevPageButtonActionPerformed
private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
//@@@ this is part of the code dealing with the data viewer. could be copied/removed to implement the scrollbar
currentOffset += pageLength;
currentPage = currentPage + 1;
currentPageLabel.setText(Integer.toString(currentPage));
setDataView(dataSource, currentOffset, false, outputType);
}//GEN-LAST:event_nextPageButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel currentPageLabel;
private javax.swing.JLabel filePathLabel;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JButton nextPageButton;
private javax.swing.JLabel ofLabel;
private javax.swing.JTextPane outputViewPane;
private javax.swing.JLabel pageLabel;
private javax.swing.JButton prevPageButton;
private javax.swing.JLabel totalPageLabel;
// End of variables declaration//GEN-END:variables
/**
* Sets the DataView (The tabbed panel)
*
* @param dataSource the content that want to be shown
* @param offset the starting offset
* @param reset whether to reset the dataView or not
* @param outputType the type of the output. 1 = hex view, 2 = string view
*/
public void setDataView(Content dataSource, long offset, boolean reset, int outputType) {
try {
this.dataSource = dataSource;
int bytesRead = 0;
if (!reset && dataSource.getSize() > 0) {
bytesRead = dataSource.read(data, offset, pageLength); // read the data
}
// I set the -1 to for empty node or directory
if (reset) {
filePathLabel.setText("");
}
// set the data on the bottom and show it
String text = "";
Boolean setVisible = false;
if (bytesRead > 0) {
text = DataConversion.getString(data, bytesRead, 4);
setVisible = true;
}
// disable or enable the next button
if (offset + pageLength < dataSource.getSize()) {
nextPageButton.setEnabled(true);
} else {
nextPageButton.setEnabled(false);
}
if (offset == 0) {
prevPageButton.setEnabled(false);
currentPage = 1; // reset the page number
} else {
prevPageButton.setEnabled(true);
}
// type 1 = hex view
if (outputType == 1) {
int showLength = bytesRead<pageLength?bytesRead:(int)pageLength;
outputViewPane.setText(DataConversion.byteArrayToHex(data, showLength, offset, outputViewPane.getFont()));
outputViewPane.moveCaretPosition(0);
}
// type 2 = string view
if (outputType == 2) {
outputViewPane.setText(text);
outputViewPane.moveCaretPosition(0);
}
if (setVisible) {
int totalPage = (int) (dataSource.getSize() / pageLength) + 1;
ofLabel.setVisible(true);
totalPageLabel.setText(Integer.toString(totalPage));
currentPageLabel.setText(Integer.toString(currentPage));
} else {
// reset or hide the labels
ofLabel.setVisible(false);
totalPageLabel.setText("");
currentPageLabel.setText("");
}
} catch (TskException ex) {
// TODO: maybe make bubble instead
Logger.getLogger(OutputViewPanel.class.getName()).log(Level.WARNING, "Error while trying to set the display on the ouput view panel.", ex);
}
}
}

View File

@ -0,0 +1,6 @@
/**
\package org.sleuthkit.autopsy.corecomponents
This package contains standard implementations of the content viewer and other frameworks.
*/

View File

@ -0,0 +1,91 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012 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.coreutils;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* File and dir utilities
*/
public class FileUtil {
private static final Logger logger = Logger.getLogger(FileUtil.class.getName());
/**
* Recursively delete a dir
*
* @param dirPath dir path of a dir to delete
* @return true if the dir deleted, false otherwise
*/
public static boolean deleteDir(File dirPath) {
if (dirPath.exists()) {
File[] files = dirPath.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteDir(files[i]);
} else {
files[i].delete();
}
}
}
return (dirPath.delete());
}
/**
* Check if given path is a file or directory, then delete it through
* recursion with path leading to a file as the base case.
*
* @param path the path to the file or directory to delete
* @return true if the File at path is deleted, false otherwise
*/
public static boolean deleteFileDir(File path) {
boolean sucess = true;
if(path.isFile()) { // If it's a file
if(!path.delete()) {
sucess = false;
logger.log(Level.WARNING, "Failed to delete file {0}", path.getPath());
}
} else { // If it's a directory
if(path.list().length==0) { // If the dir is empty
if(!path.delete()) {
sucess = false;
logger.log(Level.WARNING, "Failed to delete the empty directory at {0}", path.getPath());
}
} else {
String files[] = path.list();
for(String s:files) {
File sub = new File(path, s);
sucess = deleteFileDir(sub);
}
if(path.list().length==0) { // Delete the newly-empty dir
if(!path.delete()) {
sucess = false;
logger.log(Level.WARNING, "Failed to delete the empty directory at {0}", path.getPath());
}
} else {
sucess = false;
logger.log(Level.WARNING, "Directory {0} did not recursivly delete sucessfully.", path.getPath());
}
}
}
return sucess;
}
}

View File

@ -24,6 +24,7 @@ import java.util.logging.FileHandler;
import org.openide.modules.ModuleInstall;
import java.util.logging.Logger;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.SimpleFormatter;
@ -50,6 +51,9 @@ public class Installer extends ModuleInstall {
logs.setFormatter(new SimpleFormatter());
autopsyLogger.addHandler(logs);
}
autopsyLogger.log(Level.INFO, "Application name: " + Version.getName()
+ ", version: " + Version.getVersion() + ", build: " + Version.getBuildType());
}
@Override

View File

@ -0,0 +1,304 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012 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.coreutils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.sleuthkit.autopsy.coreutils.LnkEnums.CommonNetworkRelativeLinkFlags;
import org.sleuthkit.autopsy.coreutils.LnkEnums.DriveType;
import org.sleuthkit.autopsy.coreutils.LnkEnums.FileAttributesFlags;
import org.sleuthkit.autopsy.coreutils.LnkEnums.LinkFlags;
import org.sleuthkit.autopsy.coreutils.LnkEnums.NetworkProviderType;
/**
*
* @author dick
*/
public class JLNK {
private int header;
private byte[] linkClassIdentifier;
private List<LinkFlags> linkFlags;
private List<FileAttributesFlags> fileAttributesFlags;
private long crtime;
private long atime;
private long mtime;
private int fileSize;
private int iconIndex;
private int showCommand;
private short hotKey;
private List<String> linkTargetIdList;
private boolean hasUnicodeLocalBaseAndCommonSuffixOffset;
private String localBasePath;
private String commonPathSuffix;
private String localBasePathUnicode;
private String commonPathSuffixUnicode;
private String name;
private String relativePath;
private String workingDir;
private String arguments;
private String iconLocation;
private int driveSerialNumber;
private DriveType driveType;
private String volumeLabel;
private List<CommonNetworkRelativeLinkFlags> commonNetworkRelativeListFlags;
private NetworkProviderType networkProviderType;
private boolean unicodeNetAndDeviceName;
private String netName;
private String netNameUnicode;
private String deviceName;
private String deviceNameUnicode;
public JLNK(int header, byte[] linkClassIdentifier, int linkFlags,
int fileAttributesFlags, long crtime, long atime,
long mtime, int fileSize, int iconIndex, int showCommand, short hotKey,
List<String> linkTargetIdList,
boolean hasUnicodeLocalBaseAndCommonSuffixOffset,
String localBasePath, String commonPathSuffix, String localBasePathUnicode,
String commonPathSuffixUnicode, String name, String relativePath,
String workingDir, String arguments, String iconLocation, int driveSerialNumber,
DriveType driveType, String volumeLabel,
int commonNetworkRelativeListFlags,
NetworkProviderType networkProviderType, boolean unicodeNetAndDeviceName,
String netName, String netNameUnicode, String deviceName,
String deviceNameUnicode) {
this.header = header;
this.linkClassIdentifier = linkClassIdentifier;
this.linkFlags = new ArrayList<LinkFlags>();
for(LnkEnums.LinkFlags enumVal : LnkEnums.LinkFlags.values()) {
if((linkFlags & enumVal.getFlag()) == enumVal.getFlag()) {
this.linkFlags.add(enumVal);
}
}
this.fileAttributesFlags = new ArrayList<FileAttributesFlags>();
for(LnkEnums.FileAttributesFlags enumVal : LnkEnums.FileAttributesFlags.values()) {
if((fileAttributesFlags & enumVal.getFlag()) == enumVal.getFlag()) {
this.fileAttributesFlags.add(enumVal);
}
}
this.crtime = crtime;
this.atime = atime;
this.mtime = mtime;
this.fileSize = fileSize;
this.iconIndex = iconIndex;
this.showCommand = showCommand;
this.hotKey = hotKey;
this.linkTargetIdList = linkTargetIdList;
this.hasUnicodeLocalBaseAndCommonSuffixOffset = hasUnicodeLocalBaseAndCommonSuffixOffset;
this.localBasePath = localBasePath;
this.commonPathSuffix = commonPathSuffix;
this.localBasePathUnicode = localBasePathUnicode;
this.commonPathSuffixUnicode = commonPathSuffixUnicode;
this.name = name;
this.relativePath = relativePath;
this.workingDir = workingDir;
this.arguments = arguments;
this.iconLocation = iconLocation;
this.driveSerialNumber = driveSerialNumber;
this.driveType = driveType;
this.volumeLabel = volumeLabel;
this.commonNetworkRelativeListFlags = new ArrayList<CommonNetworkRelativeLinkFlags>();
for(LnkEnums.CommonNetworkRelativeLinkFlags enumVal : LnkEnums.CommonNetworkRelativeLinkFlags.values()) {
if((commonNetworkRelativeListFlags & enumVal.getFlag()) == enumVal.getFlag()) {
this.commonNetworkRelativeListFlags.add(enumVal);
}
}
this.networkProviderType = networkProviderType;
this.unicodeNetAndDeviceName = unicodeNetAndDeviceName;
this.netName = netName;
this.netNameUnicode = netNameUnicode;
this.deviceName = deviceName;
this.deviceNameUnicode = deviceNameUnicode;
}
public String getArguments() {
return arguments;
}
public List<CommonNetworkRelativeLinkFlags> getCommonNetworkRelativeListFlags() {
return commonNetworkRelativeListFlags;
}
public String getCommonPathSuffix() {
return commonPathSuffix;
}
public String getCommonPathSuffixUnicode() {
return commonPathSuffixUnicode;
}
public long getCrtime() {
return crtime;
}
public long getCtime() {
return atime;
}
public String getDeviceName() {
return deviceName;
}
public String getDeviceNameUnicode() {
return deviceNameUnicode;
}
public int getDriveSerialNumber() {
return driveSerialNumber;
}
public DriveType getDriveType() {
return driveType;
}
public List<FileAttributesFlags> getFileAttributesFlags() {
return fileAttributesFlags;
}
public int getFileSize() {
return fileSize;
}
public boolean isHasUnicodeLocalBaseAndCommonSuffixOffset() {
return hasUnicodeLocalBaseAndCommonSuffixOffset;
}
public int getHeader() {
return header;
}
public short getHotKey() {
return hotKey;
}
public List<String> getLinkTargetIdList() {
return linkTargetIdList;
}
public int getIconIndex() {
return iconIndex;
}
public String getIconLocation() {
return iconLocation;
}
public byte[] getLinkClassIdentifier() {
return linkClassIdentifier;
}
public List<LinkFlags> getLinkFlags() {
return linkFlags;
}
public String getLocalBasePath() {
return localBasePath;
}
public String getLocalBasePathUnicode() {
return localBasePathUnicode;
}
public long getMtime() {
return mtime;
}
public String getName() {
return name;
}
public String getNetName() {
return netName;
}
public String getNetNameUnicode() {
return netNameUnicode;
}
public NetworkProviderType getNetworkProviderType() {
return networkProviderType;
}
public String getRelativePath() {
return relativePath;
}
public int getShowCommand() {
return showCommand;
}
public boolean isUnicodeNetAndDeviceName() {
return unicodeNetAndDeviceName;
}
public String getVolumeLabel() {
return volumeLabel;
}
public String getWorkingDir() {
return workingDir;
}
public String getBestPath() {
if(localBasePathUnicode != null && !localBasePathUnicode.isEmpty()) {
if(commonPathSuffixUnicode != null) {
return localBasePathUnicode + commonPathSuffixUnicode;
} else if(commonPathSuffix != null) {
return localBasePathUnicode + commonPathSuffix;
}
} else if(localBasePath != null && !localBasePath.isEmpty()) {
if(commonPathSuffixUnicode != null) {
return localBasePath + commonPathSuffixUnicode;
} else if(commonPathSuffix != null) {
return localBasePath + commonPathSuffix;
}
} else if(netNameUnicode != null && !netNameUnicode.isEmpty()) {
if(commonPathSuffixUnicode != null && !commonPathSuffixUnicode.isEmpty()) {
return netNameUnicode + "\\" + commonPathSuffixUnicode;
} else if(commonPathSuffix != null && !commonPathSuffix.isEmpty()) {
return netNameUnicode + "\\" + commonPathSuffix;
}
} else if(netName != null && !netName.isEmpty()) {
if(commonPathSuffixUnicode != null && !commonPathSuffixUnicode.isEmpty()) {
return netName + "\\" + commonPathSuffixUnicode;
} else if(commonPathSuffix != null && !commonPathSuffix.isEmpty()) {
return netName + "\\" + commonPathSuffix;
}
} else if(linkTargetIdList != null && !linkTargetIdList.isEmpty()) {
String ret = "";
for(String s : linkTargetIdList) {
ret += s;
}
return ret;
}
return "No preferred path found";
}
public String getBestName() {
return new File(getBestPath()).getName(); // not very cross platform :(
}
}

View File

@ -0,0 +1,339 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012 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.coreutils;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.sleuthkit.autopsy.coreutils.LnkEnums.CommonCLSIDS;
import org.sleuthkit.autopsy.coreutils.LnkEnums.DriveType;
import org.sleuthkit.autopsy.coreutils.LnkEnums.NetworkProviderType;
/**
*
* @author dfickling
* Parse lnk files using documentation from
* http://msdn.microsoft.com/en-us/library/dd871305(v=prot.13).aspx
* http://msdn.microsoft.com/en-us/library/windows/desktop/cc144090(v=vs.85).aspx#unknown_74413
* http://blog.0x01000000.org/2010/08/10/lnk-parsing-youre-doing-it-wrong-i/
*/
public class JLnkParser {
private byte[] content;
private static final Logger logger = Logger.getLogger(JLnkParser.class.getName());
public JLnkParser(InputStream is, int length) {
content = new byte[length];
try {
is.read(content);
} catch (IOException ex) {
Logger.getLogger(JLnkParser.class.getName()).log(Level.WARNING, "Error reading input stream", ex);
}
}
public JLNK parse() {
ByteBuffer bb = ByteBuffer.wrap(content);
bb.order(ByteOrder.LITTLE_ENDIAN);
int header = bb.getInt();
ByteBuffer linkClassIdentifier = bb.get(new byte[16]);
int linkFlags = bb.getInt();
int fileAttributes = bb.getInt();
long crtime = bb.getLong();
long atime = bb.getLong();
long mtime = bb.getLong();
int fileSize = bb.getInt();
int iconIndex = bb.getInt();
int showCommand = bb.getInt();
short hotkey = bb.getShort();
bb.get(new byte[10]); // reserved (???)
List<String> linkTargetIdList = new ArrayList<String>();
if((linkFlags & LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) ==
LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) {
int idListSize = bb.getShort();
int bytesRead = 0;
List<byte[]> linkTargetIdListBytes = new ArrayList<byte[]>();
while(true) {
short itemIdSize = bb.getShort();
if(itemIdSize == 0) {
bytesRead += 2; // two null bytes to terminate id list
break;
}
byte[] theArray = new byte[itemIdSize-2];
bb.get(theArray); // an idlist data object
linkTargetIdListBytes.add(theArray);
bytesRead = bytesRead + itemIdSize;
}
linkTargetIdList = parseLinkTargetIdList(linkTargetIdListBytes);
}
boolean hasUnicodeLocalBaseAndCommonSuffixOffset = false;
String localBasePath = null;
String commonPathSuffix = null;
String localBasePathUnicode = null;
String commonPathSuffixUnicode = null;
int driveSerialNumber = -1;
DriveType driveType = null;
String volumeLabel = null;
int commonNetworkRelativeLinkFlags = -1;
NetworkProviderType networkProviderType = null;
boolean unicodeNetAndDeviceName = false;
String netName = null;
String netNameUnicode = null;
String deviceName = null;
String deviceNameUnicode = null;
if((linkFlags & LnkEnums.LinkFlags.HasLinkInfo.getFlag()) ==
LnkEnums.LinkFlags.HasLinkInfo.getFlag()) {
int startOfLinkInfo = bb.position();
int linkInfoSize = bb.getInt();
int linkInfoHeaderSize = bb.getInt();
hasUnicodeLocalBaseAndCommonSuffixOffset = linkInfoHeaderSize >= 0x24;
int linkInfoFlags = bb.getInt();
int volumeIdOffset = bb.getInt();
int localBasePathOffset = bb.getInt();
int commonNetworkRelativeLinkOffset = bb.getInt();
int commonPathSuffixOffset = bb.getInt();
int localBasePathOffsetUnicode = 0;
int commonPathSuffixOffsetUnicode = 0;
if (hasUnicodeLocalBaseAndCommonSuffixOffset) {
localBasePathOffsetUnicode = bb.getInt();
commonPathSuffixOffsetUnicode = bb.getInt();
}
if ((linkInfoFlags & LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
== LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag()) {
bb.position(startOfLinkInfo+volumeIdOffset);
int volumeIdSize = bb.getInt();
driveType = DriveType.valueOf(bb.getInt());
driveSerialNumber = bb.getInt();
int volumeLabelOffset = bb.getInt();
if (volumeLabelOffset != 0x14) {
volumeLabel = parseString(startOfLinkInfo + volumeIdOffset + volumeLabelOffset, false, volumeIdSize - 0x10);
} else {
int volumeLabelOffsetUnicode = bb.getInt();
volumeLabel = parseString(startOfLinkInfo + volumeIdOffset + volumeLabelOffsetUnicode, false, volumeIdSize - 0x14);
}
localBasePath = parseLocalBasePath(startOfLinkInfo + localBasePathOffset, false);
}
if ((linkInfoFlags & LnkEnums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix.getFlag())
== LnkEnums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix.getFlag()) {
bb.position(startOfLinkInfo+commonNetworkRelativeLinkOffset);
int commonNetworkRelativeLinkSize = bb.getInt();
commonNetworkRelativeLinkFlags = bb.getInt();
int netNameOffset = bb.getInt();
unicodeNetAndDeviceName = netNameOffset > 0x14;
int deviceNameOffset = bb.getInt();
int netType = bb.getInt();
int netNameOffsetUnicode = 0;
int deviceNameOffsetUnicode = 0;
if (unicodeNetAndDeviceName) {
netNameOffsetUnicode = bb.getInt();
deviceNameOffsetUnicode = bb.getInt();
}
netName = parseNetName(startOfLinkInfo + commonNetworkRelativeLinkOffset + netNameOffset, false);
if (unicodeNetAndDeviceName) {
netNameUnicode = parseNetName(startOfLinkInfo + commonNetworkRelativeLinkOffset + netNameOffsetUnicode, true);
}
if ((commonNetworkRelativeLinkFlags & LnkEnums.CommonNetworkRelativeLinkFlags.ValidNetType.getFlag())
== LnkEnums.CommonNetworkRelativeLinkFlags.ValidNetType.getFlag()) {
networkProviderType = LnkEnums.NetworkProviderType.valueOf(netType);
}
if ((commonNetworkRelativeLinkFlags & LnkEnums.CommonNetworkRelativeLinkFlags.ValidDevice.getFlag())
== LnkEnums.CommonNetworkRelativeLinkFlags.ValidDevice.getFlag()) {
deviceName = parseDeviceName(startOfLinkInfo + commonNetworkRelativeLinkOffset + deviceNameOffset, false);
if (unicodeNetAndDeviceName) {
deviceNameUnicode = parseDeviceName(startOfLinkInfo + commonNetworkRelativeLinkOffset + deviceNameOffsetUnicode, true);
}
}
}
commonPathSuffix = parseCommonPathSuffix(startOfLinkInfo + commonPathSuffixOffset, false);
if (((linkInfoFlags & LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
== LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
&& hasUnicodeLocalBaseAndCommonSuffixOffset) {
localBasePathUnicode = parseLocalBasePath(startOfLinkInfo + localBasePathOffsetUnicode, true);
commonPathSuffixUnicode = parseCommonPathSuffix(startOfLinkInfo + commonPathSuffixOffsetUnicode, true);
}
bb.position(startOfLinkInfo+linkInfoSize);
}
String name = null;
if((linkFlags & LnkEnums.LinkFlags.HasName.getFlag()) ==
LnkEnums.LinkFlags.HasName.getFlag()) {
name = readStringData(bb);
}
String relativePath = null;
if((linkFlags & LnkEnums.LinkFlags.HasRelativePath.getFlag()) ==
LnkEnums.LinkFlags.HasRelativePath.getFlag()) {
relativePath = readStringData(bb);
}
String workingDir = null;
if((linkFlags & LnkEnums.LinkFlags.HasWorkingDir.getFlag()) ==
LnkEnums.LinkFlags.HasWorkingDir.getFlag()) {
workingDir = readStringData(bb);
}
String arguments = null;
if((linkFlags & LnkEnums.LinkFlags.HasArguments.getFlag()) ==
LnkEnums.LinkFlags.HasArguments.getFlag()) {
arguments = readStringData(bb);
}
String iconLocation = null;
if((linkFlags & LnkEnums.LinkFlags.HasIconLocation.getFlag()) ==
LnkEnums.LinkFlags.HasIconLocation.getFlag()) {
iconLocation = readStringData(bb);
}
return new JLNK(header, linkClassIdentifier.array(), linkFlags, fileAttributes,
crtime, atime, mtime, fileSize, iconIndex, showCommand, hotkey,
linkTargetIdList,
hasUnicodeLocalBaseAndCommonSuffixOffset, localBasePath,
commonPathSuffix, localBasePathUnicode, commonPathSuffixUnicode,
name, relativePath, workingDir, arguments, iconLocation, driveSerialNumber,
driveType, volumeLabel, commonNetworkRelativeLinkFlags,
networkProviderType, unicodeNetAndDeviceName, netName, netNameUnicode,
deviceName, deviceNameUnicode);
}
private String readStringData(ByteBuffer bb) {
short countCharacters = bb.getShort();
if(countCharacters == 0) {
return null;
}
byte[] theString = new byte[countCharacters*2];
bb.get(theString);
try {
return new String(theString, "UTF-16LE");
} catch (UnsupportedEncodingException ex) {
logger.info("Shouldn't happen");
return null;
}
}
private String parseString(int offset, boolean unicode, int maxlen) {
ByteBuffer bb = ByteBuffer.wrap(content);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.position(offset);
StringBuilder sb = new StringBuilder(bb.limit());
int i = 0;
while (bb.remaining() > 0 && (i < maxlen || maxlen == -1)) // safer
{
char c;
if(unicode) {
c = bb.getChar();
} else {
c = (char) bb.get();
}
if (c == '\0') {
break;
}
sb.append(c);
i++;
}
return sb.toString();
}
private String parseCommonPathSuffix(int offset, boolean unicode) {
return parseString(offset, unicode, -1);
}
private String parseLocalBasePath(int offset, boolean unicode) {
return parseString(offset, unicode, -1);
}
private String parseNetName(int offset, boolean unicode) {
return parseString(offset, unicode, -1);
}
private String parseDeviceName(int offset, boolean unicode) {
return parseString(offset, unicode, -1);
}
private List<String> parseLinkTargetIdList(List<byte[]> idList) {
List<String> ret = new ArrayList<String>();
if(!idList.isEmpty()) {
CommonCLSIDS clsid = CommonCLSIDS.valueOf(Arrays.copyOfRange(idList.remove(0), 2, 18));
switch (clsid) {
case CDrivesFolder:
ret.add(new String(Arrays.copyOfRange(idList.remove(0), 1, 17)).split("\0")[0]);
ret.addAll(parsePathElements(idList));
break;
case CMyDocsFolder:
ret.addAll(parsePathElements(idList));
break;
case IEFrameDLL:
break;
case Unknown:
break;
default:
break;
}
}
return ret;
}
private List<String> parsePathElements(List<byte[]> idList) {
List<String> ret = new ArrayList<String>();
for (byte[] pathElement : idList) {
ByteBuffer bb = ByteBuffer.wrap(pathElement);
bb.order(ByteOrder.LITTLE_ENDIAN);
int offset = bb.getShort(bb.limit() - 2)-2;
if (pathElement[offset + 0x02] < 0x03
|| pathElement[offset + 0x10] >= pathElement[offset]
|| pathElement[offset + 0x10] < 0x14) {
ret.add(get0xC(bb));
continue;
}
if (pathElement[offset + 0x10] != 0) {
ret.add(getStringAt(bb, offset + pathElement[offset + 0x10], true));
continue;
} else {
if (pathElement[offset + 0x12] >= pathElement[offset]
|| pathElement[offset + 0x12] < 0x14) {
ret.add(get0xC(bb));
continue;
} else {
ret.add(getStringAt(bb, offset + pathElement[offset + 0x12], false));
continue;
}
}
}
return ret;
}
private String get0xC(ByteBuffer bb) {
return getStringAt(bb, 0xC, false);
}
private String getStringAt(ByteBuffer bb, int offset, boolean unicode) {
byte[] nameArr = Arrays.copyOfRange(bb.array(), offset, bb.limit());
if (unicode) {
try {
return new String(nameArr, "UTF-16LE").split("\0")[0];
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(JLnkParser.class.getName()).log(Level.SEVERE, null, ex);
}
}
return new String(nameArr).split("\0")[0];
}
}

View File

@ -0,0 +1,247 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012 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.coreutils;
/**
*
* @author dick
*/
public class LnkEnums {
private static final byte[] CDRIVES = new byte[] { (byte)0xe0, 0x4f, (byte)0xd0, 0x20,
(byte)0xea, 0x3a, 0x69, 0x10, (byte)0xa2, (byte)0xd8, 0x08, 0x00, 0x2b, 0x30, 0x30, (byte)0x9d };
private static final byte[] CMYDOCS = new byte[] { (byte)0xba, (byte)0x8a, 0x0d,
0x45, 0x25, (byte)0xad, (byte)0xd0, 0x11, (byte)0x98, (byte)0xa8, 0x08, 0x00, 0x36, 0x1b, 0x11, 0x03 };
private static final byte[] IEFRAME = new byte[] { (byte)0x80, 0x53, 0x1c, (byte)0x87, (byte)0xa0,
0x42, 0x69, 0x10, (byte)0xa2, (byte)0xea, 0x08, 0x00, 0x2b, 0x30, 0x30, (byte)0x9d };
public enum CommonCLSIDS {
CDrivesFolder(CDRIVES),
CMyDocsFolder(CMYDOCS),
IEFrameDLL(IEFRAME),
Unknown(new byte[16]);
private byte[] flag;
private CommonCLSIDS(byte[] flag) {
this.flag = flag;
}
static CommonCLSIDS valueOf(byte[] type) {
for(CommonCLSIDS value : CommonCLSIDS.values()) {
if(java.util.Arrays.equals(value.flag, type)) {
return value;
}
}
return Unknown;
}
}
public enum LinkFlags {
HasLinkTargetIDList(0x00000001),
HasLinkInfo(0x00000002),
HasName(0x00000004),
HasRelativePath(0x00000008),
HasWorkingDir(0x00000010),
HasArguments(0x00000020),
HasIconLocation(0x00000040),
IsUnicode(0x00000080),
ForceNoLinkInfo(0x00000100),
HasExpString(0x00000200),
RunInSeparateProcess(0x00000400),
Unused1(0x00000800),
HasDarwinID(0x00001000),
RunAsUser(0x00002000),
HasExpIcon(0x00004000),
NoPidlAlias(0x00008000),
Unused2(0x00010000),
RunWithShimLayer(0x00020000),
ForceNoLinkTrack(0x00040000),
EnableTargetMetaData(0x00080000),
DisableLinkPathTracking(0x00100000),
DisableKnownFolderTracking(0x00200000),
DisableKnownFolderAlias(0x00400000),
AllowLinkToLink(0x00800000),
UnaliasOnSave(0x01000000),
PreferEnvironmentPath(0x02000000),
KeepLocalIDListForUNCTarget(0x04000000);
private int flag;
private LinkFlags(int flag) {
this.flag = flag;
}
public int getFlag() {
return flag;
}
}
public enum DriveType {
DRIVE_UNKNOWN(0x00000000),
DRIVE_NO_ROOT_DIR(0x00000001),
DRIVE_REMOVABLE(0x00000002),
DRIVE_FIXED(0x00000003),
DRIVE_REMOTE(0x00000004),
DRIVE_CDROM(0x00000005),
DRIVE_RAMDISK(0x00000006);
private int flag;
private DriveType(int flag) {
this.flag = flag;
}
public int getFlag() {
return flag;
}
static DriveType valueOf(int type) {
for(DriveType value : DriveType.values()) {
if(value.flag == type) {
return value;
}
}
return DRIVE_UNKNOWN;
}
}
public enum FileAttributesFlags {
READONLY(0x00000001),
HIDDEN(0x00000002),
SYSTEM(0x00000004),
RESERVED1(0x00000008),
DIRECTORY(0x00000010),
ARCHIVE(0x00000020),
RESERVED2(0x00000040),
NORMAL(0x00000080),
TEMPORARY(0x00000100),
SPARSE_FILE(0x00000200),
REPARSE_POINT(0x00000400),
COMPRESSED(0x00000800),
OFFLINE(0x00001000),
NOT_CONTENT_INDEXED(0x00002000),
ENCRYPTED(0x00004000);
private int flag;
private FileAttributesFlags(int flag) {
this.flag = flag;
}
public int getFlag() {
return flag;
}
}
public enum LinkInfoFlags {
VolumeIDAndLocalBasePath(0x00000001),
CommonNetworkRelativeLinkAndPathSuffix(0x00000002);
private int flag;
private LinkInfoFlags(int flag) {
this.flag = flag;
}
public int getFlag() {
return flag;
}
}
public enum CommonNetworkRelativeLinkFlags {
ValidDevice(0x00000001),
ValidNetType(0x00000002);
private int flag;
private CommonNetworkRelativeLinkFlags(int flag) {
this.flag = flag;
}
public int getFlag() {
return flag;
}
}
public enum NetworkProviderType {
WNNC_NET_AVID(0x001A0000),
WNNC_NET_DOCUSPACE(0x001B0000),
WNNC_NET_MANGOSOFT(0x001C0000),
WNNC_NET_SERNET(0x001D0000),
WNNC_NET_RIVERFRONT1(0x001E0000),
WNNC_NET_RIVERFRONT2(0x001F0000),
WNNC_NET_DECORB(0x00200000),
WNNC_NET_PROTSTOR(0x00210000),
WNNC_NET_FJ_REDIR(0x00220000),
WNNC_NET_DISTINCT(0x00230000),
WNNC_NET_TWINS(0x00240000),
WNNC_NET_RDR2SAMPLE(0x00250000),
WNNC_NET_CSC(0x00260000),
WNNC_NET_3IN1(0x00270000),
WNNC_NET_EXTENDNET(0x00290000),
WNNC_NET_STAC(0x002A0000),
WNNC_NET_FOXBAT(0x002B0000),
WNNC_NET_YAHOO(0x002C0000),
WNNC_NET_EXIFS(0x002D0000),
WNNC_NET_DAV(0x002E0000),
WNNC_NET_KNOWARE(0x002F0000),
WNNC_NET_OBJECT_DIRE(0x00300000),
WNNC_NET_MASFAX(0x00310000),
WNNC_NET_HOB_NFS(0x00320000),
WNNC_NET_SHIVA(0x00330000),
WNNC_NET_IBMAL(0x00340000),
WNNC_NET_LOCK(0x00350000),
WNNC_NET_TERMSRV(0x00360000),
WNNC_NET_SRT(0x00370000),
WNNC_NET_QUINCY(0x00380000),
WNNC_NET_OPENAFS(0x00390000),
WNNC_NET_AVID1(0x003A0000),
WNNC_NET_DFS(0x003B0000),
WNNC_NET_KWNP(0x003C0000),
WNNC_NET_ZENWORKS(0x003D0000),
WNNC_NET_DRIVEONWEB(0x003E0000),
WNNC_NET_VMWARE(0x003F0000),
WNNC_NET_RSFX(0x00400000),
WNNC_NET_MFILES(0x00410000),
WNNC_NET_MS_NFS(0x00420000),
WNNC_NET_GOOGLE(0x00430000),
WNNC_NET_UNKNOWN(0x00000000);
private int flag;
private NetworkProviderType(int flag) {
this.flag = flag;
}
static NetworkProviderType valueOf(int type) {
for(NetworkProviderType value : NetworkProviderType.values()) {
if(value.flag == type) {
return value;
}
}
return WNNC_NET_UNKNOWN;
}
public int getFlag() {
return flag;
}
}
}

View File

@ -1,12 +1,26 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
* 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.report;
package org.sleuthkit.autopsy.coreutils;
/**
*
* @author Alex
* Utility to measure time elapsed, useful for debugging.
*/
public class StopWatch {

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -18,29 +18,72 @@
*/
package org.sleuthkit.autopsy.coreutils;
import org.openide.util.NbBundle;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
*
* @author dfickling
* Utility to get version and build settings set at build time
*/
public class Version {
private Version() { }
private static Properties versionProperties;
private Version() {
}
public enum Type {
public enum Type{
RELEASE, DEVELOPMENT;
}
private static void loadVersionProperty() {
if (versionProperties != null) {
return;
}
versionProperties = new Properties();
try {
InputStream inputStream = Version.class.getResourceAsStream("Version.properties");
versionProperties.load(inputStream);
} catch (IOException e) {
versionProperties = null;
}
}
private static String getVersionProperty(String property) {
loadVersionProperty();
if (versionProperties == null) {
return "";
} else {
return versionProperties.getProperty(property);
}
}
/**
* Get the application version as set at build time
* @return application version string
*/
public static String getVersion() {
return NbBundle.getMessage(Version.class, "app.version");
return getVersionProperty("app.version");
}
/**
* Get the application name as set at build time
* @return the application name string
*/
public static String getName() {
return NbBundle.getMessage(Version.class, "app.name");
return getVersionProperty("app.name");
}
/**
* Get the application build type as set at build time
* @return the application build type
*/
public static Version.Type getBuildType() {
return Type.valueOf(NbBundle.getMessage(Version.class, "build.type"));
String valueProp = getVersionProperty("build.type");
return Type.valueOf(valueProp);
}
}

View File

@ -6,6 +6,15 @@
<code-name-base>org.sleuthkit.autopsy.datamodel</code-name-base>
<suite-component/>
<module-dependencies>
<dependency>
<code-name-base>org.netbeans.api.progress</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.28.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>

View File

@ -21,11 +21,15 @@ package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.datamodel.AbstractFile;
/**
*
* @author dfickling
* An abstract node that encapsulates AbstractFile data
* @param <T> type of the AbstractFile to encapsulate
*/
abstract class AbstractAbstractFileNode<T extends AbstractFile> extends AbstractContentNode<T> {
/**
* @param <T> type of the AbstractFile data to encapsulate
* @param abstractFile file to encapsulate
*/
AbstractAbstractFileNode(T abstractFile) {
super(abstractFile);
}

View File

@ -129,6 +129,11 @@ abstract class AbstractContentChildren extends Keys<Object> {
return hh.new HashsetHitsRootNode();
}
@Override
public AbstractNode visit(EmailExtracted ee) {
return ee.new EmailExtractedRootNode();
}
@Override
public AbstractNode visit(Images i) {
try {

View File

@ -21,10 +21,8 @@ package org.sleuthkit.autopsy.datamodel;
import java.text.SimpleDateFormat;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TimeZone;
import org.openide.nodes.Sheet;
import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.TskException;
/**
* Abstract class that implements the commonality between File and Directory
@ -181,11 +179,17 @@ public abstract class AbstractFsContentNode<T extends FsContent> extends Abstrac
this(fsContent, true);
}
// The param 'directoryBrowseMode' refers to how the user caused this node
// to be created: if by browsing the image contents, it is true. If by
// selecting a file filter (e.g. 'type' or 'recent'), it is false
/**
* Constructor
* @param fsContent the fsContent
* @param directoryBrowseMode how the user caused this node
* to be created: if by browsing the image contents, it is true. If by
* selecting a file filter (e.g. 'type' or 'recent'), it is false
*/
AbstractFsContentNode(T fsContent, boolean directoryBrowseMode) {
super(fsContent);
this.setDisplayName(AbstractFsContentNode.getFsContentName(fsContent));
this.directoryBrowseMode = directoryBrowseMode;
}
@ -222,11 +226,12 @@ public abstract class AbstractFsContentNode<T extends FsContent> extends Abstrac
/**
* Fill map with FsContent properties
* @param map, with preserved ordering, where property names/values are put
*
* @param map map with preserved ordering, where property names/values are put
* @param content to extract properties from
*/
public static void fillPropertyMap(Map<String, Object> map, FsContent content) {
map.put(FsContentPropertyType.NAME.toString(), content.getName());
map.put(FsContentPropertyType.NAME.toString(), getFsContentName(content));
map.put(FsContentPropertyType.LOCATION.toString(), DataConversion.getformattedPath(ContentUtils.getDisplayPath(content), 0, 1));
map.put(FsContentPropertyType.MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content));
map.put(FsContentPropertyType.CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content));
@ -245,4 +250,14 @@ public abstract class AbstractFsContentNode<T extends FsContent> extends Abstrac
map.put(FsContentPropertyType.KNOWN.toString(), content.getKnown().getName());
map.put(FsContentPropertyType.MD5HASH.toString(), content.getMd5Hash() == null ? "" : content.getMd5Hash());
}
static String getFsContentName(FsContent fsContent) {
String name = fsContent.getName();
if(name.equals("..")) {
name = DirectoryNode.DOTDOTDIR;
} else if(name.equals(".")) {
name = DirectoryNode.DOTDIR;
}
return name;
}
}

View File

@ -30,8 +30,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskException;
/**
*
* @author dfickling
* Node encapsulating blackboard artifact type
*/
public class ArtifactTypeNode extends AbstractNode implements DisplayableItemNode{
@ -98,6 +97,9 @@ public class ArtifactTypeNode extends AbstractNode implements DisplayableItemNod
return "recent_docs.png";
case TSK_DEVICE_ATTACHED:
return "usb_devices.png";
case TSK_WEB_SEARCH_QUERY:
return "searchquery.png";
}
return "artifact-icon.png";
}

View File

@ -32,6 +32,7 @@ public interface AutopsyItemVisitor<T> {
T visit(RecentFiles.RecentFilesFilter rff);
T visit(KeywordHits kh);
T visit(HashsetHits hh);
T visit(EmailExtracted ee);
T visit(Images i);
T visit(Views v);
T visit(Results r);
@ -80,6 +81,11 @@ public interface AutopsyItemVisitor<T> {
return defaultVisit(hh);
}
@Override
public T visit(EmailExtracted ee) {
return defaultVisit(ee);
}
@Override
public T visit(Images i) {
return defaultVisit(i);

View File

@ -19,14 +19,12 @@
package org.sleuthkit.autopsy.datamodel;
/**
*
* @author dfickling
* Abstraction for certain top level items displayed in the GUI
*/
public interface AutopsyVisitableItem {
/**
* visitor pattern support
* @param <T> visitor return type
* @param v visitor
* @return visitor return value
*/

View File

@ -36,8 +36,7 @@ import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskException;
/**
*
* @author dfickling
* Node wrapping a blackboard artifact object
*/
public class BlackboardArtifactNode extends AbstractNode implements DisplayableItemNode{
@ -94,8 +93,8 @@ public class BlackboardArtifactNode extends AbstractNode implements DisplayableI
/**
* Fill map with Artifact properties
* @param map, with preserved ordering, where property names/values are put
* @param content to extract properties from
* @param map map with preserved ordering, where property names/values are put
* @param artifact to extract properties from
*/
private void fillPropertyMap(Map<String, Object> map, BlackboardArtifact artifact) {
try {

View File

@ -42,13 +42,13 @@ class ContentChildren extends AbstractContentChildren {
List<Content> children = ContentHierarchyVisitor.getChildren(parent);
// To not display LayoutFiles
Iterator<Content> it = children.iterator();
while(it.hasNext()) {
Content child = it.next();
if(child instanceof LayoutFile) {
it.remove();
}
}
// Iterator<Content> it = children.iterator();
// while(it.hasNext()) {
// Content child = it.next();
// if(child instanceof LayoutFile) {
// it.remove();
// }
// }
setKeys(children.subList(0, Math.min(children.size(), MAX_CHILD_COUNT)));
}

View File

@ -28,9 +28,8 @@ public interface ContentNode extends DisplayableItemNode{
/**
* Visitor pattern support.
*
* @param <T> visitor return type
* @param v visitor
* @return visitor return value
* @return visitor's visit return value
*/
<T> T accept(ContentNodeVisitor<T> v);
}

View File

@ -28,6 +28,8 @@ import java.util.List;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingWorker;
import org.netbeans.api.progress.ProgressHandle;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentVisitor;
import org.sleuthkit.datamodel.Directory;
@ -214,25 +216,47 @@ public final class ContentUtils {
* it does
* @throws IOException
*/
public static void writeToFile(Content content, java.io.File outputFile) throws IOException {
public static void writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, SwingWorker worker, boolean source) throws IOException {
InputStream in = new ReadContentInputStream(content);
boolean append = false;
FileOutputStream out = new FileOutputStream(outputFile, append);
// Get the unit size for a progress bar
int unit = (int) (content.getSize() / 100);
long totalRead = 0;
try {
byte[] buffer = new byte[TO_FILE_BUFFER_SIZE];
int len = in.read(buffer);
while (len != -1) {
// If there is a worker, check for a cancelation
if (worker!=null && worker.isCancelled()) {
break;
}
out.write(buffer, 0, len);
len = in.read(buffer);
totalRead+=len;
// If there is a progress bar and this is the source file,
// report any progress
if(progress!=null && source && totalRead>=TO_FILE_BUFFER_SIZE) {
int totalProgress = (int) (totalRead / unit);
progress.progress(content.getName(), totalProgress);
// If it's not the source, just update the file being processed
} else if(progress!=null && !source) {
progress.progress(content.getName());
}
}
} finally {
out.close();
}
}
public static void writeToFile(Content content, java.io.File outputFile) throws IOException {
writeToFile(content, outputFile, null, null, false);
}
/**
* Helper to ignore the '.' and '..' directories
*/
@ -250,11 +274,21 @@ public final class ContentUtils {
public static class ExtractFscContentVisitor extends ContentVisitor.Default<Void> {
java.io.File dest;
ProgressHandle progress;
SwingWorker worker;
boolean source = false;
/**
* Make new extractor for a specific destination
* @param dest The file/folder visited will be extracted as this file
*/
public ExtractFscContentVisitor(java.io.File dest, ProgressHandle progress, SwingWorker worker, boolean source) {
this.dest = dest;
this.progress = progress;
this.worker = worker;
this.source = source;
}
public ExtractFscContentVisitor(java.io.File dest) {
this.dest = dest;
}
@ -263,13 +297,13 @@ public final class ContentUtils {
* Convenience method to make a new instance for given destination
* and extract given content
*/
public static void extract(Content cntnt, java.io.File dest) {
cntnt.accept(new ExtractFscContentVisitor(dest));
public static void extract(Content cntnt, java.io.File dest, ProgressHandle progress, SwingWorker worker) {
cntnt.accept(new ExtractFscContentVisitor(dest, progress, worker, true));
}
public Void visit(File f) {
try {
ContentUtils.writeToFile(f, dest);
ContentUtils.writeToFile(f, dest, progress, worker, source);
} catch (IOException ex) {
logger.log(Level.SEVERE,
"Trouble extracting file to " + dest.getAbsolutePath(),
@ -292,12 +326,23 @@ public final class ContentUtils {
DestFileContentVisitor destFileCV = new DestFileContentVisitor();
try {
int numProcessed = 0;
// recurse on children
for (Content child : dir.getChildren()) {
java.io.File childFile = child.accept(destFileCV);
ExtractFscContentVisitor childVisitor =
new ExtractFscContentVisitor(childFile);
new ExtractFscContentVisitor(childFile, progress, worker, false);
// If this is the source directory of an extract it
// will have a progress and worker, and will keep track
// of the progress bar's progress
if(worker!=null && worker.isCancelled()) {
break;
}
if(progress!=null && source) {
progress.progress(child.getName(), numProcessed);
}
child.accept(childVisitor);
numProcessed++;
}
} catch (TskException ex) {
logger.log(Level.SEVERE,

View File

@ -28,30 +28,17 @@ import org.sleuthkit.datamodel.TskData;
*/
public class DirectoryNode extends AbstractFsContentNode<Directory> {
/**
* Helper so that the display name and the name used in building the path
* are determined the same way.
* @param d Directory to get the name of
* @return short name for the directory
*/
static String nameForDirectory(Directory d) {
return d.getName();
}
public static final String DOTDOTDIR = "[parent folder]";
public static final String DOTDIR = "[current folder]";
public DirectoryNode(Directory dir) {
this(dir, true);
}
/**
*
* @param dir Underlying Content instance
*/
public DirectoryNode(Directory dir, boolean directoryBrowseMode) {
super(dir, directoryBrowseMode);
// set name, display name, and icon
String dirName = nameForDirectory(dir);
this.setDisplayName(dirName);
if (Directory.dirFlagToValue(dir.getDir_flags()).equals(TskData.TSK_FS_NAME_FLAG_ENUM.TSK_FS_NAME_FLAG_UNALLOC.toString())) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-deleted.png");
} else {
@ -79,4 +66,7 @@ public class DirectoryNode extends AbstractFsContentNode<Directory> {
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
}
}

View File

@ -18,6 +18,7 @@
*/
package org.sleuthkit.autopsy.datamodel;
/**
* Interface for all displayable Nodes
*/
@ -26,9 +27,8 @@ public interface DisplayableItemNode{
/**
* Visitor pattern support.
*
* @param <T> visitor return type
* @param v visitor
* @return visitor return value
* @return visitor's visit return value
*/
<T> T accept(DisplayableItemNodeVisitor<T> v);
}

View File

@ -18,6 +18,9 @@
*/
package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedAccountNode;
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedFolderNode;
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedRootNode;
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsRootNode;
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsSetNode;
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsKeywordNode;
@ -45,6 +48,9 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(KeywordHitsKeywordNode khmln);
T visit(HashsetHitsRootNode hhrn);
T visit(HashsetHitsSetNode hhsn);
T visit(EmailExtractedRootNode eern);
T visit(EmailExtractedAccountNode eean);
T visit(EmailExtractedFolderNode eefn);
T visit(ViewsNode vn);
T visit(ResultsNode rn);
T visit(ImagesNode in);
@ -159,6 +165,21 @@ public interface DisplayableItemNodeVisitor<T> {
return defaultVisit(hhsn);
}
@Override
public T visit(EmailExtractedRootNode eern) {
return defaultVisit(eern);
}
@Override
public T visit(EmailExtractedAccountNode eean) {
return defaultVisit(eean);
}
@Override
public T visit(EmailExtractedFolderNode eefn) {
return defaultVisit(eefn);
}
@Override
public T visit(LayoutFileNode lcn) {
return defaultVisit(lcn);

View File

@ -0,0 +1,376 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datamodel;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskException;
/**
* Support for TSK_EMAIL_MSG nodes and displaying emails in the directory tree
* Email messages are grouped into parent folders, and the folders are grouped
* into parent accounts if TSK_PATH is available to define the relationship
* structure for every message
*/
public class EmailExtracted implements AutopsyVisitableItem {
private static final String LABEL_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getLabel();
private static final String DISPLAY_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getDisplayName();
private static final Logger logger = Logger.getLogger(EmailExtracted.class.getName());
private static final String MAIL_ACCOUNT = "Account";
private static final String MAIL_FOLDER = "Folder";
private static final String MAIL_PATH_SEPARATOR = "/";
private SleuthkitCase skCase;
private Map<String, Map<String, List<Long>>> accounts;
public EmailExtracted(SleuthkitCase skCase) {
this.skCase = skCase;
accounts = new LinkedHashMap<String, Map<String, List<Long>>>();
}
private void initArtifacts() {
accounts.clear();
try {
int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID();
int pathAttrId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID();
String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id "
+ "FROM blackboard_attributes,blackboard_artifacts WHERE "
+ "attribute_type_id=" + pathAttrId
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id"
+ " AND blackboard_artifacts.artifact_type_id=" + artId;
ResultSet rs = skCase.runQuery(query);
while (rs.next()) {
final String path = rs.getString("value_text");
final long artifactId = rs.getLong("artifact_id");
final Map<String, String> parsedPath = parsePath(path);
final String account = parsedPath.get(MAIL_ACCOUNT);
final String folder = parsedPath.get(MAIL_FOLDER);
Map<String, List<Long>> folders = accounts.get(account);
if (folders == null) {
folders = new LinkedHashMap<String, List<Long>>();
accounts.put(account, folders);
}
List<Long> messages = folders.get(folder);
if (messages == null) {
messages = new ArrayList<Long>();
folders.put(folder, messages);
}
messages.add(artifactId);
}
skCase.closeRunQuery(rs);
} catch (SQLException ex) {
logger.log(Level.WARNING, "Cannot initialize email extraction", ex);
}
}
private static Map<String, String> parsePath(String path) {
Map<String, String> parsed = new HashMap<String, String>();
String[] split = path.split(MAIL_PATH_SEPARATOR);
if (split.length < 4) {
logger.log(Level.WARNING, "Unexpected number of tokens when parsing email PATH: "
+ split.length + ", will use defaults");
parsed.put(MAIL_ACCOUNT, "Default");
parsed.put(MAIL_FOLDER, "Default");
return parsed;
}
parsed.put(MAIL_ACCOUNT, split[2]);
parsed.put(MAIL_FOLDER, split[3]);
return parsed;
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
}
/**
* Mail root node showing all emails
*/
public class EmailExtractedRootNodeFlat extends AbstractNode implements DisplayableItemNode {
public EmailExtractedRootNodeFlat() {
super(Children.create(new EmailExtractedRootChildrenFlat(), true), Lookups.singleton(DISPLAY_NAME));
super.setName(LABEL_NAME);
super.setDisplayName(DISPLAY_NAME);
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/mail-icon-16.png");
initArtifacts();
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
//return v.visit(this);
return null;
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
}
ss.put(new NodeProperty("Name",
"Name",
"no description",
getName()));
return s;
}
}
/**
* Mail root child node showing flattened emails
*/
private class EmailExtractedRootChildrenFlat extends ChildFactory<BlackboardArtifact> {
private EmailExtractedRootChildrenFlat() {
super();
}
@Override
protected boolean createKeys(List<BlackboardArtifact> list) {
//flatten all emails
for (String account : accounts.keySet()) {
Map<String, List<Long>> folders = accounts.get(account);
for (String folder : folders.keySet()) {
List<Long> messages = folders.get(folder);
for (long l : messages) {
try {
//TODO: bulk artifact gettings
list.add(skCase.getBlackboardArtifact(l));
} catch (TskException ex) {
logger.log(Level.WARNING, "Error creating mail messages nodes", ex);
}
}
}
}
return true;
}
@Override
protected Node createNodeForKey(BlackboardArtifact artifact) {
return new BlackboardArtifactNode(artifact);
}
}
/**
* Mail root node grouping all mail accounts, supports account-> folder
* structure
*/
public class EmailExtractedRootNode extends AbstractNode implements DisplayableItemNode {
public EmailExtractedRootNode() {
super(Children.create(new EmailExtractedRootChildren(), true), Lookups.singleton(DISPLAY_NAME));
super.setName(LABEL_NAME);
super.setDisplayName(DISPLAY_NAME);
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/mail-icon-16.png");
initArtifacts();
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
//return null;
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
}
ss.put(new NodeProperty("Name",
"Name",
"no description",
getName()));
return s;
}
}
/**
* Mail root child node creating each account node
*/
private class EmailExtractedRootChildren extends ChildFactory<String> {
@Override
protected boolean createKeys(List<String> list) {
list.addAll(accounts.keySet());
return true;
}
@Override
protected Node createNodeForKey(String key) {
return new EmailExtractedAccountNode(key, accounts.get(key));
}
}
/**
* Account node representation
*/
public class EmailExtractedAccountNode extends AbstractNode implements DisplayableItemNode {
public EmailExtractedAccountNode(String name, Map<String, List<Long>> children) {
super(Children.create(new EmailExtractedAccountChildrenNode(children), true), Lookups.singleton(name));
super.setName(name);
super.setDisplayName(name + " (" + children.size() + ")");
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/account-icon-16.png");
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
}
ss.put(new NodeProperty("Name",
"Name",
"no description",
getName()));
return s;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
}
}
/**
* Account node child creating sub nodes for every folder
*/
private class EmailExtractedAccountChildrenNode extends ChildFactory<String> {
private Map<String, List<Long>> folders;
private EmailExtractedAccountChildrenNode(Map<String, List<Long>> folders) {
super();
this.folders = folders;
}
@Override
protected boolean createKeys(List<String> list) {
list.addAll(folders.keySet());
return true;
}
@Override
protected Node createNodeForKey(String key) {
return new EmailExtractedFolderNode(key, folders.get(key));
}
}
/**
* Node representing mail folder
*/
public class EmailExtractedFolderNode extends AbstractNode implements DisplayableItemNode {
public EmailExtractedFolderNode(String name, List<Long> children) {
super(Children.create(new EmailExtractedFolderChildrenNode(children), true), Lookups.singleton(name));
super.setName(name);
super.setDisplayName(name + " (" + children.size() + ")");
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-16.png");
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
}
ss.put(new NodeProperty("Name",
"Name",
"no description",
getName()));
return s;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
}
}
/**
* Node representing mail folder content (mail messages)
*/
private class EmailExtractedFolderChildrenNode extends ChildFactory<BlackboardArtifact> {
private List<Long> messages;
private EmailExtractedFolderChildrenNode(List<Long> messages) {
super();
this.messages = messages;
}
@Override
protected boolean createKeys(List<BlackboardArtifact> list) {
for (long l : messages) {
try {
//TODO: bulk artifact gettings
list.add(skCase.getBlackboardArtifact(l));
} catch (TskException ex) {
logger.log(Level.WARNING, "Error creating mail messages nodes", ex);
}
}
return true;
}
@Override
protected Node createNodeForKey(BlackboardArtifact artifact) {
return new BlackboardArtifactNode(artifact);
}
}
}

View File

@ -47,6 +47,7 @@ public class ExtractedContentChildren extends ChildFactory<BlackboardArtifact.AR
list.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT);
list.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_INSTALLED_PROG);
list.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
list.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY);
return true;
}

View File

@ -25,8 +25,7 @@ import org.openide.util.lookup.Lookups;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
*
* @author dfickling
* Node for the extracted content
*/
public class ExtractedContentNode extends AbstractNode implements DisplayableItemNode{

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.datamodel;
import javax.swing.Action;
import org.openide.nodes.Sheet;
import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.TskData;
@ -31,17 +30,6 @@ import org.sleuthkit.datamodel.TskData;
public class FileNode extends AbstractFsContentNode<File> {
/**
* Helper so that the display name and the name used in building the path
* are determined the same way.
* @param f File to get the name of
* @return short name for the File
*/
static String nameForFile(File f) {
return f.getName();
}
/**
*
* @param file underlying Content
*/
public FileNode(File file) {
@ -52,12 +40,10 @@ public class FileNode extends AbstractFsContentNode<File> {
super(file, directoryBrowseMode);
// set name, display name, and icon
String fileName = nameForFile(file);
this.setDisplayName(fileName);
if (File.dirFlagToValue(file.getDir_flags()).equals(TskData.TSK_FS_NAME_FLAG_ENUM.TSK_FS_NAME_FLAG_UNALLOC.toString())) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png");
} else {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon.png");
this.setIconBaseWithExtension(getIconForFileType(file));
}
}
@ -81,4 +67,52 @@ public class FileNode extends AbstractFsContentNode<File> {
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
}
// Given a file, returns the correct icon for said
// file based off it's extension
static String getIconForFileType(File file) {
// Get the name, extension
String name = file.getName();
int dotIndex = name.lastIndexOf(".");
if (dotIndex == -1) {
return "org/sleuthkit/autopsy/images/file-icon.png";
}
String ext = name.substring(dotIndex).toLowerCase();
// Images
for(String s:FileTypeExtensions.getImageExtensions()) {
if(ext.equals(s)) { return "org/sleuthkit/autopsy/images/image-file.png"; }
}
// Videos
for(String s:FileTypeExtensions.getVideoExtensions()) {
if(ext.equals(s)) { return "org/sleuthkit/autopsy/images/video-file.png"; }
}
// Audio Files
for(String s:FileTypeExtensions.getAudioExtensions()) {
if(ext.equals(s)) { return "org/sleuthkit/autopsy/images/audio-file.png"; }
}
// Documents
for(String s:FileTypeExtensions.getDocumentExtensions()) {
if(ext.equals(s)) { return "org/sleuthkit/autopsy/images/doc-file.png"; }
}
// Executables / System Files
for(String s:FileTypeExtensions.getExecutableExtensions()) {
if(ext.equals(s)) { return "org/sleuthkit/autopsy/images/exe-file.png"; }
}
// Text Files
for(String s:FileTypeExtensions.getTextExtensions()) {
if(ext.equals(s)) { return "org/sleuthkit/autopsy/images/text-file.png"; }
}
// Web Files
for(String s:FileTypeExtensions.getWebExtensions()) {
if(ext.equals(s)) { return "org/sleuthkit/autopsy/images/web-file.png"; }
}
// PDFs
for(String s:FileTypeExtensions.getPDFExtensions()) {
if(ext.equals(s)) { return "org/sleuthkit/autopsy/images/pdf-file.png"; }
}
// Else return the default
return "org/sleuthkit/autopsy/images/file-icon.png";
}
}

View File

@ -26,10 +26,9 @@ import org.sleuthkit.autopsy.datamodel.SearchFilters.FileSearchFilter;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
*
* @author dfickling
* Node for the file search filter
*/
public class FileSearchFilterNode extends AbstractNode implements DisplayableItemNode{
public class FileSearchFilterNode extends AbstractNode implements DisplayableItemNode {
SearchFilters.SearchFilterInterface filter;
SleuthkitCase skCase;

View File

@ -0,0 +1,46 @@
package org.sleuthkit.autopsy.datamodel;
import java.util.Arrays;
import java.util.List;
/**
* Contains Lists of commonly known and used file type extensions
* and 'getters' to obtain them.
*/
public class FileTypeExtensions {
private final static List<String> IMAGE_EXTENSIONS = Arrays.asList(".jpg", ".jpeg", ".png", ".psd", ".nef", ".tiff", ".bmp");
private final static List<String> VIDEO_EXTENSIONS = Arrays.asList(".aaf", ".3gp", ".asf", ".avi", ".m1v", ".m2v",
".m4v", ".mp4", ".mov", ".mpeg", ".mpg", ".mpe", ".mp4", ".rm", ".wmv", ".mpv", ".flv", ".swf");
private final static List<String> AUDIO_EXTENSIONS = Arrays.asList(".aiff", ".aif", ".flac", ".wav", ".m4a", ".ape",
".wma", ".mp2", ".mp1", ".mp3", ".aac", ".mp4", ".m4p", ".m1a", ".m2a", ".m4r", ".mpa", ".m3u", ".mid", ".midi", ".ogg");
private final static List<String> DOCUMENT_EXTENSIONS = Arrays.asList(".doc", ".docx", ".odt", ".xls", ".xlsx", ".ppt", ".pptx");
private final static List<String> EXECUTABLE_EXTENSIONS = Arrays.asList(".exe", ".msi", ".cmd", ".com", ".bat", ".reg", ".scr", ".dll", ".ini");
private final static List<String> TEXT_EXTENSIONS = Arrays.asList(".txt", ".rtf", ".log", ".text", ".xml");
private final static List<String> WEB_EXTENSIONS = Arrays.asList(".html", ".htm", ".css", ".js", ".php", ".aspx");
private final static List<String> PDF_EXTENSIONS = Arrays.asList(".pdf");
public static List<String> getImageExtensions() {
return IMAGE_EXTENSIONS;
}
public static List<String> getVideoExtensions() {
return VIDEO_EXTENSIONS;
}
public static List<String> getAudioExtensions() {
return AUDIO_EXTENSIONS;
}
public static List<String> getDocumentExtensions() {
return DOCUMENT_EXTENSIONS;
}
public static List<String> getExecutableExtensions() {
return EXECUTABLE_EXTENSIONS;
}
public static List<String> getTextExtensions() {
return TEXT_EXTENSIONS;
}
public static List<String> getWebExtensions() {
return WEB_EXTENSIONS;
}
public static List<String> getPDFExtensions() {
return PDF_EXTENSIONS;
}
}

View File

@ -41,8 +41,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskException;
/**
*
* @author dfickling
* Hash set hits node support
*/
public class HashsetHits implements AutopsyVisitableItem {
@ -92,6 +91,9 @@ public class HashsetHits implements AutopsyVisitableItem {
return v.visit(this);
}
/**
* Node for the hash set hits
*/
public class HashsetHitsRootNode extends AbstractNode implements DisplayableItemNode{
public HashsetHitsRootNode() {

View File

@ -23,14 +23,15 @@ import org.openide.nodes.Sheet;
import org.sleuthkit.datamodel.Image;
/**
* This class is used to represent the "Node" for the image.
* The children of this node are volumes.
* This class is used to represent the "Node" for the image. The children of
* this node are volumes.
*/
public class ImageNode extends AbstractContentNode<Image> {
/**
* Helper so that the display name and the name used in building the path
* are determined the same way.
*
* @param i Image to get the name of
* @return short name for the Image
*/

View File

@ -21,8 +21,7 @@ package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
*
* @author dfickling
* Images nodes support
*/
public class Images implements AutopsyVisitableItem{

View File

@ -25,8 +25,7 @@ import org.openide.util.lookup.Lookups;
import org.sleuthkit.datamodel.Content;
/**
*
* @author dfickling
* Nodes for the images
*/
public class ImagesNode extends AbstractNode implements DisplayableItemNode {

Some files were not shown because too many files have changed in this diff Show More