Merge branch 'master' of github.com:sleuthkit/autopsy
6
.gitignore
vendored
@ -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
|
||||
|
||||
|
||||
|
18
BUILDING.txt
@ -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
|
||||
|
@ -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/>
|
||||
|
@ -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
|
||||
|
@ -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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -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
|
||||
}
|
@ -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"/>
|
||||
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="25" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" pref="117" max="32767" attributes="0"/>
|
||||
<Component id="jLabel2" min="-2" 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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="timeZoneComboBox">
|
||||
<Properties>
|
||||
<Property name="maximumRowCount" type="int" value="30"/>
|
||||
|
@ -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() {
|
||||
@ -115,27 +105,6 @@ final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
|
||||
boolean getNoFatOrphans() {
|
||||
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,12 +262,7 @@ 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
|
||||
File currentDir = new File(oldText);
|
||||
@ -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() + "\" ";
|
||||
}
|
||||
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;
|
||||
}
|
||||
String path = fc.getSelectedFile().getPath();
|
||||
imgPathTextField.setText(path);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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, "{key}")"/>
|
||||
</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>
|
||||
|
@ -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,16 +37,38 @@ 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("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the this panel. This name will be shown on the left
|
||||
* panel of the "Add Image" wizard panel.
|
||||
*
|
||||
* @return name the name of this panel
|
||||
* @return name the name of this panel
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
@ -59,9 +86,9 @@ final class AddImageVisualPanel2 extends JPanel {
|
||||
/**
|
||||
* Changes the progress bar text and color.
|
||||
*
|
||||
* @param text the text to be shown
|
||||
* @param value the current value of the progress bar
|
||||
* @param color the color of the progress bar text
|
||||
* @param text the text to be shown
|
||||
* @param value the current value of the progress bar
|
||||
* @param color the color of the progress bar text
|
||||
*/
|
||||
public void changeProgressBarTextAndColor(String text, int value, Color color) {
|
||||
progressLabel.setText(text);
|
||||
@ -69,9 +96,34 @@ 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
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
@ -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
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,18 +208,16 @@ 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);
|
||||
AutopsyPropFile.getInstance().setProperty(PROP_LASTIMAGE, firstImagePath);
|
||||
}
|
||||
String firstImage = getComponent().getImagePath();
|
||||
String firstImagePath = firstImage.substring(0, firstImage.lastIndexOf(File.separator) + 1);
|
||||
AutopsyPropFile.getInstance().setProperty(PROP_LASTIMAGE, firstImagePath);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
@ -79,7 +79,7 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
* but never displayed, or not all panels are displayed, it is better to
|
||||
* create only those which really need to be visible.
|
||||
*
|
||||
* @return component the UI component of this wizard panel
|
||||
* @return component the UI component of this wizard panel
|
||||
*/
|
||||
@Override
|
||||
public AddImageVisualPanel2 getComponent() {
|
||||
@ -93,7 +93,7 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
* Help for this panel. When the panel is active, this is used as the help
|
||||
* for the wizard dialog.
|
||||
*
|
||||
* @return HelpCtx.DEFAULT_HELP the help for this panel
|
||||
* @return HelpCtx.DEFAULT_HELP the help for this panel
|
||||
*/
|
||||
@Override
|
||||
public HelpCtx getHelp() {
|
||||
@ -105,7 +105,7 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
* Tests whether the panel is finished and it is safe to proceed to the next
|
||||
* one. If the panel is valid, the "Next" button will be enabled.
|
||||
*
|
||||
* @return boolean true if can proceed to the next one, false otherwise
|
||||
* @return boolean true if can proceed to the next one, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
@ -130,10 +130,10 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the isDbCreated variable in this class and also invoke
|
||||
* Sets the isDbCreated variable in this class and also invoke
|
||||
* fireChangeEvent() method.
|
||||
*
|
||||
* @param created whether the database already created or not
|
||||
* @param created whether the database already created or not
|
||||
*/
|
||||
private void setDbCreated(Boolean created) {
|
||||
imgAdded = created;
|
||||
@ -144,7 +144,7 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
/**
|
||||
* Adds a listener to changes of the panel's validity.
|
||||
*
|
||||
* @param l the change listener to add
|
||||
* @param l the change listener to add
|
||||
*/
|
||||
@Override
|
||||
public final void addChangeListener(ChangeListener l) {
|
||||
@ -156,7 +156,7 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
/**
|
||||
* Removes a listener to changes of the panel's validity.
|
||||
*
|
||||
* @param l the change listener to move
|
||||
* @param l the change listener to move
|
||||
*/
|
||||
@Override
|
||||
public final void removeChangeListener(ChangeListener l) {
|
||||
@ -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;
|
||||
@ -184,24 +184,24 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
* Load the image locations from the WizardDescriptor settings object, and
|
||||
* the
|
||||
*
|
||||
* @param settings the setting to be read from
|
||||
* @param settings the setting to be read from
|
||||
*/
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param settings the setting to be stored to
|
||||
* @param settings the setting to be stored to
|
||||
*/
|
||||
@Override
|
||||
public void storeSettings(WizardDescriptor settings) {
|
||||
@ -213,10 +213,12 @@ 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread that will make the JNI call to ingest the image.
|
||||
* Thread that will make the JNI call to ingest the image.
|
||||
*/
|
||||
private class AddImgTask extends SwingWorker<Integer, Integer> {
|
||||
|
||||
@ -233,20 +235,19 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the addImage process, but does not commit the results.
|
||||
*
|
||||
* Starts the addImage process, but does not commit the results.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected Integer doInBackground() {
|
||||
this.setProgress(0);
|
||||
|
||||
|
||||
|
||||
// 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
|
||||
@ -296,7 +296,7 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* (called by EventDispatch Thread after doInBackground finishes)
|
||||
*/
|
||||
@Override
|
||||
@ -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,7 +343,8 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
};
|
||||
cleanupImage.enable();
|
||||
|
||||
getComponent().changeProgressBarTextAndColor("*Image added.", 100, Color.black); // complete progress bar
|
||||
if (errorString == null)
|
||||
getComponent().changeProgressBarTextAndColor("*Image added.", 100, Color.black); // complete progress bar
|
||||
|
||||
// Get attention for the process finish
|
||||
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
||||
@ -112,6 +115,8 @@ public class Case {
|
||||
private SleuthkitCase db;
|
||||
// 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);
|
||||
}
|
||||
@ -253,58 +263,37 @@ 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()) {
|
||||
* Ensure that all image paths point to valid image files
|
||||
*/
|
||||
private static void checkImagesExist(SleuthkitCase db) {
|
||||
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());
|
||||
}
|
||||
try {
|
||||
db.setImagePaths(obj_id, newPaths);
|
||||
} 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!");
|
||||
String newPath = fc.getSelectedFile().getPath();
|
||||
try {
|
||||
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,11 +583,15 @@ 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) {
|
||||
@ -653,73 +603,22 @@ public class Case {
|
||||
}
|
||||
|
||||
/**
|
||||
* convert the image Path to array string
|
||||
* @param imgPath the image path
|
||||
* @return imgPath the converted image path
|
||||
* Check if image from the given image path exists.
|
||||
* @param imgPath the 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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};
|
||||
}
|
||||
|
@ -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,23 +46,13 @@ 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]))
|
||||
result = result || true;
|
||||
for (String ext : extensions) {
|
||||
if (name.endsWith(ext)) {
|
||||
result = result || true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -41,6 +41,8 @@ import org.sleuthkit.autopsy.coreutils.Log;
|
||||
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() {
|
||||
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
61
Case/src/org/sleuthkit/autopsy/casemodule/package.dox
Normal 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.
|
||||
|
||||
*/
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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>
|
||||
*/
|
@ -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>
|
After Width: | Height: | Size: 832 B |
After Width: | Height: | Size: 679 B |
After Width: | Height: | Size: 634 B |
After Width: | Height: | Size: 663 B |
After Width: | Height: | Size: 483 B |
After Width: | Height: | Size: 726 B |
After Width: | Height: | Size: 710 B |
After Width: | Height: | Size: 500 B |
After Width: | Height: | Size: 783 B |
After Width: | Height: | Size: 402 B |
After Width: | Height: | Size: 718 B |
After Width: | Height: | Size: 928 B |
@ -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>
|
@ -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
|
||||
}
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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(){
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -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;
|
||||
@ -50,6 +54,9 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
||||
private Content dataSource;
|
||||
// for error handling
|
||||
private String className = this.getClass().toString();
|
||||
|
||||
//string extract utility
|
||||
private final StringExtract stringExtract = new StringExtract();
|
||||
|
||||
/** Creates new form DataContentViewerString */
|
||||
public DataContentViewerString() {
|
||||
@ -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,14 +486,12 @@ 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
|
||||
|
@ -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>
|
||||
|
@ -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() {
|
||||
|
@ -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>
|
||||
|
@ -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++){
|
||||
|
@ -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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
/**
|
||||
\package org.sleuthkit.autopsy.corecomponents
|
||||
|
||||
This package contains standard implementations of the content viewer and other frameworks.
|
||||
|
||||
*/
|
91
CoreUtils/src/org/sleuthkit/autopsy/coreutils/FileUtil.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
304
CoreUtils/src/org/sleuthkit/autopsy/coreutils/JLNK.java
Normal 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 :(
|
||||
}
|
||||
|
||||
}
|
339
CoreUtils/src/org/sleuthkit/autopsy/coreutils/JLnkParser.java
Normal 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];
|
||||
}
|
||||
}
|
247
CoreUtils/src/org/sleuthkit/autopsy/coreutils/LnkEnums.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
1157
CoreUtils/src/org/sleuthkit/autopsy/coreutils/StringExtract.java
Normal 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() { }
|
||||
|
||||
public enum Type{
|
||||
|
||||
private static Properties versionProperties;
|
||||
|
||||
private Version() {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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/>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 {
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -27,31 +27,18 @@ import org.sleuthkit.datamodel.TskData;
|
||||
* Its children are more directories.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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{
|
||||
|
||||
|
@ -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";
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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() {
|
||||
|
@ -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
|
||||
*/
|
||||
@ -39,7 +40,7 @@ public class ImageNode extends AbstractContentNode<Image> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param img
|
||||
* @param img
|
||||
*/
|
||||
public ImageNode(Image img) {
|
||||
super(img);
|
||||
@ -82,7 +83,7 @@ public class ImageNode extends AbstractContentNode<Image> {
|
||||
public <T> T accept(ContentNodeVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
|
@ -21,8 +21,7 @@ package org.sleuthkit.autopsy.datamodel;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author dfickling
|
||||
* Images nodes support
|
||||
*/
|
||||
public class Images implements AutopsyVisitableItem{
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|