diff --git a/.gitignore b/.gitignore index 7762f76ff2..1023354034 100644 --- a/.gitignore +++ b/.gitignore @@ -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 + + diff --git a/BUILDING.txt b/BUILDING.txt index fa3ef253eb..86544bdeaa 100644 --- a/BUILDING.txt +++ b/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 diff --git a/Case/nbproject/project.xml b/Case/nbproject/project.xml index ed0e258923..d264d97853 100644 --- a/Case/nbproject/project.xml +++ b/Case/nbproject/project.xml @@ -6,15 +6,7 @@ org.sleuthkit.autopsy.casemodule - - org.jdesktop.beansbinding - - - - 1 - 1.11.1.121 - - + org.netbeans.modules.settings diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageAction.java b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageAction.java index 196092ebed..3e09bc5c7a 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageAction.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageAction.java @@ -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 diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageErrorsDialog.form b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageErrorsDialog.form new file mode 100644 index 0000000000..3af0b7554c --- /dev/null +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageErrorsDialog.form @@ -0,0 +1,100 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageErrorsDialog.java b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageErrorsDialog.java new file mode 100644 index 0000000000..cf6d30f504 --- /dev/null +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageErrorsDialog.java @@ -0,0 +1,121 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011 Basis Technology Corp. + * Contact: carrier sleuthkit 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") + // //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(); + }// //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 +} diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.form b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.form index 809858410c..67fc764e62 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.form +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.form @@ -1,4 +1,4 @@ - +
@@ -6,9 +6,6 @@ - - - @@ -31,22 +28,7 @@ - - - - - - - - - - - - - - - @@ -63,6 +45,10 @@ + + + + @@ -73,85 +59,29 @@ - - - - - - - - - + - - - + - + - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -159,13 +89,6 @@ - - - - - - - @@ -199,16 +122,6 @@ - - - - - - - - - - diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java index e554e7ec62..d03e0fff1d 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java @@ -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 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 encaseExt = Arrays.asList(new String[]{".e01"}); + static final String encaseDesc = "Encase Images (*.e01)"; + static GeneralFilter encaseFilter = new GeneralFilter(encaseExt, encaseDesc); + static final List allExt = new ArrayList(); + { + 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)) ); }// //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); } } diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel2.form b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel2.form index 22a106fde4..384535ef0b 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel2.form +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel2.form @@ -1,4 +1,4 @@ - + @@ -25,10 +25,10 @@ - + - - + + @@ -46,8 +46,8 @@ - - + + @@ -72,13 +72,6 @@ - - - - - - - @@ -86,5 +79,20 @@ + + + + + + + + + + + + + + + diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel2.java b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel2.java index df309133c4..b952e13173 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel2.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel2.java @@ -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. */ // //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)) ); }// //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 } diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.form b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.form index 5a1e6247e7..d220b5201d 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.form +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.form @@ -1,4 +1,4 @@ - +
diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.java b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.java index 6df994590f..4c37230dbf 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.java @@ -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)) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel4.form b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel4.form index 0ba0529493..cc1106d0b1 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel4.form +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel4.form @@ -1,4 +1,4 @@ - + @@ -22,6 +22,7 @@ + @@ -34,9 +35,11 @@ + + - + @@ -69,5 +72,12 @@ + + + + + + +
diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel4.java b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel4.java index 14b50fb150..6da6a216e1 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel4.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel4.java @@ -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()) ); }// //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 } diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel1.java b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel1.java index 4063870630..a987418131 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel1.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel1.java @@ -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, */ @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); } diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel2.java b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel2.java index cea82741d5..6c2b2ea6da 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel2.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel2.java @@ -50,7 +50,7 @@ import org.sleuthkit.datamodel.TskException; class AddImageWizardPanel2 implements WizardDescriptor.Panel { // 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 { * 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 { * 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 { * 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 { } /** - * 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 { /** * 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 { /** * 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 { } /** - * 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 it; @@ -184,24 +184,24 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel { * 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 { // 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 { @@ -233,20 +235,19 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel { } /** - * 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 { //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 { 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 { } /** - * + * * (called by EventDispatch Thread after doInBackground finishes) */ @Override @@ -317,15 +317,14 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel { logger.log(Level.INFO, "Handling errors or interruption that occured in add image process"); revert(); if (hasCritError) { - StringBuilder errMsgB = new StringBuilder(); - errMsgB.append("*Failed to add image"); - if (errorString != null) { - errMsgB.append(":
").append(errorString); - } - errMsgB.append(""); - 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 { }; 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! diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel3.java b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel3.java index 987ed115cc..28b3d362b0 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel3.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel3.java @@ -178,7 +178,7 @@ class AddImageWizardPanel3 implements WizardDescriptor.Panel { */ 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 { 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); } diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Case/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index a29fc26e87..1701014740 100755 --- a/Case/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Case/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -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= We are now analyzing the disk image to extract volume and file system data and populate a local database. -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= Press 'Next' to analyze the disk image to extract volume and file system data and populate a local database. -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. diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/Case.java b/Case/src/org/sleuthkit/autopsy/casemodule/Case.java index 4405fe4b20..a356046956 100755 --- a/Case/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -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> getImagePaths() { - Map> imgPaths = new HashMap>(); + static Map getImagePaths(SleuthkitCase db) { //TODO: clean this up + Map imgPaths = new HashMap(); try { - imgPaths = db.getImagePaths(); + Map> imgPathsList = db.getImagePaths(); + for(Map.Entry> 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> imgPaths = new HashMap>(); - try { - imgPaths = db.getImagePaths(); - } catch (TskException ex) { - Logger.getLogger(Case.class.getName()).log(Level.WARNING, "Error getting image paths", ex); - } - for (Map.Entry> entry : imgPaths.entrySet()) { + * Ensure that all image paths point to valid image files + */ + private static void checkImagesExist(SleuthkitCase db) { + Map imgPaths = getImagePaths(db); + for (Map.Entry entry : imgPaths.entrySet()) { JFileChooser fc = new JFileChooser(); FileFilter filter; long obj_id = entry.getKey(); - List 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 newPaths = new ArrayList(); - 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 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 ids = getImagePaths().keySet(); + Set 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 getTimeZone() { - if (xmlcm == null) { - return new HashSet(); - } else { - return xmlcm.getTimeZone(); + Set timezones = new HashSet(); + 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); } /** diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java b/Case/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java index b8ee3830a6..ae4b189543 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java @@ -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.singletonList(".aut"), "AUTOPSY File (*.aut)"); /** The constructor */ public CaseOpenAction() { diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java b/Case/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java index f642ecb7d6..674e86483f 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java @@ -77,7 +77,7 @@ public final class CasePropertiesAction extends CallableSystemAction { int totalImage = currentCase.getRootObjectsCount(); // put the image paths information into hashmap - Map> imgPaths = currentCase.getImagePaths(); + Map imgPaths = currentCase.getImagePaths(currentCase.getSleuthkitCase()); // create the case properties form CasePropertiesForm cpf = new CasePropertiesForm(currentCase, crDate, caseDir, imgPaths); diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java b/Case/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java index 9c51e9a151..5a477b7bc9 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java @@ -76,7 +76,7 @@ class CasePropertiesForm extends javax.swing.JPanel{ /** Creates new form CasePropertiesForm */ - CasePropertiesForm(Case currentCase, String crDate, String caseDir, Map> imgPaths) { + CasePropertiesForm(Case currentCase, String crDate, String caseDir, Map 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}; } diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java b/Case/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java index 390a09beb6..16620d9a07 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java @@ -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 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 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; diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/IngestConfigurator.java b/Case/src/org/sleuthkit/autopsy/casemodule/IngestConfigurator.java index 116344b553..b3e8466203 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/IngestConfigurator.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/IngestConfigurator.java @@ -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(); diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java b/Case/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java index b0d90292be..c8277ccf69 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java @@ -41,6 +41,8 @@ import org.sleuthkit.autopsy.coreutils.Log; public final class NewCaseWizardAction extends CallableSystemAction { private WizardDescriptor.Panel[] 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 diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java b/Case/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java index 1d98fe0091..66eceae985 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java @@ -169,8 +169,9 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel +
diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java b/Case/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java index 10dc3c2d10..e58a4c51c9 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java @@ -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; } diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/XMLCaseManagement.java b/Case/src/org/sleuthkit/autopsy/casemodule/XMLCaseManagement.java index 421fa99196..e67b3e23d2 100644 --- a/Case/src/org/sleuthkit/autopsy/casemodule/XMLCaseManagement.java +++ b/Case/src/org/sleuthkit/autopsy/casemodule/XMLCaseManagement.java @@ -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 getTimeZone() { - HashSet result = new HashSet(); - - 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); // ... - 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); // ... - 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); // ... -// 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); // ... -// 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); - - } } diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/package.dox b/Case/src/org/sleuthkit/autopsy/casemodule/package.dox new file mode 100644 index 0000000000..3f438b6ecc --- /dev/null +++ b/Case/src/org/sleuthkit/autopsy/casemodule/package.dox @@ -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. + + */ + diff --git a/Case/src/org/sleuthkit/autopsy/casemodule/package.html b/Case/src/org/sleuthkit/autopsy/casemodule/package.html deleted file mode 100644 index 4d7d55f36f..0000000000 --- a/Case/src/org/sleuthkit/autopsy/casemodule/package.html +++ /dev/null @@ -1,10 +0,0 @@ - -

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.

- -

Case settings are stored in an XML file. See the {@link org.sleuthkit.autopsy.casemodule.XMLCaseManagement#XMLCaseManagement() XMLCaseManagement} class for more details.

- -

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.

- -

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.

- - diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataContentViewer.java b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataContentViewer.java index f77479e6ea..bd99546299 100644 --- a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataContentViewer.java +++ b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataContentViewer.java @@ -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); } diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/corecomponentinterfaces/package.dox b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/corecomponentinterfaces/package.dox new file mode 100644 index 0000000000..9beb6e1d37 --- /dev/null +++ b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/corecomponentinterfaces/package.dox @@ -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. + * +NOTE: Much of this data may be out of date. It has not been updated +since a major redesign was done. + +\section corecomponentinterface_contents Package Contents +The following are imporant classes in this package +- TODO + + + *

Autopsy Zones

+ * 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.

+ * 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. + *

Data Flow

+ *

Creating Nodes in DataExplorer

+ * 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. + *

Getting Nodes to DataResult

+ * 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()). + *

Getting Nodes to DataContent

+ * 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. + *

Creating new Functionality

+ *

Creating a DataExplorer

+ *
    + *
  1. Create a module from within NetBeans. It must be dependent on these modules: + *
      + *
    • Case + *
    • CoreComponentInterfaces + *
    • CoreComponents + *
    • DataModel + *
    • DialogsAPI (if pop-ups and such are going to be used) + *
    • Explorer & Property Sheet API + *
    • Lookup + *
    • Nodes API + *
    • Setting API + *
    • UI Utilities API + *
    • Utilities API + *
    • Window System API + *
    + *
  2. 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. + *
  3. Implement the methods required by the DataExplorer interface. + *
  4. Register the class to receive property change events from the org.sleuthkit.autopsy.Case module by using its addPropertyChangeListener() method. + *
  5. Access case data using the org.sleuthkit.autopsy.Case module. + *
  6. Create Nodes for the data objects using the techniques outlined in the previous section. + *
  7. Wrap the nodes in FilterNodes to define actions as outlined in the previous section. + *
  8. Send results to DataResults using the techniques outlined in the previous section. + *
+ *

Creating a DataResultViewer

+ *

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. + *

    + *
  1. Create a module from within NetBeans. It must be dependent on these modules: + *
      + *
    • Case + *
    • CoreComponentInterfaces + *
    • CoreComponents + *
    • DataModel + *
    • DialogsAPI (if pop-ups and such are going to be used) + *
    • Explorer & Property Sheet API + *
    • Lookup + *
    • Nodes API + *
    • Setting API + *
    • UI Utilities API + *
    • Utilities API + *
    • Window System API + *
    + *
  2. 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.
  3. + *
  4. See the previous sections on default actions.
  5. + *
+ *

Creating a DataContentViewer

+ * 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. + *
    + *
  1. Create a module from within NetBeans. It must be dependent on these modules: + *
      + *
    • Case + *
    • CoreComponentInterfaces + *
    • CoreComponents + *
    • DataModel + *
    • DialogsAPI (if pop-ups and such are going to be used) + *
    • Explorer & Property Sheet API + *
    • Lookup + *
    • Nodes API + *
    • Setting API + *
    • UI Utilities API + *
    • Utilities API + *
    • Window System API + *
    + *
  2. 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.
  3. + *
+*/ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/corecomponentinterfaces/package.html b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/corecomponentinterfaces/package.html deleted file mode 100644 index a43d19c45f..0000000000 --- a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/corecomponentinterfaces/package.html +++ /dev/null @@ -1,106 +0,0 @@ - -

This package contains the interface classes that define the core components in Autopsy. These components are used in the difference zones of the GUI.

- -

Autopsy Zones

- -

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).

- -

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.

- -

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.

- - -

Data Flow

-

Creating Nodes in DataExplorer

- -

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.

- -

Getting Nodes to DataResult

- -

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()). - -

Getting Nodes to DataContent

-

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.

- -

Creating new Functionality

- -

Creating a DataExplorer

-
    -
  1. Create a module from within NetBeans. It must be dependent on these modules: -
      -
    • Case -
    • CoreComponentInterfaces -
    • CoreComponents -
    • DataModel -
    • DialogsAPI (if pop-ups and such are going to be used) -
    • Explorer & Property Sheet API -
    • Lookup -
    • Nodes API -
    • Setting API -
    • UI Utilities API -
    • Utilities API -
    • Window System API -
    - -
  2. 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. -
  3. Implement the methods required by the DataExplorer interface. -
  4. Register the class to receive property change events from the org.sleuthkit.autopsy.Case module by using its addPropertyChangeListener() method. -
  5. Access case data using the org.sleuthkit.autopsy.Case module. -
  6. Create Nodes for the data objects using the techniques outlined in the previous section. -
  7. Wrap the nodes in FilterNodes to define actions as outlined in the previous section. -
  8. Send results to DataResults using the techniques outlined in the previous section. -
- -

Creating a DataResultViewer

-

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.

- -
    -
  1. Create a module from within NetBeans. It must be dependent on these modules: -
      -
    • Case -
    • CoreComponentInterfaces -
    • CoreComponents -
    • DataModel -
    • DialogsAPI (if pop-ups and such are going to be used) -
    • Explorer & Property Sheet API -
    • Lookup -
    • Nodes API -
    • Setting API -
    • UI Utilities API -
    • Utilities API -
    • Window System API -
    - -
  2. 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.
  3. - -
  4. See the previous sections on default actions.
  5. -
- -

Creating a DataContentViewer

-

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.

- -
    -
  1. Create a module from within NetBeans. It must be dependent on these modules: -
      -
    • Case -
    • CoreComponentInterfaces -
    • CoreComponents -
    • DataModel -
    • DialogsAPI (if pop-ups and such are going to be used) -
    • Explorer & Property Sheet API -
    • Lookup -
    • Nodes API -
    • Setting API -
    • UI Utilities API -
    • Utilities API -
    • Window System API -
    - -
  2. 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.
  3. -
- - \ No newline at end of file diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/account-icon-16.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/account-icon-16.png new file mode 100644 index 0000000000..73d9cfeabb Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/account-icon-16.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/audio-file.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/audio-file.png new file mode 100644 index 0000000000..516ac7f233 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/audio-file.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/doc-file.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/doc-file.png new file mode 100644 index 0000000000..2d364e1cf3 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/doc-file.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/exe-file.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/exe-file.png new file mode 100644 index 0000000000..a886401df0 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/exe-file.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/folder-icon-16.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/folder-icon-16.png new file mode 100644 index 0000000000..c8eb4f6708 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/folder-icon-16.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/image-file.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/image-file.png new file mode 100644 index 0000000000..e2e79d0324 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/image-file.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/mail-icon-16.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/mail-icon-16.png new file mode 100644 index 0000000000..a919ae3e50 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/mail-icon-16.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/pdf-file.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/pdf-file.png new file mode 100644 index 0000000000..7a6dcb42d0 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/pdf-file.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/searchquery.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/searchquery.png new file mode 100644 index 0000000000..d036553018 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/searchquery.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/text-file.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/text-file.png new file mode 100644 index 0000000000..43ec054ac2 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/text-file.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/video-file.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/video-file.png new file mode 100644 index 0000000000..c290609f59 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/video-file.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/web-file.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/web-file.png new file mode 100644 index 0000000000..ac5957ad62 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/web-file.png differ diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationCleanDialog.form b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationCleanDialog.form new file mode 100644 index 0000000000..8c0236cde0 --- /dev/null +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationCleanDialog.form @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationCleanDialog.java b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationCleanDialog.java new file mode 100644 index 0000000000..0ae2014ca4 --- /dev/null +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationCleanDialog.java @@ -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") + // //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(); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationDialog.form b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationDialog.form index d99cc0b860..cc784d4d4a 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationDialog.form +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationDialog.form @@ -1,4 +1,4 @@ - +
diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationDialog.java b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationDialog.java index 2748d01551..3c338c9053 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationDialog.java +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/AdvancedConfigurationDialog.java @@ -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); } diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 90da263d58..4242f6af36 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -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 diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.form b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.form index a99a3b3a2b..7da782da37 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.form +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.form @@ -1,4 +1,4 @@ - + diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java index 77e4781b19..324621bb84 100755 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java @@ -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 dcvs = new ArrayList(); - dcvs.addAll(Lookup.getDefault().lookupAll(DataContentViewer.class)); - for (int i = 0; i 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; diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index b49113ca7c..901f901446 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -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(){ diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form index 0a60b7b5b6..1817615f84 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form @@ -1,4 +1,4 @@ - + diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index 0416cdee81..5e76c1b17c 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -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 diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index 70e5362f63..c92deeca35 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -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) { diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java index e4bc39c99c..36ca063420 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java @@ -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 diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.form b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.form index 3a40b53cf8..9d0c5e483c 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.form +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.form @@ -1,4 +1,4 @@ - + @@ -55,7 +55,7 @@ - + @@ -74,9 +74,14 @@ - + + + + + + - + @@ -93,7 +98,12 @@ - + + + + + + @@ -252,6 +262,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java index 1da7c206e0..4a05d7ac67 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java @@ -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 tags + scripts.append(tag.getElement().getContent()).append("\n"); + numScripts++; + } else if(tag.getName().equals("a")) { + links.append(numLinks).append(") "); + links.append(tag.getTagContent()).append("\n"); + numLinks++; + } else if(tag.getName().equals("img")) { + images.append(numImages).append(") "); + images.append(tag.getTagContent()).append("\n"); + numImages++; + } else if(tag.getTagType().equals(StartTagType.COMMENT)) { + comments.append(numComments).append(") "); + comments.append(tag.getTagContent()).append("\n"); + numComments++; + } else { + // Make sure it has an attribute + Attributes atts = tag.getAttributes(); + if (atts!=null && atts.length()>0) { + others.append(numOthers).append(") "); + others.append(tag.getName()).append(":"); + others.append(tag.getTagContent()).append("\n"); + numOthers++; + } + } + } + + out.append(text.toString()).append("\n"); + + out.append("----------NONVISIBLE TEXT----------\n\n"); + if(numScripts>1) { + out.append("---Scripts---\n"); + out.append(scripts.toString()).append("\n"); + } if(numLinks>1) { + out.append("---Links---\n"); + out.append(links.toString()).append("\n"); + } if(numImages>1) { + out.append("---Images---\n"); + out.append(images.toString()).append("\n"); + } if(numComments>1) { + out.append("---Comments---\n"); + out.append(comments.toString()).append("\n"); + } if(numOthers>1) { + out.append("---Others---\n"); + out.append(others.toString()).append("\n"); + } + // All done, now make it a reader + reader = new StringReader(out.toString()); + } catch (IOException ex) { + logger.log(Level.WARNING, "Unable to parse the HTML file", ex); + } + } + + /** + * Returns the reader, initialized in parse(), which will be + * null if parse() is not called or if parse() throws an error. + * @return Reader + */ + public Reader getReader() { + return reader; + } + +} diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java index ba3b0182fe..99524a700f 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java @@ -56,6 +56,13 @@ public class Keyword { return isLiteral; } + @Override + public String toString() { + return "Keyword{" + "query=" + query + ", isLiteral=" + isLiteral + ", keywordType=" + keywordType + '}'; + } + + + @Override public boolean equals(Object obj) { if (obj == null) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.form index d88483b1ff..6a22cf2579 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.form +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.form @@ -1,6 +1,6 @@ - + - + @@ -16,61 +16,19 @@ - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.java index 298045c0ff..0046b2cb29 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2012 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,34 +17,19 @@ * limitations under the License. */ -/* - * KeywordSearchConfigurationPanel.java - * - * Created on Feb 28, 2012, 4:12:47 PM - */ package org.sleuthkit.autopsy.keywordsearch; -import java.util.logging.Logger; -import org.sleuthkit.autopsy.ingest.IngestManager; - /** - * - * @author dfickling + * Container for KeywordSearchConfigurationPanelX tabs */ public class KeywordSearchConfigurationPanel extends javax.swing.JPanel { - - KeywordSearchListsManagementPanel listsManagementPanel; - KeywordSearchEditListPanel editListPanel; - private static final Logger logger = Logger.getLogger(KeywordSearchConfigurationPanel.class.getName()); - private static final String KEYWORD_CONFIG_NAME = org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "ListBundleConfig"); - private static KeywordSearchConfigurationPanel instance; + private static KeywordSearchConfigurationPanel instance = null; + /** Creates new form KeywordSearchConfigurationPanel */ - private KeywordSearchConfigurationPanel() { - + public KeywordSearchConfigurationPanel() { initComponents(); customizeComponents(); - setName(KEYWORD_CONFIG_NAME); } public static KeywordSearchConfigurationPanel getDefault() { @@ -52,17 +37,13 @@ public class KeywordSearchConfigurationPanel extends javax.swing.JPanel { instance = new KeywordSearchConfigurationPanel(); return instance; } - + private void customizeComponents() { - listsManagementPanel = KeywordSearchListsManagementPanel.getDefault(); - editListPanel = KeywordSearchEditListPanel.getDefault(); - - listsManagementPanel.addListSelectionListener(editListPanel); + setName("Advanced Keyword Search Configuration"); + tabbedPane.insertTab("Lists", null, KeywordSearchConfigurationPanel1.getDefault(), "List configuration", 0); + tabbedPane.insertTab("Languages", null, KeywordSearchConfigurationPanel3.getDefault(), "Languages configuration", 1); + tabbedPane.insertTab("General", null, KeywordSearchConfigurationPanel2.getDefault(), "General configuration", 2); - mainSplitPane.setLeftComponent(listsManagementPanel); - mainSplitPane.setRightComponent(editListPanel); - mainSplitPane.revalidate(); - mainSplitPane.repaint(); } /** This method is called from within the constructor to @@ -74,51 +55,20 @@ public class KeywordSearchConfigurationPanel extends javax.swing.JPanel { // //GEN-BEGIN:initComponents private void initComponents() { - mainSplitPane = new javax.swing.JSplitPane(); - jPanel1 = new javax.swing.JPanel(); - jPanel2 = new javax.swing.JPanel(); - javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); - jPanel1.setLayout(jPanel1Layout); - jPanel1Layout.setHorizontalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 100, Short.MAX_VALUE) - ); - jPanel1Layout.setVerticalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 242, Short.MAX_VALUE) - ); - - mainSplitPane.setLeftComponent(jPanel1); - - javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); - jPanel2.setLayout(jPanel2Layout); - jPanel2Layout.setHorizontalGroup( - jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 291, Short.MAX_VALUE) - ); - jPanel2Layout.setVerticalGroup( - jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 242, Short.MAX_VALUE) - ); - - mainSplitPane.setRightComponent(jPanel2); + tabbedPane = new javax.swing.JTabbedPane(); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(mainSplitPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(mainSplitPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) ); }// //GEN-END:initComponents - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JPanel jPanel1; - private javax.swing.JPanel jPanel2; - private javax.swing.JSplitPane mainSplitPane; + private javax.swing.JTabbedPane tabbedPane; // End of variables declaration//GEN-END:variables - } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel1.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel1.form new file mode 100644 index 0000000000..d88483b1ff --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel1.form @@ -0,0 +1,76 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel1.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel1.java new file mode 100644 index 0000000000..f44355b7ff --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel1.java @@ -0,0 +1,125 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011 Basis Technology Corp. + * Contact: carrier sleuthkit 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. + */ + +/* + * KeywordSearchConfigurationPanel1.java + * + * Created on Feb 28, 2012, 4:12:47 PM + */ +package org.sleuthkit.autopsy.keywordsearch; + +import java.util.logging.Logger; +import org.sleuthkit.autopsy.ingest.IngestManager; + +/** + * + * @author dfickling + */ +public class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel { + + KeywordSearchListsManagementPanel listsManagementPanel; + KeywordSearchEditListPanel editListPanel; + private static final Logger logger = Logger.getLogger(KeywordSearchConfigurationPanel1.class.getName()); + private static final String KEYWORD_CONFIG_NAME = org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "ListBundleConfig"); + private static KeywordSearchConfigurationPanel1 instance; + + /** Creates new form KeywordSearchConfigurationPanel1 */ + private KeywordSearchConfigurationPanel1() { + + initComponents(); + customizeComponents(); + setName(KEYWORD_CONFIG_NAME); + } + + public static KeywordSearchConfigurationPanel1 getDefault() { + if(instance == null) + instance = new KeywordSearchConfigurationPanel1(); + return instance; + } + + private void customizeComponents() { + listsManagementPanel = KeywordSearchListsManagementPanel.getDefault(); + editListPanel = KeywordSearchEditListPanel.getDefault(); + + listsManagementPanel.addListSelectionListener(editListPanel); + + mainSplitPane.setLeftComponent(listsManagementPanel); + mainSplitPane.setRightComponent(editListPanel); + mainSplitPane.revalidate(); + mainSplitPane.repaint(); + } + + /** 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + mainSplitPane = new javax.swing.JSplitPane(); + jPanel1 = new javax.swing.JPanel(); + jPanel2 = new javax.swing.JPanel(); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 100, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 242, Short.MAX_VALUE) + ); + + mainSplitPane.setLeftComponent(jPanel1); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 291, Short.MAX_VALUE) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 242, Short.MAX_VALUE) + ); + + mainSplitPane.setRightComponent(jPanel2); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(mainSplitPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(mainSplitPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JSplitPane mainSplitPane; + // End of variables declaration//GEN-END:variables + +} diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel2.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel2.form new file mode 100644 index 0000000000..3c4a811524 --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel2.form @@ -0,0 +1,89 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel2.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel2.java new file mode 100644 index 0000000000..b85356dbf2 --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel2.java @@ -0,0 +1,173 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2012 Basis Technology Corp. + * Contact: carrier sleuthkit 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.keywordsearch; + +import java.awt.Graphics; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.AbstractButton; +import javax.swing.JCheckBox; +import org.apache.solr.client.solrj.SolrServerException; +import org.sleuthkit.autopsy.coreutils.StringExtract; +import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT; +import org.sleuthkit.autopsy.ingest.IngestManager; + +/** + * + * General, not per list, keyword search configuration and status display widget + */ +public class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel { + + private static KeywordSearchConfigurationPanel2 instance = null; + private final Logger logger = Logger.getLogger(KeywordSearchConfigurationPanel2.class.getName()); + + /** + * Creates new form KeywordSearchConfigurationPanel2 + */ + public KeywordSearchConfigurationPanel2() { + initComponents(); + customizeComponents(); + } + + public static KeywordSearchConfigurationPanel2 getDefault() { + if (instance == null) { + instance = new KeywordSearchConfigurationPanel2(); + } + return instance; + } + + @Override + public void paint(Graphics g) { + super.paint(g); + + activateWidgets(); + } + + private void activateWidgets() { + final KeywordSearchIngestService service = KeywordSearchIngestService.getDefault(); + skipNSRLCheckBox.setSelected(service.getSkipKnown()); + boolean enable = !IngestManager.getDefault().isIngestRunning(); + skipNSRLCheckBox.setEnabled(enable); + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + langButtonGroup = new javax.swing.ButtonGroup(); + skipNSRLCheckBox = new javax.swing.JCheckBox(); + filesIndexedLabel = new javax.swing.JLabel(); + filesIndexedValue = new javax.swing.JLabel(); + jSeparator2 = new javax.swing.JSeparator(); + + skipNSRLCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.skipNSRLCheckBox.text")); // NOI18N + skipNSRLCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.skipNSRLCheckBox.toolTipText")); // NOI18N + skipNSRLCheckBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + skipNSRLCheckBoxActionPerformed(evt); + } + }); + + filesIndexedLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.filesIndexedLabel.text")); // NOI18N + + filesIndexedValue.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.filesIndexedValue.text")); // NOI18N + filesIndexedValue.setMaximumSize(null); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSeparator2) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(skipNSRLCheckBox) + .addGroup(layout.createSequentialGroup() + .addComponent(filesIndexedLabel) + .addGap(18, 18, 18) + .addComponent(filesIndexedValue, javax.swing.GroupLayout.PREFERRED_SIZE, 104, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap(205, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(skipNSRLCheckBox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(filesIndexedLabel) + .addComponent(filesIndexedValue, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(51, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + +private void skipNSRLCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipNSRLCheckBoxActionPerformed + KeywordSearchIngestService.getDefault().setSkipKnown(skipNSRLCheckBox.isSelected()); +}//GEN-LAST:event_skipNSRLCheckBoxActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel filesIndexedLabel; + private javax.swing.JLabel filesIndexedValue; + private javax.swing.JSeparator jSeparator2; + private javax.swing.ButtonGroup langButtonGroup; + private javax.swing.JCheckBox skipNSRLCheckBox; + // End of variables declaration//GEN-END:variables + + private void customizeComponents() { + this.skipNSRLCheckBox.setSelected(KeywordSearchIngestService.getDefault().getSkipKnown()); + + try { + filesIndexedValue.setText(Integer.toString(KeywordSearch.getServer().queryNumIndexedFiles())); + } catch (SolrServerException ex) { + logger.log(Level.WARNING, "Could not get number of indexed files"); + + } catch (NoOpenCoreException ex) { + logger.log(Level.WARNING, "Could not get number of indexed files"); + } + + KeywordSearch.changeSupport.addPropertyChangeListener(KeywordSearch.NUM_FILES_CHANGE_EVT, + new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + String changed = evt.getPropertyName(); + Object newValue = evt.getNewValue(); + + if (changed.equals(KeywordSearch.NUM_FILES_CHANGE_EVT)) { + int newFilesIndexed = ((Integer) newValue).intValue(); + filesIndexedValue.setText(Integer.toString(newFilesIndexed)); + + } + } + }); + + + } +} diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel3.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel3.form new file mode 100644 index 0000000000..b0b6ab85f6 --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel3.form @@ -0,0 +1,72 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel3.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel3.java new file mode 100644 index 0000000000..9563729de7 --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel3.java @@ -0,0 +1,179 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.keywordsearch; + +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; +import javax.swing.JCheckBox; +import org.sleuthkit.autopsy.coreutils.StringExtract; +import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT; +import org.sleuthkit.autopsy.ingest.IngestManager; + +/** + * Advanced configuration panel handling languages config. + */ +public class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel { + + private static KeywordSearchConfigurationPanel3 instance = null; + private final Logger logger = Logger.getLogger(KeywordSearchConfigurationPanel3.class.getName()); + private final Map scripts = new HashMap(); + private ActionListener updateLanguagesAction; + + /** + * Creates new form KeywordSearchConfigurationPanel3 + */ + public KeywordSearchConfigurationPanel3() { + initComponents(); + customizeComponents(); + } + + public static KeywordSearchConfigurationPanel3 getDefault() { + if (instance == null) { + instance = new KeywordSearchConfigurationPanel3(); + } + return instance; + } + + @Override + public void paint(Graphics g) { + super.paint(g); + activateWidgets(); + } + + private void customizeComponents() { + + + updateLanguagesAction = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + List