Merge remote-tracking branch 'upstream/develop' into aut-2025-pt2

This commit is contained in:
Oliver Spohngellert 2016-04-06 15:50:45 -04:00
commit 7f43ef3901
114 changed files with 2438 additions and 2048 deletions

View File

@ -2,7 +2,7 @@ Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.core/10 OpenIDE-Module: org.sleuthkit.autopsy.core/10
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml
OpenIDE-Module-Implementation-Version: 15 OpenIDE-Module-Implementation-Version: 16
OpenIDE-Module-Requires: org.openide.windows.WindowManager OpenIDE-Module-Requires: org.openide.windows.WindowManager
AutoUpdate-Show-In-Client: true AutoUpdate-Show-In-Client: true
AutoUpdate-Essential-Module: true AutoUpdate-Essential-Module: true

View File

@ -21,5 +21,5 @@ nbm.homepage=http://www.sleuthkit.org/
nbm.module.author=Brian Carrier nbm.module.author=Brian Carrier
nbm.needs.restart=true nbm.needs.restart=true
source.reference.metadata-extractor-2.8.1.jar=release/modules/ext/metadata-extractor-2.8.1-src.zip!/Source/ source.reference.metadata-extractor-2.8.1.jar=release/modules/ext/metadata-extractor-2.8.1-src.zip!/Source/
spec.version.base=10.4 spec.version.base=10.5

View File

@ -177,7 +177,7 @@
<compile-dependency/> <compile-dependency/>
<run-dependency> <run-dependency>
<release-version>3</release-version> <release-version>3</release-version>
<specification-version>1.0</specification-version> <specification-version>1.1</specification-version>
</run-dependency> </run-dependency>
</dependency> </dependency>
</module-dependencies> </module-dependencies>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -40,6 +40,7 @@ import org.sleuthkit.datamodel.TskCoreException;
public class GetTagNameAndCommentDialog extends JDialog { public class GetTagNameAndCommentDialog extends JDialog {
private static final long serialVersionUID = 1L;
private static final String NO_TAG_NAMES_MESSAGE = NbBundle.getMessage(GetTagNameAndCommentDialog.class, private static final String NO_TAG_NAMES_MESSAGE = NbBundle.getMessage(GetTagNameAndCommentDialog.class,
"GetTagNameAndCommentDialog.noTags"); "GetTagNameAndCommentDialog.noTags");
private final HashMap<String, TagName> tagNames = new HashMap<>(); private final HashMap<String, TagName> tagNames = new HashMap<>();
@ -47,8 +48,8 @@ public class GetTagNameAndCommentDialog extends JDialog {
public static class TagNameAndComment { public static class TagNameAndComment {
private TagName tagName; private final TagName tagName;
private String comment; private final String comment;
private TagNameAndComment(TagName tagName, String comment) { private TagNameAndComment(TagName tagName, String comment) {
this.tagName = tagName; this.tagName = tagName;
@ -67,8 +68,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
/** /**
* Show the Tag Name and Comment Dialog and return the TagNameAndContent * Show the Tag Name and Comment Dialog and return the TagNameAndContent
* chosen by the user. The dialog will be centered with the main autopsy * chosen by the user. The dialog will be centered with the main autopsy
* window as its owner. To set another window as the owner use {@link #doDialog(java.awt.Window) * window as its owner.
* }
* *
* @return a TagNameAndComment instance containing the TagName selected by * @return a TagNameAndComment instance containing the TagName selected by
* the user and the entered comment, or null if the user canceled * the user and the entered comment, or null if the user canceled

View File

@ -35,6 +35,7 @@ import org.openide.util.HelpCtx;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
@ -271,7 +272,10 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
cleanupTask.disable(); cleanupTask.disable();
// Get attention for the process finish // Get attention for the process finish
// this caused a crash on OS X
if (PlatformUtil.isWindowsOS() == true) {
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP! java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
}
AddImageWizardAddingProgressVisual panel = progressPanel.getComponent(); AddImageWizardAddingProgressVisual panel = progressPanel.getComponent();
if (panel != null) { if (panel != null) {
Window w = SwingUtilities.getWindowAncestor(panel); Window w = SwingUtilities.getWindowAncestor(panel);

View File

@ -252,5 +252,6 @@ SingleUserCaseConverter.CanNotOpenDatabase=Unable to open database
CloseCaseWhileIngesting.Warning=Ingest is running. Are you sure you want to close the case? CloseCaseWhileIngesting.Warning=Ingest is running. Are you sure you want to close the case?
CloseCaseWhileIngesting.Warning.title=Warning\: This will close the current case CloseCaseWhileIngesting.Warning.title=Warning\: This will close the current case
CasePropertiesForm.imagesTable.columnModel.title1=Remove CasePropertiesForm.imagesTable.columnModel.title1=Remove
CasePropertiesForm.imagesTable.columnModel.title0=Path CasePropertiesForm.imagesTable.columnModel.title0=Path
LocalFilesPanel.jButton1.text=Change
LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -714,16 +714,14 @@ public class Case implements SleuthkitCase.ErrorObserver {
} }
/** /**
* Adds the image to the current case after it has been added to the DB. * Adds an image to the current case after it has been added to the DB.
* Sends out event and reopens windows if needed. * Sends out event and reopens windows if needed.
* *
* @param imgPaths the paths of the image that being added * @param imgPath The path of the image file.
* @param imgId the ID of the image that being added * @param imgId The ID of the image.
* @param timeZone the timeZone of the image where it's added * @param timeZone The time zone of the image.
* *
* @deprecated As of release 4.0, replaced by {@link #notifyAddingDataSource(java.util.UUID) and * @deprecated As of release 4.0
* {@link #notifyDataSourceAdded(org.sleuthkit.datamodel.Content, java.util.UUID) and
* {@link #notifyFailedAddingDataSource(java.util.UUID)}
*/ */
@Deprecated @Deprecated
public Image addImage(String imgPath, long imgId, String timeZone) throws CaseActionException { public Image addImage(String imgPath, long imgId, String timeZone) throws CaseActionException {

View File

@ -190,9 +190,9 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
* Sets the configuration of the data source processor without using the * Sets the configuration of the data source processor without using the
* configuration panel. * configuration panel.
* *
* @param imagePath Path to the image file. * @param drivePath Path to the local drive.
* @param timeZone The time zone to use when processing dates * @param timeZone The time zone to use when processing dates
* and times for the image, obtained from * and times for the local drive, obtained from
* java.util.TimeZone.getID. * java.util.TimeZone.getID.
* @param ignoreFatOrphanFiles Whether to parse orphans if the image has a * @param ignoreFatOrphanFiles Whether to parse orphans if the image has a
* FAT filesystem. * FAT filesystem.

View File

@ -43,7 +43,6 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
* TODO: Remove the setDataSourceOptionsCalled flag and the settings fields * TODO: Remove the setDataSourceOptionsCalled flag and the settings fields
* when the deprecated method setDataSourceOptions is removed. * when the deprecated method setDataSourceOptions is removed.
*/ */
private String deviceId;
private List<String> localFilePaths; private List<String> localFilePaths;
private boolean setDataSourceOptionsCalled; private boolean setDataSourceOptionsCalled;
@ -123,10 +122,9 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
@Override @Override
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
if (!setDataSourceOptionsCalled) { if (!setDataSourceOptionsCalled) {
deviceId = UUID.randomUUID().toString();
localFilePaths = Arrays.asList(configPanel.getContentPaths().split(LocalFilesPanel.FILES_SEP)); localFilePaths = Arrays.asList(configPanel.getContentPaths().split(LocalFilesPanel.FILES_SEP));
} }
run(deviceId, "", localFilePaths, progressMonitor, callback); run(UUID.randomUUID().toString(), configPanel.getFileSetName(), localFilePaths, progressMonitor, callback);
} }
/** /**
@ -194,7 +192,8 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
*/ */
@Deprecated @Deprecated
public void setDataSourceOptions(String paths) { public void setDataSourceOptions(String paths) {
this.localFilePaths = Arrays.asList(configPanel.getContentPaths().split(LocalFilesPanel.FILES_SEP)); //LocalFilesPanel.FILES_SEP is currently ","
this.localFilePaths = Arrays.asList(paths.split(LocalFilesPanel.FILES_SEP));
setDataSourceOptionsCalled = true; setDataSourceOptionsCalled = true;
} }

View File

@ -47,21 +47,30 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="1" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="infoLabel" min="-2" max="-2" attributes="0"/> <Component id="infoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="1" attributes="0"> <Component id="jScrollPane2" pref="389" max="32767" attributes="0"/>
<Component id="jScrollPane2" pref="353" max="32767" attributes="0"/> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0"> <Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="selectButton" max="32767" attributes="0"/> <Component id="selectButton" max="32767" attributes="0"/>
<Component id="clearButton" max="32767" attributes="0"/> <Component id="clearButton" pref="69" max="32767" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/> <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="errorLabel" min="-2" max="-2" attributes="0"/> <Component id="errorLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="displayNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jButton1" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/> <EmptySpace max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
@ -70,17 +79,23 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="infoLabel" min="-2" max="-2" attributes="0"/> <Component id="infoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
<Component id="jScrollPane2" min="-2" pref="82" max="-2" attributes="0"/>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Component id="selectButton" min="-2" max="-2" attributes="0"/> <Component id="selectButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/> <EmptySpace min="-2" pref="36" max="-2" attributes="0"/>
<Component id="clearButton" min="-2" max="-2" attributes="0"/> <Component id="clearButton" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Component id="jScrollPane2" min="-2" pref="82" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jButton1" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
<Component id="displayNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
<Component id="errorLabel" min="-2" max="-2" attributes="0"/> <Component id="errorLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -151,5 +166,22 @@
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JButton" name="jButton1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalFilesPanel.jButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="displayNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalFilesPanel.displayNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.awt.Dialog;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeSupport;
import java.io.File; import java.io.File;
@ -32,6 +33,10 @@ import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JOptionPane;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.sleuthkit.autopsy.casemodule.Case.CaseType; import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PathValidator; import org.sleuthkit.autopsy.coreutils.PathValidator;
@ -47,6 +52,7 @@ class LocalFilesPanel extends JPanel {
private static LocalFilesPanel instance; private static LocalFilesPanel instance;
public static final String FILES_SEP = ","; public static final String FILES_SEP = ",";
private static final Logger logger = Logger.getLogger(LocalFilesPanel.class.getName()); private static final Logger logger = Logger.getLogger(LocalFilesPanel.class.getName());
private String displayName = "";
/** /**
* Creates new form LocalFilesPanel * Creates new form LocalFilesPanel
@ -67,6 +73,7 @@ class LocalFilesPanel extends JPanel {
localFileChooser.setMultiSelectionEnabled(true); localFileChooser.setMultiSelectionEnabled(true);
errorLabel.setVisible(false); errorLabel.setVisible(false);
selectedPaths.setText(""); selectedPaths.setText("");
this.displayNameLabel.setText(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.displayNameLabel.text"));
} }
//@Override //@Override
@ -137,6 +144,8 @@ class LocalFilesPanel extends JPanel {
selectedPaths.setText(""); selectedPaths.setText("");
enableNext = false; enableNext = false;
errorLabel.setVisible(false); errorLabel.setVisible(false);
displayName = "";
this.displayNameLabel.setText(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.displayNameLabel.text"));
} }
@Override @Override
@ -157,6 +166,10 @@ class LocalFilesPanel extends JPanel {
pcs.removePropertyChangeListener(pcl); pcs.removePropertyChangeListener(pcl);
} }
public String getFileSetName() {
return this.displayName;
}
@Override @Override
public String toString() { public String toString() {
return NbBundle.getMessage(this.getClass(), "LocalFilesDSProcessor.toString.text"); return NbBundle.getMessage(this.getClass(), "LocalFilesDSProcessor.toString.text");
@ -180,6 +193,8 @@ class LocalFilesPanel extends JPanel {
jScrollPane2 = new javax.swing.JScrollPane(); jScrollPane2 = new javax.swing.JScrollPane();
selectedPaths = new javax.swing.JTextArea(); selectedPaths = new javax.swing.JTextArea();
errorLabel = new javax.swing.JLabel(); errorLabel = new javax.swing.JLabel();
jButton1 = new javax.swing.JButton();
displayNameLabel = new javax.swing.JLabel();
localFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonText")); // NOI18N localFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonText")); // NOI18N
localFileChooser.setApproveButtonToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonToolTipText")); // NOI18N localFileChooser.setApproveButtonToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonToolTipText")); // NOI18N
@ -218,37 +233,57 @@ class LocalFilesPanel extends JPanel {
errorLabel.setForeground(new java.awt.Color(255, 0, 0)); errorLabel.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.errorLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.errorLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.jButton1.text")); // NOI18N
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(displayNameLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.displayNameLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(infoLabel) .addComponent(infoLabel)
.addGap(0, 0, Short.MAX_VALUE)) .addGap(0, 0, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 389, Short.MAX_VALUE))
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 353, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(selectButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(selectButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, 69, Short.MAX_VALUE))
.addGap(2, 2, 2)) .addGap(2, 2, 2))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(errorLabel) .addComponent(errorLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(displayNameLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jButton1)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(infoLabel) .addComponent(infoLabel)
.addGap(5, 5, 5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(selectButton) .addComponent(selectButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGap(36, 36, 36)
.addComponent(clearButton))) .addComponent(clearButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(errorLabel)) .addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(displayNameLabel))
.addGap(13, 13, 13)
.addComponent(errorLabel)
.addGap(7, 7, 7))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -291,10 +326,20 @@ class LocalFilesPanel extends JPanel {
}//GEN-LAST:event_clearButtonActionPerformed }//GEN-LAST:event_clearButtonActionPerformed
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
String displayName = JOptionPane.showInputDialog("New Display Name: ");
if (displayName != null && !displayName.equals("")) {
this.displayName = displayName;
this.displayNameLabel.setText("Display Name: " + this.displayName);
}
}//GEN-LAST:event_jButton1ActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton clearButton; private javax.swing.JButton clearButton;
private javax.swing.JLabel displayNameLabel;
private javax.swing.JLabel errorLabel; private javax.swing.JLabel errorLabel;
private javax.swing.JLabel infoLabel; private javax.swing.JLabel infoLabel;
private javax.swing.JButton jButton1;
private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2; private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextArea1; private javax.swing.JTextArea jTextArea1;

View File

@ -156,9 +156,6 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/**
* @inheritDoc
*/
@Override @Override
public int getRowCount() { public int getRowCount() {
int count = 0; int count = 0;
@ -170,17 +167,11 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
return count; return count;
} }
/**
* @inheritDoc
*/
@Override @Override
public int getColumnCount() { public int getColumnCount() {
return 2; return 2;
} }
/**
* @inheritDoc
*/
@Override @Override
public String getColumnName(int column) { public String getColumnName(int column) {
String colName = null; String colName = null;
@ -197,9 +188,6 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
return colName; return colName;
} }
/**
* @inheritDoc
*/
@Override @Override
public Object getValueAt(int rowIndex, int columnIndex) { public Object getValueAt(int rowIndex, int columnIndex) {
Object ret = null; Object ret = null;
@ -217,17 +205,11 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
return ret; return ret;
} }
/**
* @inheritDoc
*/
@Override @Override
public boolean isCellEditable(int rowIndex, int columnIndex) { public boolean isCellEditable(int rowIndex, int columnIndex) {
return false; return false;
} }
/**
* @inheritDoc
*/
@Override @Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) { public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
} }

View File

@ -2,7 +2,7 @@
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* *
* Copyright 2012 42six Solutions. * Copyright 2012 42six Solutions.
* Contact: aebadirad <at> 42six <dot> com * Contact: aebadirad <at> 42six <dot> com
@ -512,6 +512,7 @@ public class FileManager implements Closeable {
* Helper (internal) method to recursively add contents of a folder. Node * Helper (internal) method to recursively add contents of a folder. Node
* passed in can be a file or directory. Children of directories are added. * passed in can be a file or directory. Children of directories are added.
* *
* @param trans A case database transaction.
* @param parentVd Dir that is the parent of localFile * @param parentVd Dir that is the parent of localFile
* @param localFile File/Dir that we are adding * @param localFile File/Dir that we are adding
* @param addProgressUpdater notifier to receive progress notifications on * @param addProgressUpdater notifier to receive progress notifications on
@ -569,6 +570,7 @@ public class FileManager implements Closeable {
* @param parentFile parent file object container (such as virtual * @param parentFile parent file object container (such as virtual
* directory, another local file, or fscontent File), * directory, another local file, or fscontent File),
* @param localFile File that we are adding * @param localFile File that we are adding
* @param trans A case database transaction.
* *
* @return newly created local file object added to the database * @return newly created local file object added to the database
* *

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2013 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -385,7 +385,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
/** /**
* Sets the DataView (The tabbed panel) by offset * Sets the DataView (The tabbed panel) by offset
* *
* @param page Page to display (1-based counting) * @param offset Page to display (1-based counting)
*/ */
private void setDataViewByOffset(long offset) { private void setDataViewByOffset(long offset) {
if (this.dataSource == null) { if (this.dataSource == null) {

View File

@ -22,8 +22,6 @@ import java.awt.CardLayout;
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension; import java.awt.Dimension;
import java.util.List; import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
@ -47,7 +45,6 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
//UI //UI
private final MediaViewVideoPanel videoPanel; private final MediaViewVideoPanel videoPanel;
private final boolean videoPanelInited; private final boolean videoPanelInited;
private final SortedSet<String> videoExtensions; // get them from the panel
private final MediaViewImagePanel imagePanel; private final MediaViewImagePanel imagePanel;
private final boolean imagePanelInited; private final boolean imagePanelInited;
@ -64,7 +61,6 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
// get the right panel for our platform // get the right panel for our platform
videoPanel = MediaViewVideoPanel.createVideoPanel(); videoPanel = MediaViewVideoPanel.createVideoPanel();
videoPanelInited = videoPanel.isInited(); videoPanelInited = videoPanel.isInited();
videoExtensions = new TreeSet<>(videoPanel.getExtensionsList());
imagePanel = new MediaViewImagePanel(); imagePanel = new MediaViewImagePanel();
imagePanelInited = imagePanel.isInited(); imagePanelInited = imagePanel.isInited();

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.corecomponents; package org.sleuthkit.autopsy.corecomponents;
import com.google.common.io.Files;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Image; import java.awt.Image;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
@ -680,6 +681,7 @@ public class GstVideoPanel extends MediaViewVideoPanel {
progressLabel.setText(NbBundle.getMessage(this.getClass(), "GstVideoPanel.progress.buffering")); progressLabel.setText(NbBundle.getMessage(this.getClass(), "GstVideoPanel.progress.buffering"));
progress.start(100); progress.start(100);
try { try {
Files.createParentDirs(tempFile);
return ContentUtils.writeToFile(sourceFile, tempFile, progress, this, true); return ContentUtils.writeToFile(sourceFile, tempFile, progress, this, true);
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.WARNING, "Error buffering file", ex); //NON-NLS logger.log(Level.WARNING, "Error buffering file", ex); //NON-NLS

View File

@ -28,7 +28,9 @@ import java.util.TreeSet;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JPanel; import javax.swing.JPanel;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Video viewer part of the Media View layered pane. Uses different engines * Video viewer part of the Media View layered pane. Uses different engines
@ -131,18 +133,38 @@ public abstract class MediaViewVideoPanel extends JPanel implements FrameCapture
@Override @Override
public boolean isSupported(AbstractFile file) { public boolean isSupported(AbstractFile file) {
/*
* TODO (AUT-2042): Is this the logic we want?
*/
String extension = file.getNameExtension(); String extension = file.getNameExtension();
/**
* Although it seems too restrictive, requiring both a supported
* extension and a supported MIME type prevents two undesirable
* behaviors:
*
* 1) Until AUT-1766 and AUT-1801 are fixed, we incorrectly identify all
* iff files as audio/aiff. This means that if this panel went with the
* looser 'mime type OR extension' criteria we use for images, then this
* panel would attempt (and fail) to display all iff files, even non
* audio ones.
*
* 2) The looser criteria means we are less confident about the files we
* are potentialy sending to GStreamer on 32bit jvms. We are less
* comfortable with the error handling for GStreamer, and don't want to
* send it files which might cause it trouble.
*/
if (AUDIO_EXTENSIONS.contains("." + extension) || getExtensionsList().contains("." + extension)) { if (AUDIO_EXTENSIONS.contains("." + extension) || getExtensionsList().contains("." + extension)) {
SortedSet<String> mimeTypes = new TreeSet<>(getMimeTypes()); SortedSet<String> mimeTypes = new TreeSet<>(getMimeTypes());
String mimeType = file.getMIMEType(); try {
String mimeType = new FileTypeDetector().detect(file);
if (nonNull(mimeType)) { if (nonNull(mimeType)) {
return mimeTypes.contains(mimeType); return mimeTypes.contains(mimeType);
} else {
return getExtensionsList().contains("." + extension);
} }
} catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) {
logger.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + " using FileTypeDetector. Fallingback on AbstractFile.isMimeType", ex);
if (!mimeTypes.isEmpty() && file.isMimeType(mimeTypes) == AbstractFile.MimeMatchEnum.TRUE) {
return true;
}
}
return getExtensionsList().contains("." + extension);
} }
return false; return false;
} }

View File

@ -1,7 +1,20 @@
/* /*
* To change this license header, choose License Headers in Project Properties. * Autopsy Forensic Browser
* To change this template file, choose Tools | Templates *
* and open the template in the editor. * Copyright 2013-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.sleuthkit.autopsy.corecomponents; package org.sleuthkit.autopsy.corecomponents;
@ -467,7 +480,8 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel {
/** /**
* Enables/disables the multi-user settings, based upon input provided * Enables/disables the multi-user settings, based upon input provided
* *
* @param enabled true means enable, false means disable * @param textFields The text fields to enable/disable.
* @param enabled True means enable, false means disable.
*/ */
private static void enableMultiUserComponents(Collection<JTextField> textFields, boolean enabled) { private static void enableMultiUserComponents(Collection<JTextField> textFields, boolean enabled) {
for (JTextField textField : textFields) { for (JTextField textField : textFields) {

View File

@ -132,7 +132,7 @@ class ThumbnailViewChildren extends Children.Keys<Integer> {
return new Node[]{pageNode}; return new Node[]{pageNode};
} }
public static boolean isSupported(Node node) { static boolean isSupported(Node node) {
if (node != null) { if (node != null) {
Content content = node.getLookup().lookup(Content.class); Content content = node.getLookup().lookup(Content.class);
if (content != null) { if (content != null) {

View File

@ -26,10 +26,12 @@ import java.util.concurrent.ExecutionException;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import javax.swing.Timer; import javax.swing.Timer;
import org.apache.commons.lang3.StringUtils;
import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory; import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.nodes.FilterNode; import org.openide.nodes.FilterNode;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
@ -58,14 +60,12 @@ class ThumbnailViewNode extends FilterNode {
@Override @Override
public String getDisplayName() { public String getDisplayName() {
if (super.getDisplayName().length() > 15) { return StringUtils.abbreviate(super.getDisplayName(), 18);
return super.getDisplayName().substring(0, 15).concat("...");
} else {
return super.getDisplayName();
}
} }
@Override @Override
@NbBundle.Messages({"# {0} - file name",
"ThumbnailViewNode.progressHandle.text=Generating thumbnail for {0}"})
public Image getIcon(int type) { public Image getIcon(int type) {
Image icon = null; Image icon = null;
@ -82,7 +82,7 @@ class ThumbnailViewNode extends FilterNode {
} }
if (swingWorker == null || swingWorker.isDone()) { if (swingWorker == null || swingWorker.isDone()) {
swingWorker = new SwingWorker<Image, Object>() { swingWorker = new SwingWorker<Image, Object>() {
final private ProgressHandle progressHandle = ProgressHandleFactory.createHandle("generating thumbnail for video file " + content.getName()); final private ProgressHandle progressHandle = ProgressHandleFactory.createHandle(Bundle.ThumbnailViewNode_progressHandle_text(content.getName()));
@Override @Override
protected Image doInBackground() throws Exception { protected Image doInBackground() throws Exception {
@ -97,7 +97,7 @@ class ThumbnailViewNode extends FilterNode {
iconCache = new SoftReference<>(super.get()); iconCache = new SoftReference<>(super.get());
fireIconChange(); fireIconChange();
} catch (InterruptedException | ExecutionException ex) { } catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(ThumbnailViewNode.class.getName()).log(Level.SEVERE, "Error getting thumbnail icon", ex); //NON-NLS Logger.getLogger(ThumbnailViewNode.class.getName()).log(Level.SEVERE, "Error getting thumbnail icon for " + content.getName(), ex); //NON-NLS
} finally { } finally {
progressHandle.finish(); progressHandle.finish();
if (timer != null) { if (timer != null) {

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-2014 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -96,9 +96,6 @@ public final class ExecUtil {
this.startTimeInSeconds = (new Date().getTime()) / 1000; this.startTimeInSeconds = (new Date().getTime()) / 1000;
} }
/**
* @inheritDoc
*/
@Override @Override
public boolean shouldTerminateProcess() { public boolean shouldTerminateProcess() {
long currentTimeInSeconds = (new Date().getTime()) / 1000; long currentTimeInSeconds = (new Date().getTime()) / 1000;
@ -120,9 +117,6 @@ public final class ExecUtil {
*/ */
public static int execute(ProcessBuilder processBuilder) throws SecurityException, IOException { public static int execute(ProcessBuilder processBuilder) throws SecurityException, IOException {
return ExecUtil.execute(processBuilder, 30, TimeUnit.DAYS, new ProcessTerminator() { return ExecUtil.execute(processBuilder, 30, TimeUnit.DAYS, new ProcessTerminator() {
/**
* @inheritDoc
*/
@Override @Override
public boolean shouldTerminateProcess() { public boolean shouldTerminateProcess() {
return false; return false;

View File

@ -32,10 +32,10 @@ import java.io.InputStream;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects;
import static java.util.Objects.nonNull; import static java.util.Objects.nonNull;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
@ -78,7 +78,7 @@ public class ImageUtils {
/** /**
* save thumbnails to disk as this format * save thumbnails to disk as this format
*/ */
private static final String FORMAT = "png"; //NON-NLS //NOI18N private static final String FORMAT = "png"; //NON-NLS
public static final int ICON_SIZE_SMALL = 50; public static final int ICON_SIZE_SMALL = 50;
public static final int ICON_SIZE_MEDIUM = 100; public static final int ICON_SIZE_MEDIUM = 100;
@ -86,12 +86,11 @@ public class ImageUtils {
private static final BufferedImage DEFAULT_THUMBNAIL; private static final BufferedImage DEFAULT_THUMBNAIL;
private static final String IMAGE_GIF_MIME = "image/gif"; //NOI18N NON-NLS private static final List<String> GIF_EXTENSION_LIST = Arrays.asList("gif");
private static final SortedSet<String> GIF_MIME_SET = ImmutableSortedSet.copyOf(new String[]{IMAGE_GIF_MIME}); private static final SortedSet<String> GIF_MIME_SET = ImmutableSortedSet.copyOf(new String[]{"image/gif"});
private static final List<String> SUPPORTED_IMAGE_EXTENSIONS; private static final List<String> SUPPORTED_IMAGE_EXTENSIONS;
private static final SortedSet<String> SUPPORTED_IMAGE_MIME_TYPES; private static final SortedSet<String> SUPPORTED_IMAGE_MIME_TYPES;
private static final List<String> CONDITIONAL_MIME_TYPES = Arrays.asList("audio/x-aiff", "application/octet-stream"); //NOI18N NON-NLS
private static final boolean openCVLoaded; private static final boolean openCVLoaded;
@ -99,9 +98,9 @@ public class ImageUtils {
ImageIO.scanForPlugins(); ImageIO.scanForPlugins();
BufferedImage tempImage; BufferedImage tempImage;
try { try {
tempImage = ImageIO.read(ImageUtils.class.getResourceAsStream("/org/sleuthkit/autopsy/images/file-icon.png"));//NON-NLS //NOI18N tempImage = ImageIO.read(ImageUtils.class.getResourceAsStream("/org/sleuthkit/autopsy/images/file-icon.png"));//NON-NLS
} catch (IOException ex) { } catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Failed to load default icon.", ex); //NOI18N NON-NLS LOGGER.log(Level.SEVERE, "Failed to load default icon.", ex); //NON-NLS
tempImage = null; tempImage = null;
} }
DEFAULT_THUMBNAIL = tempImage; DEFAULT_THUMBNAIL = tempImage;
@ -110,23 +109,22 @@ public class ImageUtils {
boolean openCVLoadedTemp; boolean openCVLoadedTemp;
try { try {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")) { //NOI18N NON-NLS if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")) { //NON-NLS
System.loadLibrary("opencv_ffmpeg248_64"); //NOI18N NON-NLS System.loadLibrary("opencv_ffmpeg248_64"); //NON-NLS
} else { } else {
System.loadLibrary("opencv_ffmpeg248"); //NOI18N NON-NLS System.loadLibrary("opencv_ffmpeg248"); //NON-NLS
} }
openCVLoadedTemp = true; openCVLoadedTemp = true;
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError e) {
openCVLoadedTemp = false; openCVLoadedTemp = false;
LOGGER.log(Level.SEVERE, "OpenCV Native code library failed to load", e); //NOI18N NON-NLS LOGGER.log(Level.SEVERE, "OpenCV Native code library failed to load", e); //NON-NLS
//TODO: show warning bubble //TODO: show warning bubble
} }
openCVLoaded = openCVLoadedTemp; openCVLoaded = openCVLoadedTemp;
SUPPORTED_IMAGE_EXTENSIONS = Arrays.asList(ImageIO.getReaderFileSuffixes()); SUPPORTED_IMAGE_EXTENSIONS = Arrays.asList(ImageIO.getReaderFileSuffixes());
SUPPORTED_IMAGE_MIME_TYPES = new TreeSet<>(Arrays.asList(ImageIO.getReaderMIMETypes())); SUPPORTED_IMAGE_MIME_TYPES = new TreeSet<>(Arrays.asList(ImageIO.getReaderMIMETypes()));
/* /*
* special cases and variants that we support, but don't get registered * special cases and variants that we support, but don't get registered
@ -137,8 +135,8 @@ public class ImageUtils {
"image/x-ms-bmp", //NON-NLS "image/x-ms-bmp", //NON-NLS
"image/x-portable-graymap", //NON-NLS "image/x-portable-graymap", //NON-NLS
"image/x-portable-bitmap", //NON-NLS "image/x-portable-bitmap", //NON-NLS
"application/x-123")); //TODO: is this correct? -jm //NOI18N NON-NLS "application/x-123")); //TODO: is this correct? -jm //NON-NLS
SUPPORTED_IMAGE_MIME_TYPES.removeIf("application/octet-stream"::equals); //NOI18N NON-NLS SUPPORTED_IMAGE_MIME_TYPES.removeIf("application/octet-stream"::equals); //NON-NLS
} }
/** /**
@ -151,7 +149,7 @@ public class ImageUtils {
*/ */
private static final Executor imageSaver private static final Executor imageSaver
= Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder() = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder()
.namingPattern("icon saver-%d").build()); //NOI18N NON-NLS .namingPattern("thumbnail-saver-%d").build()); //NON-NLS
public static List<String> getSupportedImageExtensions() { public static List<String> getSupportedImageExtensions() {
return Collections.unmodifiableList(SUPPORTED_IMAGE_EXTENSIONS); return Collections.unmodifiableList(SUPPORTED_IMAGE_EXTENSIONS);
@ -163,20 +161,7 @@ public class ImageUtils {
/** /**
* Get the default thumbnail, which is the icon for a file. Used when we can * Get the default thumbnail, which is the icon for a file. Used when we can
* not generate content based thumbnail. * not generate a content based thumbnail.
*
* @return
*
* @deprecated use {@link #getDefaultThumbnail() } instead.
*/
@Deprecated
public static Image getDefaultIcon() {
return getDefaultThumbnail();
}
/**
* Get the default thumbnail, which is the icon for a file. Used when we can
* not generate content based thumbnail.
* *
* @return the default thumbnail * @return the default thumbnail
*/ */
@ -196,9 +181,6 @@ public class ImageUtils {
*/ */
public static boolean thumbnailSupported(Content content) { public static boolean thumbnailSupported(Content content) {
if (content.getSize() == 0) {
return false;
}
if (!(content instanceof AbstractFile)) { if (!(content instanceof AbstractFile)) {
return false; return false;
} }
@ -206,79 +188,84 @@ public class ImageUtils {
return VideoUtils.isVideoThumbnailSupported(file) return VideoUtils.isVideoThumbnailSupported(file)
|| isImageThumbnailSupported(file); || isImageThumbnailSupported(file);
} }
/** /**
* is the file an image that we can read and generate a thumbnail for * Is the file an image that we can read and generate a thumbnail for?
* *
* @param file * @param file the AbstractFile to test
* *
* @return true if the file is an image we can read and generate thumbnail * @return true if the file is an image we can read and generate thumbnail
* for. * for.
*/ */
public static boolean isImageThumbnailSupported(AbstractFile file) { public static boolean isImageThumbnailSupported(AbstractFile file) {
return isMediaThumbnailSupported(file, SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS, CONDITIONAL_MIME_TYPES) return isMediaThumbnailSupported(file, "image/", SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS) || hasImageFileHeader(file);//NON-NLS
|| hasImageFileHeader(file);
} }
/** /**
* Checks the MIME type of a file to determine whether it is a GIF. If the * Checks the MIME type and/or extension of a file to determine whether it
* MIME type is not known, checks for a "gif" extension. * is a GIF.
* *
* @param file The file to be checked. * @param file the AbstractFile to test
* *
* @return True or false * @return true if the file is a gif
*/ */
public static boolean isGIF(AbstractFile file) { public static boolean isGIF(AbstractFile file) {
String mimeType = file.getMIMEType(); return isMediaThumbnailSupported(file, null, GIF_MIME_SET, GIF_EXTENSION_LIST);
if (nonNull(mimeType)) {
return IMAGE_GIF_MIME.equalsIgnoreCase(mimeType);
} else {
return "gif".equalsIgnoreCase(file.getNameExtension()); //NOI18N
}
} }
/** /**
* Check if a file is "supported" by checking its mimetype and extension * Check if making a thumbnail for the given file is supported by checking
* its extension and/or MIME type against the supplied collections.
* *
* //TODO: this should move to a better place. Should ImageUtils and * //TODO: this should move to a better place. Should ImageUtils and
* VideoUtils both implement/extend some base interface/abstract class. That * VideoUtils both implement/extend some base interface/abstract class. That
* would be the natural place to put this. * would be the natural place to put this.
* *
* @param file * @param file the AbstractFile to test
* @param supportedMimeTypes a set of mimetypes that the could have to be * @param mimeTypePrefix a MIME 'top-level type name' such as "image/",
* supported * including the "/". In addition to the list of
* @param supportedExtension a set of extensions a file could have to be * supported MIME types, any type that starts with
* supported if the mime lookup fails or is * this prefix will be regarded as supported
* inconclusive * @param supportedMimeTypes a collection of mimetypes that are supported
* @param conditionalMimes a set of mimetypes that a file could have to be * @param supportedExtension a collection of extensions that are supported
* supoprted if it also has a supported extension
* *
* @return true if a thumbnail can be generated for the given file based on * @return true if a thumbnail can be generated for the given file based on
* the given lists of supported mimetype and extensions * the given MIME type prefix and lists of supported MIME types and
* extensions
*/ */
static boolean isMediaThumbnailSupported(AbstractFile file, final SortedSet<String> supportedMimeTypes, final List<String> supportedExtension, List<String> conditionalMimes) { static boolean isMediaThumbnailSupported(AbstractFile file, String mimeTypePrefix, final Collection<String> supportedMimeTypes, final List<String> supportedExtension) {
if (file.getSize() == 0) { if (false == file.isFile() || file.getSize() <= 0) {
return false; return false;
} }
String mimeType = file.getMIMEType();
String extension = file.getNameExtension(); String extension = file.getNameExtension();
if (nonNull(mimeType)) {
return supportedMimeTypes.contains(mimeType) if (StringUtils.isNotBlank(extension) && supportedExtension.contains(extension)) {
|| (conditionalMimes.contains(mimeType.toLowerCase()) return true;
&& supportedExtension.contains(extension));
} else { } else {
return StringUtils.isNotBlank(extension) && supportedExtension.contains(extension); try {
String mimeType = getFileTypeDetector().detect(file);
if (StringUtils.isNotBlank(mimeTypePrefix) && mimeType.startsWith(mimeTypePrefix)) {
return true;
}
return supportedMimeTypes.contains(mimeType);
} catch (FileTypeDetectorInitException | TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex);//NON-NLS
return false;
}
} }
} }
/** /**
* returns a lazily instatiated FileTypeDetector * //TODO: AUT-2057 this FileTypeDetector needs to be recreated when the
* user adds new user defined file types.
*
* get a FileTypeDetector
* *
* @return a FileTypeDetector * @return a FileTypeDetector
* *
* @throws FileTypeDetectorInitException if a initializing the * @throws FileTypeDetectorInitException if initializing the
* FileTypeDetector failed. * FileTypeDetector failed.
*/ */
synchronized private static FileTypeDetector getFileTypeDetector() throws FileTypeDetector.FileTypeDetectorInitException { synchronized private static FileTypeDetector getFileTypeDetector() throws FileTypeDetector.FileTypeDetectorInitException {
@ -292,27 +279,8 @@ public class ImageUtils {
* Get a thumbnail of a specified size for the given image. Generates the * Get a thumbnail of a specified size for the given image. Generates the
* thumbnail if it is not already cached. * thumbnail if it is not already cached.
* *
* @param content * @param content the content to generate a thumbnail for
* @param iconSize * @param iconSize the size (one side of a square) in pixels to generate
*
* @return a thumbnail for the given image or a default one if there was a
* problem making a thumbnail.
*
* @deprecated use {@link #getThumbnail(org.sleuthkit.datamodel.Content, int)
* } instead.
*/
@Nonnull
@Deprecated
public static BufferedImage getIcon(Content content, int iconSize) {
return getThumbnail(content, iconSize);
}
/**
* Get a thumbnail of a specified size for the given image. Generates the
* thumbnail if it is not already cached.
*
* @param content
* @param iconSize
* *
* @return a thumbnail for the given image or a default one if there was a * @return a thumbnail for the given image or a default one if there was a
* problem making a thumbnail. * problem making a thumbnail.
@ -334,34 +302,13 @@ public class ImageUtils {
} }
} }
/**
* Get a thumbnail of a specified size for the given image. Generates the
* thumbnail if it is not already cached.
*
* @param content
* @param iconSize
*
* @return File object for cached image. Is guaranteed to exist, as long as
* there was not an error generating or saving the thumbnail.
*
* @deprecated use {@link #getCachedThumbnailFile(org.sleuthkit.datamodel.Content, int)
* } instead.
*
*/
@Nullable
@Deprecated
public static File getIconFile(Content content, int iconSize) {
return getCachedThumbnailFile(content, iconSize);
}
/** /**
* *
* Get a thumbnail of a specified size for the given image. Generates the * Get a thumbnail of a specified size for the given image. Generates the
* thumbnail if it is not already cached. * thumbnail if it is not already cached.
* *
* @param content * @param content the content to generate a thumbnail for
* @param iconSize * @param iconSize the size (one side of a square) in pixels to generate
* *
* @return File object for cached image. Is guaranteed to exist, as long as * @return File object for cached image. Is guaranteed to exist, as long as
* there was not an error generating or saving the thumbnail. * there was not an error generating or saving the thumbnail.
@ -373,26 +320,10 @@ public class ImageUtils {
} }
/** /**
* Get a file object for where the cached icon should exist. The returned * Get the location of the cached thumbnail for a file with the given fileID
* file may not exist. * as a java {@link File}. The returned File may not exist on disk yet.
* *
* @param id * @param fileID the fileID to get the cached thumbnail location for
*
* @return
*
* @deprecated use {@link #getCachedThumbnailLocation(long) } instead
*/
@Deprecated
public static File getFile(long id) {
return getCachedThumbnailLocation(id);
}
/**
* Get a file object for where the cached thumbnail should exist. The
* returned file may not exist.
*
* @param fileID
* *
* @return a File object representing the location of the cached thumbnail. * @return a File object representing the location of the cached thumbnail.
* This file may not actually exist(yet). Returns null if there was * This file may not actually exist(yet). Returns null if there was
@ -401,19 +332,18 @@ public class ImageUtils {
private static File getCachedThumbnailLocation(long fileID) { private static File getCachedThumbnailLocation(long fileID) {
try { try {
String cacheDirectory = Case.getCurrentCase().getCacheDirectory(); String cacheDirectory = Case.getCurrentCase().getCacheDirectory();
return Paths.get(cacheDirectory, "thumbnails", fileID + ".png").toFile(); //NOI18N NON-NLS return Paths.get(cacheDirectory, "thumbnails", fileID + ".png").toFile(); //NON-NLS
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
LOGGER.log(Level.WARNING, "Could not get cached thumbnail location. No case is open."); //NON-NLS LOGGER.log(Level.WARNING, "Could not get cached thumbnail location. No case is open."); //NON-NLS
return null; return null;
} }
} }
/** /**
* Do a direct check to see if the given file has an image file header. * Do a direct check to see if the given file has an image file header.
* NOTE: Currently only jpeg and png are supported. * NOTE: Currently only jpeg and png are supported.
* *
* @param file * @param file the AbstractFile to check
* *
* @return true if the given file has one of the supported image headers. * @return true if the given file has one of the supported image headers.
*/ */
@ -424,7 +354,7 @@ public class ImageUtils {
/** /**
* Check if the given file is a jpeg based on header. * Check if the given file is a jpeg based on header.
* *
* @param file * @param file the AbstractFile to check
* *
* @return true if jpeg file, false otherwise * @return true if jpeg file, false otherwise
*/ */
@ -449,7 +379,7 @@ public class ImageUtils {
/** /**
* Check if the given file is a png based on header. * Check if the given file is a png based on header.
* *
* @param file * @param file the AbstractFile to check
* *
* @return true if png file, false otherwise * @return true if png file, false otherwise
*/ */
@ -481,7 +411,7 @@ public class ImageUtils {
if (bytesRead != buffLength) { if (bytesRead != buffLength) {
//ignore if can't read the first few bytes, not an image //ignore if can't read the first few bytes, not an image
throw new TskCoreException("Could not read " + buffLength + " bytes from " + file.getName()); //NOI18N throw new TskCoreException("Could not read " + buffLength + " bytes from " + file.getName());//NON-NLS
} }
return fileHeaderBuffer; return fileHeaderBuffer;
} }
@ -498,7 +428,7 @@ public class ImageUtils {
*/ */
static public int getImageWidth(AbstractFile file) throws IOException { static public int getImageWidth(AbstractFile file) throws IOException {
return getImageProperty(file, return getImageProperty(file,
"ImageIO could not determine width of {0}: ", //NOI18N NON-NLS "ImageIO could not determine width of {0}: ", //NON-NLS
imageReader -> imageReader.getWidth(0) imageReader -> imageReader.getWidth(0)
); );
} }
@ -515,7 +445,7 @@ public class ImageUtils {
*/ */
static public int getImageHeight(AbstractFile file) throws IOException { static public int getImageHeight(AbstractFile file) throws IOException {
return getImageProperty(file, return getImageProperty(file,
"ImageIO could not determine height of {0}: ", //NOI18N NON-NLS "ImageIO could not determine height of {0}: ", //NON-NLS
imageReader -> imageReader.getHeight(0) imageReader -> imageReader.getHeight(0)
); );
} }
@ -537,7 +467,7 @@ public class ImageUtils {
/** /**
* Private template method designed to be used as the implementation of * Private template method designed to be used as the implementation of
* public methods that pull particular (usually meta-)data out of a image * public methods that pull particular (usually meta-)data out of a image
* file. ./** * file.
* *
* @param <T> the type of the property to be retrieved. * @param <T> the type of the property to be retrieved.
* @param file the file to extract the data from * @param file the file to extract the data from
@ -598,8 +528,9 @@ public class ImageUtils {
* but is not started automatically. Clients are responsible for running the * but is not started automatically. Clients are responsible for running the
* task, monitoring its progress, and using its result. * task, monitoring its progress, and using its result.
* *
* @param file the file to create a thumbnail for * @param file The file to create a thumbnail for.
* @param iconSize the size of the thumbnail * @param iconSize The size of the thumbnail.
* @param defaultOnFailure Whether or not to default on failure.
* *
* @return a new Task that returns a thumbnail as its result. * @return a new Task that returns a thumbnail as its result.
*/ */
@ -612,7 +543,7 @@ public class ImageUtils {
*/ */
static private class GetThumbnailTask extends ReadImageTaskBase { static private class GetThumbnailTask extends ReadImageTaskBase {
private static final String FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION = "Failed to read {0} for thumbnail generation."; //NOI18N NON-NLS private static final String FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION = "Failed to read {0} for thumbnail generation."; //NON-NLS
private final int iconSize; private final int iconSize;
private final File cacheFile; private final File cacheFile;
@ -646,7 +577,7 @@ public class ImageUtils {
return SwingFXUtils.toFXImage(cachedThumbnail, null); return SwingFXUtils.toFXImage(cachedThumbnail, null);
} }
} catch (Exception ex) { } catch (Exception ex) {
LOGGER.log(Level.WARNING, "ImageIO had a problem reading the cached thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS LOGGER.log(Level.WARNING, "ImageIO had a problem reading the cached thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
cacheFile.delete(); //since we can't read the file we might as well delete it. cacheFile.delete(); //since we can't read the file we might as well delete it.
} }
} }
@ -666,7 +597,7 @@ public class ImageUtils {
if (defaultOnFailure) { if (defaultOnFailure) {
thumbnail = DEFAULT_THUMBNAIL; thumbnail = DEFAULT_THUMBNAIL;
} else { } else {
throw new IIOException("Failed to generate a thumbnail for " + getContentPathSafe(file)); throw new IIOException("Failed to generate a thumbnail for " + getContentPathSafe(file));//NON-NLS
} }
} }
@ -686,7 +617,7 @@ public class ImageUtils {
thumbnail = ScalrWrapper.resizeFast(bufferedImage, iconSize); thumbnail = ScalrWrapper.resizeFast(bufferedImage, iconSize);
} catch (IllegalArgumentException | OutOfMemoryError e) { } catch (IllegalArgumentException | OutOfMemoryError e) {
// if resizing does not work due to extreme aspect ratio or oom, crop the image instead. // if resizing does not work due to extreme aspect ratio or oom, crop the image instead.
LOGGER.log(Level.WARNING, "Cropping {0}, because it could not be scaled: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS LOGGER.log(Level.WARNING, "Cropping {0}, because it could not be scaled: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
final int height = bufferedImage.getHeight(); final int height = bufferedImage.getHeight();
final int width = bufferedImage.getWidth(); final int width = bufferedImage.getWidth();
@ -696,11 +627,11 @@ public class ImageUtils {
try { try {
thumbnail = ScalrWrapper.cropImage(bufferedImage, cropWidth, cropHeight); thumbnail = ScalrWrapper.cropImage(bufferedImage, cropWidth, cropHeight);
} catch (Exception cropException) { } catch (Exception cropException) {
LOGGER.log(Level.WARNING, "Could not crop {0}: " + cropException.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS LOGGER.log(Level.WARNING, "Could not crop {0}: " + cropException.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
} }
} }
} catch (Exception e) { } catch (Exception e) {
LOGGER.log(Level.WARNING, "Could not scale {0}: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS LOGGER.log(Level.WARNING, "Could not scale {0}: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
throw e; throw e;
} }
} }
@ -733,7 +664,7 @@ public class ImageUtils {
} }
ImageIO.write(thumbnail, FORMAT, cacheFile); ImageIO.write(thumbnail, FORMAT, cacheFile);
} catch (IllegalArgumentException | IOException ex) { } catch (IllegalArgumentException | IOException ex) {
LOGGER.log(Level.WARNING, "Could not write thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS LOGGER.log(Level.WARNING, "Could not write thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
} }
}); });
} }
@ -745,7 +676,8 @@ public class ImageUtils {
* *
* Note: the returned task is suitable for running in a background thread, * Note: the returned task is suitable for running in a background thread,
* but is not started automatically. Clients are responsible for running the * but is not started automatically. Clients are responsible for running the
* task, monitoring its progress, and using its result. * task, monitoring its progress, and using its result(including testing for
* null).
* *
* @param file the file to read as an Image * @param file the file to read as an Image
* *
@ -779,7 +711,7 @@ public class ImageUtils {
*/ */
static private abstract class ReadImageTaskBase extends Task<javafx.scene.image.Image> implements IIOReadProgressListener { static private abstract class ReadImageTaskBase extends Task<javafx.scene.image.Image> implements IIOReadProgressListener {
private static final String IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT = "ImageIO could not read {0}. It may be unsupported or corrupt"; //NOI18N NON-NLS private static final String IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT = "ImageIO could not read {0}. It may be unsupported or corrupt"; //NON-NLS
final AbstractFile file; final AbstractFile file;
// private ImageReader reader; // private ImageReader reader;
@ -815,7 +747,7 @@ public class ImageUtils {
try { try {
bufferedImage = imageReader.read(0, param); //should always be same bufferedImage object bufferedImage = imageReader.read(0, param); //should always be same bufferedImage object
} catch (IOException iOException) { } catch (IOException iOException) {
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + iOException.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + iOException.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
} finally { } finally {
imageReader.removeIIOReadProgressListener(ReadImageTaskBase.this); imageReader.removeIIOReadProgressListener(ReadImageTaskBase.this);
} }
@ -901,15 +833,85 @@ public class ImageUtils {
* *
* @param content * @param content
* *
* @return * @return the unique path for the content, or if that fails, just the name.
*/ */
static String getContentPathSafe(Content content) { static String getContentPathSafe(Content content) {
try { try {
return content.getUniquePath(); return content.getUniquePath();
} catch (TskCoreException tskCoreException) { } catch (TskCoreException tskCoreException) {
String contentName = content.getName(); String contentName = content.getName();
LOGGER.log(Level.SEVERE, "Failed to get unique path for " + contentName, tskCoreException); //NOI18N NON-NLS LOGGER.log(Level.SEVERE, "Failed to get unique path for " + contentName, tskCoreException); //NON-NLS
return contentName; return contentName;
} }
} }
/**
* Get the default thumbnail, which is the icon for a file. Used when we can
* not generate content based thumbnail.
*
* @return
*
* @deprecated use {@link #getDefaultThumbnail() } instead.
*/
@Deprecated
public static Image getDefaultIcon() {
return getDefaultThumbnail();
}
/**
* Get a file object for where the cached icon should exist. The returned
* file may not exist.
*
* @param id
*
* @return
*
* @deprecated use {@link #getCachedThumbnailLocation(long) } instead
*/
@Deprecated
public static File getFile(long id) {
return getCachedThumbnailLocation(id);
}
/**
* Get a thumbnail of a specified size for the given image. Generates the
* thumbnail if it is not already cached.
*
* @param content
* @param iconSize
*
* @return a thumbnail for the given image or a default one if there was a
* problem making a thumbnail.
*
* @deprecated use {@link #getThumbnail(org.sleuthkit.datamodel.Content, int)
* } instead.
*/
@Nonnull
@Deprecated
public static BufferedImage getIcon(Content content, int iconSize) {
return getThumbnail(content, iconSize);
}
/**
* Get a thumbnail of a specified size for the given image. Generates the
* thumbnail if it is not already cached.
*
* @param content
* @param iconSize
*
* @return File object for cached image. Is guaranteed to exist, as long as
* there was not an error generating or saving the thumbnail.
*
* @deprecated use {@link #getCachedThumbnailFile(org.sleuthkit.datamodel.Content, int)
* } instead.
*
*/
@Nullable
@Deprecated
public static File getIconFile(Content content, int iconSize) {
return getCachedThumbnailFile(content, iconSize);
}
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -25,14 +25,12 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.LnkEnums.CommonCLSIDS; import org.sleuthkit.autopsy.coreutils.LnkEnums.CommonCLSIDS;
import org.sleuthkit.autopsy.coreutils.LnkEnums.DriveType; import org.sleuthkit.autopsy.coreutils.LnkEnums.DriveType;
import org.sleuthkit.autopsy.coreutils.LnkEnums.NetworkProviderType; import org.sleuthkit.autopsy.coreutils.LnkEnums.NetworkProviderType;
/** /**
* * Parse lnk files using documentation from:
* @author dfickling Parse lnk files using documentation from
* http://msdn.microsoft.com/en-us/library/dd871305(v=prot.13).aspx * http://msdn.microsoft.com/en-us/library/dd871305(v=prot.13).aspx
* http://msdn.microsoft.com/en-us/library/windows/desktop/cc144090(v=vs.85).aspx#unknown_74413 * http://msdn.microsoft.com/en-us/library/windows/desktop/cc144090(v=vs.85).aspx#unknown_74413
* http://blog.0x01000000.org/2010/08/10/lnk-parsing-youre-doing-it-wrong-i/ * http://blog.0x01000000.org/2010/08/10/lnk-parsing-youre-doing-it-wrong-i/
@ -67,12 +65,12 @@ public class JLnkParser {
int showCommand = bb.getInt(); int showCommand = bb.getInt();
short hotkey = bb.getShort(); short hotkey = bb.getShort();
bb.get(new byte[10]); // reserved (???) bb.get(new byte[10]); // reserved (???)
List<String> linkTargetIdList = new ArrayList<String>(); List<String> linkTargetIdList = new ArrayList<>();
if ((linkFlags & LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) if ((linkFlags & LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag())
== LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) { == LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) {
int idListSize = bb.getShort(); int idListSize = bb.getShort();
int bytesRead = 0; int bytesRead = 0;
List<byte[]> linkTargetIdListBytes = new ArrayList<byte[]>(); List<byte[]> linkTargetIdListBytes = new ArrayList<>();
while (true) { while (true) {
short itemIdSize = bb.getShort(); short itemIdSize = bb.getShort();
if (itemIdSize == 0) { if (itemIdSize == 0) {
@ -82,7 +80,7 @@ public class JLnkParser {
byte[] theArray = new byte[itemIdSize - 2]; byte[] theArray = new byte[itemIdSize - 2];
bb.get(theArray); // an idlist data object bb.get(theArray); // an idlist data object
linkTargetIdListBytes.add(theArray); linkTargetIdListBytes.add(theArray);
bytesRead = bytesRead + itemIdSize; bytesRead += itemIdSize;
} }
linkTargetIdList = parseLinkTargetIdList(linkTargetIdListBytes); linkTargetIdList = parseLinkTargetIdList(linkTargetIdListBytes);
} }
@ -272,7 +270,7 @@ public class JLnkParser {
} }
private List<String> parseLinkTargetIdList(List<byte[]> idList) { private List<String> parseLinkTargetIdList(List<byte[]> idList) {
List<String> ret = new ArrayList<String>(); List<String> ret = new ArrayList<>();
if (!idList.isEmpty()) { if (!idList.isEmpty()) {
CommonCLSIDS clsid = CommonCLSIDS.valueOf(Arrays.copyOfRange(idList.remove(0), 2, 18)); CommonCLSIDS clsid = CommonCLSIDS.valueOf(Arrays.copyOfRange(idList.remove(0), 2, 18));
switch (clsid) { switch (clsid) {
@ -295,7 +293,7 @@ public class JLnkParser {
} }
private List<String> parsePathElements(List<byte[]> idList) { private List<String> parsePathElements(List<byte[]> idList) {
List<String> ret = new ArrayList<String>(); List<String> ret = new ArrayList<>();
for (byte[] pathElement : idList) { for (byte[] pathElement : idList) {
ByteBuffer bb = ByteBuffer.wrap(pathElement); ByteBuffer bb = ByteBuffer.wrap(pathElement);
bb.order(ByteOrder.LITTLE_ENDIAN); bb.order(ByteOrder.LITTLE_ENDIAN);

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -60,7 +60,8 @@ public class UNCPathUtilities {
/** /**
* This method converts a passed in path to UNC if it is not already UNC. * This method converts a passed in path to UNC if it is not already UNC.
* The UNC path will end up in one of the following two forms: * The UNC path will end up in one of the following two forms:
* \\hostname\somefolder\otherfolder or \\IP_ADDRESS\somefolder\otherfolder * "\\hostname\somefolder\otherfolder" or
* "\\IP_ADDRESS\somefolder\otherfolder"
* *
* This is accomplished by checking the mapped drives list the operating * This is accomplished by checking the mapped drives list the operating
* system maintains and substituting where required. If the drive of the * system maintains and substituting where required. If the drive of the
@ -167,9 +168,10 @@ public class UNCPathUtilities {
/** /**
* Takes a UNC path that may have an IP address in it and converts it to * Takes a UNC path that may have an IP address in it and converts it to
* hostname, if it can resolve the hostname. Given * hostname, if it can resolve the hostname. Given
* \\10.11.12.13\some\folder, the result will be \\TEDS_COMPUTER\some\folder * "\\10.11.12.13\some\folder", the result will be
* if the IP address 10.11.12.13 belongs to a machine with the hostname * "\\TEDS_COMPUTER\some\folder" if the IP address 10.11.12.13 belongs to a
* TEDS_COMPUTER and the local machine is able to resolve the hostname. * machine with the hostname TEDS_COMPUTER and the local machine is able to
* resolve the hostname.
* *
* @param inputPath the path to convert to a hostname UNC path * @param inputPath the path to convert to a hostname UNC path
* *
@ -186,9 +188,10 @@ public class UNCPathUtilities {
/** /**
* Takes a UNC path that may have an IP address in it and converts it to * Takes a UNC path that may have an IP address in it and converts it to
* hostname, if it can resolve the hostname. Given * hostname, if it can resolve the hostname. Given
* \\10.11.12.13\some\folder, the result will be \\TEDS_COMPUTER\some\folder * "\\10.11.12.13\some\folder", the result will be
* if the IP address 10.11.12.13 belongs to a machine with the hostname * "\\TEDS_COMPUTER\some\folder" if the IP address 10.11.12.13 belongs to a
* TEDS_COMPUTER and the local machine is able to resolve the hostname. * machine with the hostname TEDS_COMPUTER and the local machine is able to
* resolve the hostname.
* *
* @param inputPath a String of the path to convert to a hostname UNC path * @param inputPath a String of the path to convert to a hostname UNC path
* *
@ -263,6 +266,11 @@ public class UNCPathUtilities {
*/ */
synchronized private Map<String, String> getMappedDrives() { synchronized private Map<String, String> getMappedDrives() {
Map<String, String> driveMap = new HashMap<>(); Map<String, String> driveMap = new HashMap<>();
if (PlatformUtil.isWindowsOS() == false) {
return driveMap;
}
File mappedDrive = Paths.get(System.getenv(TEMP_FOLDER), nameString + MAPPED_DRIVES).toFile(); File mappedDrive = Paths.get(System.getenv(TEMP_FOLDER), nameString + MAPPED_DRIVES).toFile();
try { try {
Files.deleteIfExists(mappedDrive.toPath()); Files.deleteIfExists(mappedDrive.toPath());

View File

@ -60,10 +60,17 @@ public class VideoUtils {
"flm", "tmv", "4xm"); //NON-NLS "flm", "tmv", "4xm"); //NON-NLS
private static final SortedSet<String> SUPPORTED_VIDEO_MIME_TYPES = new TreeSet<>( private static final SortedSet<String> SUPPORTED_VIDEO_MIME_TYPES = new TreeSet<>(
Arrays.asList("application/x-shockwave-flash", "video/x-m4v", "video/x-flv", "video/quicktime", "video/avi", "video/msvideo", "video/x-msvideo", //NON-NLS Arrays.asList("application/x-shockwave-flash",
"video/mp4", "video/x-ms-wmv", "video/mpeg", "video/asf")); //NON-NLS "video/x-m4v",
"video/x-flv",
private static final List<String> CONDITIONAL_MIME_TYPES = Arrays.asList("application/octet-stream"); //NON-NLS "video/quicktime",
"video/avi",
"video/msvideo",
"video/x-msvideo", //NON-NLS
"video/mp4",
"video/x-ms-wmv",
"video/mpeg",
"video/asf")); //NON-NLS
public static List<String> getSupportedVideoExtensions() { public static List<String> getSupportedVideoExtensions() {
return SUPPORTED_VIDEO_EXTENSIONS; return SUPPORTED_VIDEO_EXTENSIONS;
@ -89,7 +96,7 @@ public class VideoUtils {
} }
public static boolean isVideoThumbnailSupported(AbstractFile file) { public static boolean isVideoThumbnailSupported(AbstractFile file) {
return isMediaThumbnailSupported(file, SUPPORTED_VIDEO_MIME_TYPES, SUPPORTED_VIDEO_EXTENSIONS, CONDITIONAL_MIME_TYPES); return isMediaThumbnailSupported(file, "video/", SUPPORTED_VIDEO_MIME_TYPES, SUPPORTED_VIDEO_EXTENSIONS);
} }
@NbBundle.Messages({"# {0} - file name", @NbBundle.Messages({"# {0} - file name",

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2013 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -50,6 +50,7 @@ public class ArtifactStringContent implements StringContent {
} }
@Override @Override
@SuppressWarnings("deprecation")
public String getString() { public String getString() {
if (stringContent.isEmpty()) { if (stringContent.isEmpty()) {
try { try {

View File

@ -286,25 +286,19 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
* are put * are put
* @param artifact to extract properties from * @param artifact to extract properties from
*/ */
@SuppressWarnings("deprecation") // TODO: Remove this when TSK_TAGGED_ARTIFACT rows are removed in a database upgrade. @SuppressWarnings("deprecation")
private void fillPropertyMap(Map<String, Object> map, BlackboardArtifact artifact) { private void fillPropertyMap(Map<String, Object> map, BlackboardArtifact artifact) {
try { try {
for (BlackboardAttribute attribute : artifact.getAttributes()) { for (BlackboardAttribute attribute : artifact.getAttributes()) {
final int attributeTypeID = attribute.getAttributeTypeID(); final int attributeTypeID = attribute.getAttributeType().getTypeID();
//skip some internal attributes that user shouldn't see //skip some internal attributes that user shouldn't see
if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID() if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) { || attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
} else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID() continue;
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID() } else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID() map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()) {
map.put(attribute.getAttributeTypeDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
} else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID() } else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
&& attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) { && attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) {
/* /*
@ -318,9 +312,9 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
if (value.length() > 512) { if (value.length() > 512) {
value = value.substring(0, 512); value = value.substring(0, 512);
} }
map.put(attribute.getAttributeTypeDisplayName(), value); map.put(attribute.getAttributeType().getDisplayName(), value);
} else { } else {
map.put(attribute.getAttributeTypeDisplayName(), attribute.getDisplayString()); map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
} }
} }
} catch (TskException ex) { } catch (TskException ex) {

View File

@ -210,29 +210,17 @@ public class ExtractedContent implements AutopsyVisitableItem {
// these are shown in other parts of the UI tree // these are shown in other parts of the UI tree
doNotShow.add(new BlackboardArtifact.Type( doNotShow.add(new BlackboardArtifact.Type(
BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO));
BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getLabel(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getDisplayName()));
doNotShow.add(new BlackboardArtifact.Type( doNotShow.add(new BlackboardArtifact.Type(
BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG));
BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getLabel(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getDisplayName()));
doNotShow.add(new BlackboardArtifact.Type( doNotShow.add(new BlackboardArtifact.Type(
BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT));
BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getLabel(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName()));
doNotShow.add(new BlackboardArtifact.Type( doNotShow.add(new BlackboardArtifact.Type(
BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT));
BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getLabel(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName()));
doNotShow.add(new BlackboardArtifact.Type( doNotShow.add(new BlackboardArtifact.Type(
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT));
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getLabel(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getDisplayName()));
doNotShow.add(new BlackboardArtifact.Type( doNotShow.add(new BlackboardArtifact.Type(
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT));
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getLabel(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getDisplayName()));
} }
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.datamodel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.Action; import javax.swing.Action;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.actions.AddContentTagAction; import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
@ -110,70 +111,52 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
// file based off it's extension // file based off it's extension
static String getIconForFileType(AbstractFile file) { static String getIconForFileType(AbstractFile file) {
// Get the name, extension // Get the name, extension
String name = file.getName(); String ext = file.getNameExtension();
int dotIndex = name.lastIndexOf(".");
if (dotIndex == -1) {
return "org/sleuthkit/autopsy/images/file-icon.png"; //NON-NLS
}
String ext = name.substring(dotIndex).toLowerCase();
// Images if (StringUtils.isBlank(ext)) {
for (String s : FileTypeExtensions.getImageExtensions()) { return "org/sleuthkit/autopsy/images/file-icon.png"; //NON-NLS
if (ImageUtils.thumbnailSupported(file) || ext.equals(s)) { } else {
ext = "." + ext;
}
if (ImageUtils.isImageThumbnailSupported(file)
|| FileTypeExtensions.getImageExtensions().contains(ext)) {
return "org/sleuthkit/autopsy/images/image-file.png"; //NON-NLS return "org/sleuthkit/autopsy/images/image-file.png"; //NON-NLS
} }
}
// Videos // Videos
for (String s : FileTypeExtensions.getVideoExtensions()) { if (FileTypeExtensions.getVideoExtensions().contains(ext)) {
if (ext.equals(s)) {
return "org/sleuthkit/autopsy/images/video-file.png"; //NON-NLS return "org/sleuthkit/autopsy/images/video-file.png"; //NON-NLS
} }
}
// Audio Files // Audio Files
for (String s : FileTypeExtensions.getAudioExtensions()) { if (FileTypeExtensions.getAudioExtensions().contains(ext)) {
if (ext.equals(s)) {
return "org/sleuthkit/autopsy/images/audio-file.png"; //NON-NLS return "org/sleuthkit/autopsy/images/audio-file.png"; //NON-NLS
} }
}
// Documents // Documents
for (String s : FileTypeExtensions.getDocumentExtensions()) { if (FileTypeExtensions.getDocumentExtensions().contains(ext)) {
if (ext.equals(s)) {
return "org/sleuthkit/autopsy/images/doc-file.png"; //NON-NLS return "org/sleuthkit/autopsy/images/doc-file.png"; //NON-NLS
} }
}
// Executables / System Files // Executables / System Files
for (String s : FileTypeExtensions.getExecutableExtensions()) { if (FileTypeExtensions.getExecutableExtensions().contains(ext)) {
if (ext.equals(s)) {
return "org/sleuthkit/autopsy/images/exe-file.png"; //NON-NLS return "org/sleuthkit/autopsy/images/exe-file.png"; //NON-NLS
} }
}
// Text Files // Text Files
for (String s : FileTypeExtensions.getTextExtensions()) { if (FileTypeExtensions.getTextExtensions().contains(ext)) {
if (ext.equals(s)) {
return "org/sleuthkit/autopsy/images/text-file.png"; //NON-NLS return "org/sleuthkit/autopsy/images/text-file.png"; //NON-NLS
} }
}
// Web Files // Web Files
for (String s : FileTypeExtensions.getWebExtensions()) { if (FileTypeExtensions.getWebExtensions().contains(ext)) {
if (ext.equals(s)) {
return "org/sleuthkit/autopsy/images/web-file.png"; //NON-NLS return "org/sleuthkit/autopsy/images/web-file.png"; //NON-NLS
} }
}
// PDFs // PDFs
for (String s : FileTypeExtensions.getPDFExtensions()) { if (FileTypeExtensions.getPDFExtensions().contains(ext)) {
if (ext.equals(s)) {
return "org/sleuthkit/autopsy/images/pdf-file.png"; //NON-NLS return "org/sleuthkit/autopsy/images/pdf-file.png"; //NON-NLS
} }
}
// Archives // Archives
for (String s : FileTypeExtensions.getArchiveExtensions()) { if (FileTypeExtensions.getArchiveExtensions().contains(ext)) {
if (ext.equals(s)) {
return "org/sleuthkit/autopsy/images/archive-file.png"; //NON-NLS return "org/sleuthkit/autopsy/images/archive-file.png"; //NON-NLS
} }
}
// Else return the default // Else return the default
return "org/sleuthkit/autopsy/images/file-icon.png"; //NON-NLS return "org/sleuthkit/autopsy/images/file-icon.png"; //NON-NLS
} }
@Override @Override

View File

@ -55,7 +55,7 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
//set icon for name, special case for some built-ins //set icon for name, special case for some built-ins
if (name.equals(VirtualDirectory.NAME_UNALLOC)) { if (name.equals(VirtualDirectory.NAME_UNALLOC)) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-deleted.png"); //NON-NLS this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-deleted.png"); //NON-NLS
} else if (name.startsWith(LOGICAL_FILE_SET_PREFIX)) { } else if (ld.isDataSource()) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS
} else if (name.equals(VirtualDirectory.NAME_CARVED)) { } else if (name.equals(VirtualDirectory.NAME_CARVED)) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/Folder-icon.png"); //TODO NON-NLS this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/Folder-icon.png"); //TODO NON-NLS

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -26,7 +26,6 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
@ -34,7 +33,6 @@ import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.coreutils.ErrorInfo; import org.sleuthkit.autopsy.coreutils.ErrorInfo;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
@ -72,8 +70,9 @@ public final class ExternalResultsImporter {
* artifacts, derived files, reports)from the data source. * artifacts, derived files, reports)from the data source.
* *
* @return A collection of error messages, possibly empty. The error * @return A collection of error messages, possibly empty. The error
* messages are already logged but are provided to allow the caller to * messages are already logged but are provided to allow the caller
* provide additional user feedback via the Autopsy user interface. * to provide additional user feedback via the Autopsy user
* interface.
*/ */
public List<ErrorInfo> importResults(ExternalResults results) { public List<ErrorInfo> importResults(ExternalResults results) {
blackboard = Case.getCurrentCase().getServices().getBlackboard(); blackboard = Case.getCurrentCase().getServices().getBlackboard();
@ -133,7 +132,7 @@ public final class ExternalResultsImporter {
for (ExternalResults.Artifact artifactData : results.getArtifacts()) { for (ExternalResults.Artifact artifactData : results.getArtifacts()) {
try { try {
// Add the artifact to the case database. // Add the artifact to the case database.
int artifactTypeId = caseDb.getArtifactTypeID(artifactData.getType()); int artifactTypeId = caseDb.getArtifactType(artifactData.getType()).getTypeID();
if (artifactTypeId == -1) { if (artifactTypeId == -1) {
artifactTypeId = caseDb.addBlackboardArtifactType(artifactData.getType(), artifactData.getType()).getTypeID(); artifactTypeId = caseDb.addBlackboardArtifactType(artifactData.getType(), artifactData.getType()).getTypeID();
} }
@ -216,13 +215,7 @@ public final class ExternalResultsImporter {
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage); ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage)); this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage));
} }
} catch (TskCoreException ex) { } catch (TskCoreException | TskDataException ex) {
String errorMessage = NbBundle.getMessage(this.getClass(),
"ExternalResultsImporter.importArtifacts.errMsg2.text",
artifactData.getType(), artifactData.getSourceFilePath());
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage, ex);
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage, ex));
} catch (TskDataException ex) {
String errorMessage = NbBundle.getMessage(this.getClass(), String errorMessage = NbBundle.getMessage(this.getClass(),
"ExternalResultsImporter.importArtifacts.errMsg2.text", "ExternalResultsImporter.importArtifacts.errMsg2.text",
artifactData.getType(), artifactData.getSourceFilePath()); artifactData.getType(), artifactData.getSourceFilePath());
@ -299,15 +292,6 @@ public final class ExternalResultsImporter {
return relativePath; return relativePath;
} }
// private static boolean isStandardArtifactType(int artifactTypeId) {
// for (BlackboardArtifact.ARTIFACT_TYPE art : BlackboardArtifact.ARTIFACT_TYPE.values()) {
// if (art.getTypeID() == artifactTypeId) {
// return true;
// }
// }
// return false;
// }
//
private void recordError(String errorMessage) { private void recordError(String errorMessage) {
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage); ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
this.errors.add(new ErrorInfo(this.getClass().getName(), errorMessage)); this.errors.add(new ErrorInfo(this.getClass().getName(), errorMessage));

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -117,6 +117,7 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
/** /**
* Constructor. * Constructor.
* *
* @param dataSource The data source for the results.
* @param resultsFilePath Full path of the results file to be parsed. * @param resultsFilePath Full path of the results file to be parsed.
*/ */
public ExternalResultsXMLParser(Content dataSource, String resultsFilePath) { public ExternalResultsXMLParser(Content dataSource, String resultsFilePath) {

View File

@ -18,7 +18,7 @@ DateSearchPanel.jLabel1.text=to
DateSearchPanel.dateFromTextField.text= DateSearchPanel.dateFromTextField.text=
DateSearchPanel.dateFromButtonCalendar.text= DateSearchPanel.dateFromButtonCalendar.text=
NameSearchPanel.nameCheckBox.text=Name: NameSearchPanel.nameCheckBox.text=Name:
NameSearchPanel.noteNameLabel.text=<html>*Note: Name match is case insensitive and matches<br/> any part of the file name. Regular expressions are<br/> not currently supported. </html> NameSearchPanel.noteNameLabel.text=<html>*Note: Name match is case insensitive and matches any part of the file name. Regular expressions are not currently supported.</html>
NameSearchPanel.searchTextField.text= NameSearchPanel.searchTextField.text=
SizeSearchPanel.sizeCheckBox.text=Size: SizeSearchPanel.sizeCheckBox.text=Size:
NameSearchPanel.cutMenuItem.text=Cut NameSearchPanel.cutMenuItem.text=Cut
@ -40,7 +40,6 @@ FileSearchPanel.custComp.label.text=Search for files that match the following cr
FileSearchPanel.filterTitle.name=Name FileSearchPanel.filterTitle.name=Name
FileSearchPanel.filterTitle.metadata=Metadata FileSearchPanel.filterTitle.metadata=Metadata
FileSearchPanel.filterTitle.knownStatus=Known Status FileSearchPanel.filterTitle.knownStatus=Known Status
FileSearchPanel.searchButton.text=Search
FileSearchPanel.search.results.title=File Search Results {0} FileSearchPanel.search.results.title=File Search Results {0}
FileSearchPanel.search.results.pathText=Filename Search Results\: FileSearchPanel.search.results.pathText=Filename Search Results\:
FileSearchPanel.search.results.msg=File Search\: {0} matches found FileSearchPanel.search.results.msg=File Search\: {0} matches found
@ -54,3 +53,6 @@ SearchNode.getName.text=Search Result
SizeSearchPanel.sizeCompareComboBox.equalTo=equal to SizeSearchPanel.sizeCompareComboBox.equalTo=equal to
SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than
SizeSearchPanel.sizeCompareComboBox.lessThan=less than SizeSearchPanel.sizeCompareComboBox.lessThan=less than
MimeTypePanel.jCheckBox1.text=MIME Type:
MimeTypePanel.jLabel1.text=*Note: Multiple MIME types can be selected
FileSearchPanel.searchButton.text=Search

View File

@ -1,51 +1,50 @@
OpenIDE-Module-Name=\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 OpenIDE-Module-Name=\u30d5\u30a1\u30a4\u30eb\u691c\u7d22
KnownStatusSearchPanel.knownCheckBox.text=\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9\uFF1A KnownStatusSearchPanel.knownCheckBox.text=\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9\uff1a
KnownStatusSearchPanel.knownBadOptionCheckBox.text=\u65E2\u77E5\u306E\u60AA\u8CEA KnownStatusSearchPanel.knownBadOptionCheckBox.text=\u65e2\u77e5\u306e\u60aa\u8cea
KnownStatusSearchPanel.knownOptionCheckBox.text=\u65E2\u77E5\uFF08NSRL\u307E\u305F\u306F\u305D\u306E\u4ED6\uFF09 KnownStatusSearchPanel.knownOptionCheckBox.text=\u65e2\u77e5\uff08NSRL\u307e\u305f\u306f\u305d\u306e\u4ed6\uff09
KnownStatusSearchPanel.unknownOptionCheckBox.text=\u4E0D\u660E KnownStatusSearchPanel.unknownOptionCheckBox.text=\u4e0d\u660e
DateSearchFilter.noneSelectedMsg.text=\u6700\u4F4E\u4E00\u3064\u306E\u30C7\u30FC\u30BF\u30BF\u30A4\u30D7\u3092\u9078\u629E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF01 DateSearchFilter.noneSelectedMsg.text=\u6700\u4f4e\u4e00\u3064\u306e\u30c7\u30fc\u30bf\u30bf\u30a4\u30d7\u3092\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\uff01
DateSearchPanel.dateCheckBox.text=\u65E5\u4ED8\uFF1A DateSearchPanel.dateCheckBox.text=\u65e5\u4ed8\uff1a
DateSearchPanel.jLabel4.text=\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\uFF1A DateSearchPanel.jLabel4.text=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\uff1a
DateSearchPanel.jLabel3.text=*\u65E5\u4ED8\u306E\u5F62\u5F0F\u306Fmm/dd/yyyy DateSearchPanel.jLabel3.text=*\u65e5\u4ed8\u306e\u5f62\u5f0f\u306fmm/dd/yyyy
DateSearchPanel.jLabel2.text=*\u7A7A\u767D\u306E\u9805\u76EE\u306F\u300C\u5236\u9650\u306A\u3057\u300D\u3068\u3044\u3046\u610F\u5473\u3067\u3059 DateSearchPanel.jLabel2.text=*\u7a7a\u767d\u306e\u9805\u76ee\u306f\u300c\u5236\u9650\u306a\u3057\u300d\u3068\u3044\u3046\u610f\u5473\u3067\u3059
DateSearchPanel.createdCheckBox.text=\u4F5C\u6210\u6E08\u307F DateSearchPanel.createdCheckBox.text=\u4f5c\u6210\u6e08\u307f
DateSearchPanel.accessedCheckBox.text=\u30A2\u30AF\u30BB\u30B9\u6E08\u307F DateSearchPanel.accessedCheckBox.text=\u30a2\u30af\u30bb\u30b9\u6e08\u307f
DateSearchPanel.changedCheckBox.text=\u5909\u66F4\u6E08\u307F DateSearchPanel.changedCheckBox.text=\u5909\u66f4\u6e08\u307f
DateSearchPanel.modifiedCheckBox.text=\u4FEE\u6B63\u6E08\u307F DateSearchPanel.modifiedCheckBox.text=\u4fee\u6b63\u6e08\u307f
DateSearchPanel.jLabel1.text=to DateSearchPanel.jLabel1.text=to
NameSearchPanel.nameCheckBox.text=\u540D\u524D\uFF1A NameSearchPanel.nameCheckBox.text=\u540d\u524d\uff1a
NameSearchPanel.noteNameLabel.text=<html>*\u6CE8\u610F\uFF1A\u540D\u524D\u30DE\u30C3\u30C1\u306F\u5927\u6587\u5B57\u3068\u5C0F\u6587\u5B57\u3092\u533A\u5225\u3057\u307E\u3059\u3002\u307E\u305F\u3001<br/> \u30D5\u30A1\u30A4\u30EB\u540D\u306E\u3044\u304B\u306A\u308B\u90E8\u5206\u3082\u30DE\u30C3\u30C1\u3057\u307E\u3059\u3002\u6B63\u898F\u8868\u73FE\u306F<br/>\u73FE\u5728\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 </html> NameSearchPanel.noteNameLabel.text=<html>*\u6ce8\u610f\uff1a\u540d\u524d\u30de\u30c3\u30c1\u306f\u5927\u6587\u5b57\u3068\u5c0f\u6587\u5b57\u3092\u533a\u5225\u3057\u307e\u3059\u3002\u307e\u305f\u3001<br/> \u30d5\u30a1\u30a4\u30eb\u540d\u306e\u3044\u304b\u306a\u308b\u90e8\u5206\u3082\u30de\u30c3\u30c1\u3057\u307e\u3059\u3002\u6b63\u898f\u8868\u73fe\u306f<br/>\u73fe\u5728\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 </html>
SizeSearchPanel.sizeCheckBox.text=\u30B5\u30A4\u30BA\uFF1A SizeSearchPanel.sizeCheckBox.text=\u30b5\u30a4\u30ba\uff1a
NameSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8 NameSearchPanel.cutMenuItem.text=\u30ab\u30c3\u30c8
NameSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC NameSearchPanel.copyMenuItem.text=\u30b3\u30d4\u30fc
NameSearchPanel.pasteMenuItem.text=\u8CBC\u308A\u4ED8\u3051 NameSearchPanel.pasteMenuItem.text=\u8cbc\u308a\u4ed8\u3051
NameSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E NameSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e
SizeSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E SizeSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e
SizeSearchPanel.pasteMenuItem.text=\u8CBC\u308A\u4ED8\u3051 SizeSearchPanel.pasteMenuItem.text=\u8cbc\u308a\u4ed8\u3051
SizeSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC SizeSearchPanel.copyMenuItem.text=\u30b3\u30d4\u30fc
SizeSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8 SizeSearchPanel.cutMenuItem.text=\u30ab\u30c3\u30c8
DateSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8 DateSearchPanel.cutMenuItem.text=\u30ab\u30c3\u30c8
DateSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E DateSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e
DateSearchPanel.pasteMenuItem.text=\u8CBC\u308A\u4ED8\u3051 DateSearchPanel.pasteMenuItem.text=\u8cbc\u308a\u4ed8\u3051
DateSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC DateSearchPanel.copyMenuItem.text=\u30b3\u30d4\u30fc
FileSearchAction.getName.text=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 FileSearchAction.getName.text=\u5c5e\u6027\u306b\u3088\u308b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22
FileSearchDialog.frame.title=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 FileSearchDialog.frame.title=\u5c5e\u6027\u306b\u3088\u308b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22
FileSearchDialog.frame.msg=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 FileSearchDialog.frame.msg=\u5c5e\u6027\u306b\u3088\u308b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22
FileSearchPanel.custComp.label.text=\u6B21\u306E\u6761\u4EF6\u306B\u4E00\u81F4\u3059\u308B\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\uFF1A FileSearchPanel.custComp.label.text=\u6b21\u306e\u6761\u4ef6\u306b\u4e00\u81f4\u3059\u308b\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22\uff1a
FileSearchPanel.filterTitle.name=\u540D\u524D FileSearchPanel.filterTitle.name=\u540d\u524d
FileSearchPanel.filterTitle.metadata=\u30E1\u30BF\u30C7\u30FC\u30BF FileSearchPanel.filterTitle.metadata=\u30e1\u30bf\u30c7\u30fc\u30bf
FileSearchPanel.filterTitle.knownStatus=\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9 FileSearchPanel.filterTitle.knownStatus=\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9
FileSearchPanel.searchButton.text=\u691C\u7D22 FileSearchPanel.search.results.title=\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u7d50\u679c{0}
FileSearchPanel.search.results.title=\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u7D50\u679C{0} FileSearchPanel.search.results.pathText=\u30d5\u30a1\u30a4\u30eb\u540d\u691c\u7d22\u7d50\u679c\uff1a
FileSearchPanel.search.results.pathText=\u30D5\u30A1\u30A4\u30EB\u540D\u691C\u7D22\u7D50\u679C\uFF1A FileSearchPanel.search.results.msg=\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\uff1a{0}\u500b\u306e\u30de\u30c3\u30c1\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f
FileSearchPanel.search.results.msg=\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\uFF1A{0}\u500B\u306E\u30DE\u30C3\u30C1\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F FileSearchPanel.search.results.details=\u591a\u304f\u306e\u30de\u30c3\u30c1\u304c\u3042\u308b\u5834\u5408\u3001\u4e00\u90e8\u306e\u51e6\u7406\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u306b\u5f71\u97ff\u3092\u4e0e\u3048\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093
FileSearchPanel.search.results.details=\u591A\u304F\u306E\u30DE\u30C3\u30C1\u304C\u3042\u308B\u5834\u5408\u3001\u4E00\u90E8\u306E\u51E6\u7406\u306E\u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u306B\u5F71\u97FF\u3092\u4E0E\u3048\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093 FileSearchPanel.search.exception.noFilterSelected.msg=\u6700\u4f4e\uff11\u500b\u306e\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002
FileSearchPanel.search.exception.noFilterSelected.msg=\u6700\u4F4E\uFF11\u500B\u306E\u30D5\u30A3\u30EB\u30BF\u30FC\u3092\u9078\u629E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 FileSearchPanel.search.validationErr.msg=\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\uff1a{0}
FileSearchPanel.search.validationErr.msg=\u30D0\u30EA\u30C7\u30FC\u30B7\u30E7\u30F3\u30A8\u30E9\u30FC\uFF1A{0} FileSearchPanel.emptyWhereClause.text=\u7121\u52b9\u306a\u30aa\u30d7\u30b7\u30e7\u30f3\u3067\u3059\u3002\u8868\u793a\u3059\u308b\u3082\u306e\u304c\u3042\u308a\u307e\u305b\u3093\u3002
FileSearchPanel.emptyWhereClause.text=\u7121\u52B9\u306A\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3059\u3002\u8868\u793A\u3059\u308B\u3082\u306E\u304C\u3042\u308A\u307E\u305B\u3093\u3002 KnownStatusSearchFilter.noneSelectedMsg.text=\u6700\u4f4e\uff11\u500b\u306e\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\uff01
KnownStatusSearchFilter.noneSelectedMsg.text=\u6700\u4F4E\uFF11\u500B\u306E\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9\u3092\u9078\u629E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF01 NameSearchFilter.emptyNameMsg.text=\u540d\u524d\u691c\u7d22\u306b\u4f55\u304b\u8a18\u5165\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093\u3002
NameSearchFilter.emptyNameMsg.text=\u540D\u524D\u691C\u7D22\u306B\u4F55\u304B\u8A18\u5165\u3057\u306A\u3051\u308C\u3070\u3044\u3051\u307E\u305B\u3093\u3002 SearchNode.getName.text=\u691c\u7d22\u7d50\u679c
SearchNode.getName.text=\u691C\u7D22\u7D50\u679C SizeSearchPanel.sizeCompareComboBox.equalTo=\u4e0b\u8a18\u3068\u7b49\u3057\u3044
SizeSearchPanel.sizeCompareComboBox.equalTo=\u4E0B\u8A18\u3068\u7B49\u3057\u3044 SizeSearchPanel.sizeCompareComboBox.greaterThan=\u4e0b\u8a18\u3088\u308a\u5927\u304d\u3044
SizeSearchPanel.sizeCompareComboBox.greaterThan=\u4E0B\u8A18\u3088\u308A\u5927\u304D\u3044 SizeSearchPanel.sizeCompareComboBox.lessThan=\u4e0b\u8a18\u3088\u308a\u5c0f\u3055\u3044
SizeSearchPanel.sizeCompareComboBox.lessThan=\u4E0B\u8A18\u3088\u308A\u5C0F\u3055\u3044

View File

@ -54,6 +54,8 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Component id="dateCheckBox" min="-2" max="-2" attributes="0"/> <Component id="dateCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
@ -67,74 +69,79 @@
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="dateToButtonCalendar" min="-2" max="-2" attributes="0"/> <Component id="dateToButtonCalendar" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace min="21" pref="21" max="21" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Component id="jLabel3" min="-2" max="-2" attributes="0"/>
<Component id="changedCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="modifiedCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="accessedCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="createdCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace pref="26" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="jLabel4" min="-2" max="-2" attributes="0"/> <Component id="jLabel4" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="timeZoneComboBox" min="-2" pref="193" max="-2" attributes="0"/> <Component id="timeZoneComboBox" min="-2" pref="193" max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="21" pref="21" max="21" attributes="0"/> <Component id="modifiedCheckBox" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="accessedCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> <Component id="createdCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="changedCheckBox" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace min="-2" pref="33" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" max="-2" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="dateCheckBox" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="dateCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dateFromTextField" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="dateFromTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="dateToButtonCalendar" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="dateToButtonCalendar" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="3" attributes="0"> <Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dateToTextField" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="dateToTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Component id="dateFromButtonCalendar" min="-2" max="-2" attributes="0"/> <Component id="dateFromButtonCalendar" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group> </Group>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="timeZoneComboBox" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="timeZoneComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Component id="modifiedCheckBox" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="modifiedCheckBox" min="-2" max="-2" attributes="0"/> <Group type="103" alignment="1" groupAlignment="3" attributes="0">
<EmptySpace max="-2" attributes="0"/> <Component id="accessedCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="changedCheckBox" min="-2" max="-2" attributes="0"/> <Component id="createdCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="changedCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="1" attributes="0">
<Component id="accessedCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="23" pref="23" max="23" attributes="0"/>
</Group> </Group>
<Component id="createdCheckBox" alignment="1" min="-2" max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -188,6 +195,9 @@
</Component> </Component>
<Component class="javax.swing.JLabel" name="jLabel3"> <Component class="javax.swing.JLabel" name="jLabel3">
<Properties> <Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="10" style="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.jLabel3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.jLabel3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
@ -208,6 +218,9 @@
</Component> </Component>
<Component class="javax.swing.JLabel" name="jLabel2"> <Component class="javax.swing.JLabel" name="jLabel2">
<Properties> <Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="10" style="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>

View File

@ -74,7 +74,6 @@ class DateSearchPanel extends javax.swing.JPanel {
copyMenuItem.addActionListener(actList); copyMenuItem.addActionListener(actList);
pasteMenuItem.addActionListener(actList); pasteMenuItem.addActionListener(actList);
selectAllMenuItem.addActionListener(actList); selectAllMenuItem.addActionListener(actList);
} }
JCheckBox getAccessedCheckBox() { JCheckBox getAccessedCheckBox() {
@ -172,6 +171,7 @@ class DateSearchPanel extends javax.swing.JPanel {
dateCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.dateCheckBox.text")); // NOI18N dateCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.dateCheckBox.text")); // NOI18N
jLabel3.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
jLabel3.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.jLabel3.text")); // NOI18N jLabel3.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.jLabel3.text")); // NOI18N
dateFromTextField.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.dateFromTextField.text")); // NOI18N dateFromTextField.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.dateFromTextField.text")); // NOI18N
@ -181,6 +181,7 @@ class DateSearchPanel extends javax.swing.JPanel {
} }
}); });
jLabel2.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
jLabel2.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.jLabel2.text")); // NOI18N jLabel2.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.jLabel2.text")); // NOI18N
modifiedCheckBox.setSelected(true); modifiedCheckBox.setSelected(true);
@ -213,6 +214,8 @@ class DateSearchPanel extends javax.swing.JPanel {
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(dateCheckBox) .addComponent(dateCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -225,58 +228,61 @@ class DateSearchPanel extends javax.swing.JPanel {
.addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(21, 21, 21) .addContainerGap()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel3)))
.addContainerGap(26, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(changedCheckBox)
.addComponent(modifiedCheckBox))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(accessedCheckBox)
.addComponent(createdCheckBox)))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(jLabel4) .addComponent(jLabel4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21) .addComponent(modifiedCheckBox)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(6, 6, 6)
.addComponent(jLabel3) .addComponent(accessedCheckBox)
.addComponent(jLabel2))))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(createdCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(changedCheckBox)))
.addGap(33, 33, 33))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(dateCheckBox) .addComponent(dateCheckBox)
.addComponent(dateFromTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(dateFromTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1) .addComponent(jLabel1)
.addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(dateFromButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(dateFromButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(4, 4, 4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel3)
.addComponent(jLabel2))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel4) .addComponent(jLabel4)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addComponent(modifiedCheckBox, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(modifiedCheckBox) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(changedCheckBox))
.addGroup(layout.createSequentialGroup()
.addComponent(accessedCheckBox) .addComponent(accessedCheckBox)
.addGap(23, 23, 23)) .addComponent(createdCheckBox)
.addComponent(createdCheckBox)) .addComponent(changedCheckBox)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGap(0, 0, 0))
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel3)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents

View File

@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> <Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[300, 300]"/>
</Property>
</Properties>
<AuxValues> <AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@ -16,13 +21,48 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="300" max="32767" attributes="0"/> <Component id="filterPanel" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Component id="searchButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="376" max="32767" attributes="0"/> <Group type="102" alignment="0" attributes="0">
<Component id="filterPanel" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="searchButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="filterPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
<EmptyBorder bottom="10" left="10" right="10" top="10"/>
</Border>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[300, 400]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
<Property name="axis" type="int" value="1"/>
</Layout>
</Container>
<Component class="javax.swing.JButton" name="searchButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="FileSearchPanel.searchButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form> </Form>

View File

@ -60,8 +60,7 @@ import org.sleuthkit.datamodel.TskCoreException;
*/ */
class FileSearchPanel extends javax.swing.JPanel { class FileSearchPanel extends javax.swing.JPanel {
private List<FilterArea> filterAreas = new ArrayList<FilterArea>(); private final List<FilterArea> filterAreas = new ArrayList<>();
private JButton searchButton;
private static int resultWindowCount = 0; //keep track of result windows so they get unique names private static int resultWindowCount = 0; //keep track of result windows so they get unique names
private static final String EMPTY_WHERE_CLAUSE = NbBundle.getMessage(DateSearchFilter.class, "FileSearchPanel.emptyWhereClause.text"); private static final String EMPTY_WHERE_CLAUSE = NbBundle.getMessage(DateSearchFilter.class, "FileSearchPanel.emptyWhereClause.text");
@ -79,14 +78,6 @@ class FileSearchPanel extends javax.swing.JPanel {
*/ */
private void customizeComponents() { private void customizeComponents() {
this.setLayout(new BorderLayout());
JPanel filterPanel = new JPanel();
filterPanel.setLayout(new BoxLayout(filterPanel, BoxLayout.Y_AXIS));
filterPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
this.add(filterPanel, BorderLayout.CENTER);
JLabel label = new JLabel(NbBundle.getMessage(this.getClass(), "FileSearchPanel.custComp.label.text")); JLabel label = new JLabel(NbBundle.getMessage(this.getClass(), "FileSearchPanel.custComp.label.text"));
label.setAlignmentX(Component.LEFT_ALIGNMENT); label.setAlignmentX(Component.LEFT_ALIGNMENT);
label.setBorder(new EmptyBorder(0, 0, 10, 0)); label.setBorder(new EmptyBorder(0, 0, 10, 0));
@ -95,8 +86,9 @@ class FileSearchPanel extends javax.swing.JPanel {
// Create and add filter areas // Create and add filter areas
this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.name"), new NameSearchFilter())); this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.name"), new NameSearchFilter()));
List<FileSearchFilter> metadataFilters = new ArrayList<FileSearchFilter>(); List<FileSearchFilter> metadataFilters = new ArrayList<>();
metadataFilters.add(new SizeSearchFilter()); metadataFilters.add(new SizeSearchFilter());
metadataFilters.add(new MimeTypeFilter());
metadataFilters.add(new DateSearchFilter()); metadataFilters.add(new DateSearchFilter());
this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.metadata"), metadataFilters)); this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.metadata"), metadataFilters));
@ -108,11 +100,6 @@ class FileSearchPanel extends javax.swing.JPanel {
filterPanel.add(fa); filterPanel.add(fa);
} }
// Create and add search button
this.searchButton = new JButton(NbBundle.getMessage(this.getClass(), "FileSearchPanel.searchButton.text"));
this.searchButton.setAlignmentX(Component.LEFT_ALIGNMENT);
filterPanel.add(searchButton);
addListenerToAll(new ActionListener() { addListenerToAll(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@ -234,7 +221,7 @@ class FileSearchPanel extends javax.swing.JPanel {
} }
private Collection<FileSearchFilter> getFilters() { private Collection<FileSearchFilter> getFilters() {
Collection<FileSearchFilter> filters = new ArrayList<FileSearchFilter>(); Collection<FileSearchFilter> filters = new ArrayList<>();
for (FilterArea fa : this.filterAreas) { for (FilterArea fa : this.filterAreas) {
filters.addAll(fa.getFilters()); filters.addAll(fa.getFilters());
@ -244,7 +231,7 @@ class FileSearchPanel extends javax.swing.JPanel {
} }
private Collection<FileSearchFilter> getEnabledFilters() { private Collection<FileSearchFilter> getEnabledFilters() {
Collection<FileSearchFilter> enabledFilters = new ArrayList<FileSearchFilter>(); Collection<FileSearchFilter> enabledFilters = new ArrayList<>();
for (FileSearchFilter f : this.getFilters()) { for (FileSearchFilter f : this.getFilters()) {
if (f.isEnabled()) { if (f.isEnabled()) {
@ -273,17 +260,38 @@ class FileSearchPanel extends javax.swing.JPanel {
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() { private void initComponents() {
filterPanel = new javax.swing.JPanel();
searchButton = new javax.swing.JButton();
setPreferredSize(new java.awt.Dimension(300, 300));
filterPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
filterPanel.setPreferredSize(new java.awt.Dimension(300, 400));
filterPanel.setLayout(new javax.swing.BoxLayout(filterPanel, javax.swing.BoxLayout.Y_AXIS));
searchButton.setText(org.openide.util.NbBundle.getMessage(FileSearchPanel.class, "FileSearchPanel.searchButton.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE) .addComponent(filterPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(searchButton)
.addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 376, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup()
.addComponent(filterPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, 0)
.addComponent(searchButton)
.addContainerGap())
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel filterPanel;
private javax.swing.JButton searchButton;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
} }

View File

@ -92,20 +92,22 @@ class FilterArea extends JPanel {
filtersPanel = new JPanel(); filtersPanel = new JPanel();
filtersPanel.setAlignmentX(Component.LEFT_ALIGNMENT); filtersPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
BoxLayout filtersPanelLayout = new BoxLayout(filtersPanel, BoxLayout.Y_AXIS); BoxLayout filtersPanelLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
filtersPanel.setLayout(filtersPanelLayout); this.setLayout(filtersPanelLayout);
for (FileSearchFilter f : filters) { for (int i = 0; i < filters.size(); i++) {
FileSearchFilter f = filters.get(i);
JComponent filterComponent = f.getComponent(); JComponent filterComponent = f.getComponent();
filterComponent.setAlignmentX(Component.LEFT_ALIGNMENT); filterComponent.setAlignmentX(Component.LEFT_ALIGNMENT);
filterComponent.setBorder(new EmptyBorder(0, 0, 20, 0)); if (i != filters.size() - 1) {
filtersPanel.add(filterComponent); filterComponent.setBorder(new EmptyBorder(0, 0, 15, 0));
} }
else {
this.add(filtersPanel); filterComponent.setBorder(new EmptyBorder(0, 0, 18, 0));
}
BoxLayout layout = new BoxLayout(this, BoxLayout.Y_AXIS); this.add(filterComponent);
this.setLayout(layout); }
this.setAlignmentX(Component.LEFT_ALIGNMENT);
} }
private void refresh() { private void refresh() {

View File

@ -15,16 +15,21 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="knownCheckBox" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="knownCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="21" pref="21" max="21" attributes="0"/> <EmptySpace min="21" pref="21" max="21" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Component id="unknownOptionCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="knownBadOptionCheckBox" alignment="0" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="unknownOptionCheckBox" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="knownOptionCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="knownOptionCheckBox" alignment="0" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="knownBadOptionCheckBox" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace pref="28" max="32767" attributes="0"/>
</Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
@ -32,11 +37,11 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="knownCheckBox" min="-2" max="-2" attributes="0"/> <Component id="knownCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="unknownOptionCheckBox" min="-2" max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0">
<EmptySpace max="-2" attributes="0"/> <Component id="unknownOptionCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="knownOptionCheckBox" min="-2" max="-2" attributes="0"/> <Component id="knownOptionCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <Component id="knownBadOptionCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="knownBadOptionCheckBox" min="-2" max="-2" attributes="0"/> </Group>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>

View File

@ -89,24 +89,27 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(knownCheckBox) .addComponent(knownCheckBox)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21) .addGap(21, 21, 21)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(knownBadOptionCheckBox)
.addComponent(unknownOptionCheckBox) .addComponent(unknownOptionCheckBox)
.addComponent(knownOptionCheckBox))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(knownOptionCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(knownBadOptionCheckBox)))
.addContainerGap(28, Short.MAX_VALUE))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(knownCheckBox) .addComponent(knownCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(unknownOptionCheckBox) .addComponent(unknownOptionCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(knownOptionCheckBox) .addComponent(knownOptionCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(knownBadOptionCheckBox)))
.addComponent(knownBadOptionCheckBox))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents

View File

@ -0,0 +1,44 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener;
/**
* Filter by mime type used in filter areas of file search by attribute.
*/
class MimeTypeFilter extends AbstractFileSearchFilter<MimeTypePanel> {
public MimeTypeFilter(MimeTypePanel component) {
super(component);
}
public MimeTypeFilter() {
this(new MimeTypePanel());
}
@Override
public boolean isEnabled() {
return this.getComponent().isSelected() &&
!this.getComponent().getMimeTypesSelected().isEmpty();
}
@Override
public String getPredicate() throws FilterValidationException {
String predicate = "";
for(String mimeType : this.getComponent().getMimeTypesSelected()) {
predicate += "mime_type = '" + mimeType + "' OR ";
}
if(predicate.length() > 3) {
predicate = predicate.substring(0, predicate.length() - 3);
}
return predicate;
}
@Override
public void addActionListener(ActionListener l) {
}
}

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[150, 150]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 100]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" pref="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel1" min="-2" pref="246" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="106" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JList" name="jList1">
<Properties>
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.AbstractListModel&lt;String&gt;() {&#xa; String[] strings = getMimeTypeArray();&#xa; public int getSize() { return strings.length; }&#xa; public String getElementAt(int i) { return strings[i]; }&#xa;}" type="code"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 200]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JCheckBox" name="jCheckBox1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="MimeTypePanel.jCheckBox1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="10" style="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="MimeTypePanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,138 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.logging.Level;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.apache.tika.mime.MediaType;
import org.apache.tika.mime.MimeTypes;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
*
* @author oliver
*/
public class MimeTypePanel extends javax.swing.JPanel {
private static final SortedSet<MediaType> mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes();
private static final Logger logger = Logger.getLogger(MimeTypePanel.class.getName());
private static final long serialVersionUID = 1L;
/**
* Creates new form MimeTypePanel
*/
public MimeTypePanel() {
initComponents();
}
private String[] getMimeTypeArray() {
Set<String> fileTypesCollated = new HashSet<>();
for (MediaType mediaType : mediaTypes) {
fileTypesCollated.add(mediaType.toString());
}
FileTypeDetector fileTypeDetector;
try {
fileTypeDetector = new FileTypeDetector();
List<String> userDefinedFileTypes = fileTypeDetector.getUserDefinedTypes();
fileTypesCollated.addAll(userDefinedFileTypes);
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
logger.log(Level.SEVERE, "Unable to get user defined file types", ex);
}
List<String> toSort = new ArrayList<>(fileTypesCollated);
toSort.sort((String string1, String string2) -> {
int result = String.CASE_INSENSITIVE_ORDER.compare(string1, string2);
if (result == 0) {
result = string1.compareTo(string2);
}
return result;
});
String[] mimeTypeArray = new String[toSort.size()];
return toSort.toArray(mimeTypeArray);
}
List<String> getMimeTypesSelected() {
return this.jList1.getSelectedValuesList();
}
boolean isSelected() {
return this.jCheckBox1.isSelected();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jList1 = new javax.swing.JList<String>();
jCheckBox1 = new javax.swing.JCheckBox();
jLabel1 = new javax.swing.JLabel();
setMinimumSize(new java.awt.Dimension(150, 150));
setPreferredSize(new java.awt.Dimension(100, 100));
jList1.setModel(new javax.swing.AbstractListModel<String>() {
String[] strings = getMimeTypeArray();
public int getSize() { return strings.length; }
public String getElementAt(int i) { return strings[i]; }
});
jList1.setMinimumSize(new java.awt.Dimension(0, 200));
jScrollPane1.setViewportView(jList1);
org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(MimeTypePanel.class, "MimeTypePanel.jCheckBox1.text")); // NOI18N
jLabel1.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(MimeTypePanel.class, "MimeTypePanel.jLabel1.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jCheckBox1)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 246, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jCheckBox1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 106, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)
.addGap(0, 0, 0))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox jCheckBox1;
private javax.swing.JLabel jLabel1;
private javax.swing.JList<String> jList1;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration//GEN-END:variables
}

View File

@ -55,18 +55,16 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="nameCheckBox" min="-2" max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
<Component id="noteNameLabel" min="-2" pref="296" max="-2" attributes="0"/>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/> <Component id="nameCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="noteNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> <Component id="searchTextField" min="-2" pref="247" max="-2" attributes="0"/>
<Group type="102" attributes="1">
<EmptySpace max="-2" attributes="0"/>
<Component id="searchTextField" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -79,6 +77,7 @@
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="noteNameLabel" min="-2" max="-2" attributes="0"/> <Component id="noteNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -121,6 +120,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="NameSearchPanel.noteNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="NameSearchPanel.noteNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 30]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 30]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 30]"/>
</Property>
</Properties> </Properties>
</Component> </Component>
</SubComponents> </SubComponents>

View File

@ -121,21 +121,23 @@ class NameSearchPanel extends javax.swing.JPanel {
noteNameLabel.setFont(noteNameLabel.getFont().deriveFont(noteNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 10)); noteNameLabel.setFont(noteNameLabel.getFont().deriveFont(noteNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 10));
noteNameLabel.setText(org.openide.util.NbBundle.getMessage(NameSearchPanel.class, "NameSearchPanel.noteNameLabel.text")); // NOI18N noteNameLabel.setText(org.openide.util.NbBundle.getMessage(NameSearchPanel.class, "NameSearchPanel.noteNameLabel.text")); // NOI18N
noteNameLabel.setMaximumSize(new java.awt.Dimension(250, 30));
noteNameLabel.setMinimumSize(new java.awt.Dimension(250, 30));
noteNameLabel.setPreferredSize(new java.awt.Dimension(250, 30));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, 0)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(noteNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 296, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(nameCheckBox) .addComponent(nameCheckBox)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createSequentialGroup()
.addGap(12, 12, 12)
.addComponent(noteNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(searchTextField)))) .addComponent(searchTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 247, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, 0))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -144,7 +146,8 @@ class NameSearchPanel extends javax.swing.JPanel {
.addComponent(nameCheckBox) .addComponent(nameCheckBox)
.addComponent(searchTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(searchTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(noteNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(noteNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -69,9 +69,6 @@ public final class DataSourceIngestModuleProcessTerminator implements ProcessTer
} }
} }
/**
* @inheritDoc
*/
@Override @Override
public boolean shouldTerminateProcess() { public boolean shouldTerminateProcess() {

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014-2015 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -195,17 +195,11 @@ final class DataSourceIngestPipeline {
return this.processingStartTime; return this.processingStartTime;
} }
/**
* @inheritDoc
*/
@Override @Override
public void startUp(IngestJobContext context) throws IngestModuleException { public void startUp(IngestJobContext context) throws IngestModuleException {
this.module.startUp(context); this.module.startUp(context);
} }
/**
* @inheritDoc
*/
@Override @Override
public IngestModule.ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) { public IngestModule.ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) {
this.processingStartTime = new Date(); this.processingStartTime = new Date();

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -68,9 +68,6 @@ public final class FileIngestModuleProcessTerminator implements ProcessTerminato
} }
} }
/**
* @inheritDoc
*/
@Override @Override
public boolean shouldTerminateProcess() { public boolean shouldTerminateProcess() {

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2014 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -168,12 +168,9 @@ public class IngestMessage {
return hash; return hash;
} }
//factory methods
/** /**
* Create a message of specified type * Create a message of specified type
* *
* @param ID ID of the message, unique in the context of module
* that generated it
* @param messageType message type * @param messageType message type
* @param source originating module * @param source originating module
* @param subject message subject to be displayed * @param subject message subject to be displayed
@ -210,8 +207,6 @@ public class IngestMessage {
/** /**
* Create error message * Create error message
* *
* @param ID ID of the message, unique in the context of module
* that generated it
* @param source originating module * @param source originating module
* @param subject message subject to be displayed * @param subject message subject to be displayed
* @param detailsHtml html formatted detailed message (without leading and * @param detailsHtml html formatted detailed message (without leading and

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -58,7 +58,7 @@ public class ModuleDataEvent extends ChangeEvent {
*/ */
public ModuleDataEvent(String moduleName, ARTIFACT_TYPE artifactType) { public ModuleDataEvent(String moduleName, ARTIFACT_TYPE artifactType) {
super(artifactType); super(artifactType);
this.blackboardArtifactType = new BlackboardArtifact.Type(artifactType.getTypeID(), artifactType.getLabel(), artifactType.getDisplayName()); this.blackboardArtifactType = new BlackboardArtifact.Type(artifactType);
this.moduleName = moduleName; this.moduleName = moduleName;
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -45,7 +45,7 @@ public final class ContentChangedEvent extends AutopsyEvent implements Serializa
* Constructs a event to be published when new content is added to a case or * Constructs a event to be published when new content is added to a case or
* there is a change a recorded attribute of existing content. * there is a change a recorded attribute of existing content.
* *
* @param contentEvent A ModuleContentEvent object containing the data * @param eventData A ModuleContentEvent object containing the data
* associated with the content addition or change. * associated with the content addition or change.
*/ */
public ContentChangedEvent(ModuleContentEvent eventData) { public ContentChangedEvent(ModuleContentEvent eventData) {

View File

@ -43,7 +43,6 @@ FileExtMismatchSettingsPanel.mimeRemoveErrLabel.text=\
FileExtMismatchSettingsPanel.extRemoveErrLabel.text=\ FileExtMismatchSettingsPanel.extRemoveErrLabel.text=\
FileExtMismatchSettingsPanel.mimeErrLabel.text=\ FileExtMismatchSettingsPanel.mimeErrLabel.text=\
FileExtMismatchSettingsPanel.removeTypeButton.text=Remove Selected Type FileExtMismatchSettingsPanel.removeTypeButton.text=Remove Selected Type
FileExtMismatchSettingsPanel.saveButton.text=Save Configuration
FileExtMismatchSettingsPanel.jLabel1.text=File Types: FileExtMismatchSettingsPanel.jLabel1.text=File Types:
FileExtMismatchSettingsPanel.userExtTextField.text= FileExtMismatchSettingsPanel.userExtTextField.text=
FileExtMismatchSettingsPanel.addExtButton.text=Add Extension FileExtMismatchSettingsPanel.addExtButton.text=Add Extension

View File

@ -38,7 +38,6 @@ FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text=\u62e1\u5f35\u5b50\u30
FileExtMismatchSettingsPanel.addTypeButton.text=\u30bf\u30a4\u30d7\u3092\u8ffd\u52a0 FileExtMismatchSettingsPanel.addTypeButton.text=\u30bf\u30a4\u30d7\u3092\u8ffd\u52a0
FileExtMismatchSettingsPanel.extHeaderLabel.text=\u8a31\u53ef\u3059\u308b\u62e1\u5f35\u5b50\uff1a FileExtMismatchSettingsPanel.extHeaderLabel.text=\u8a31\u53ef\u3059\u308b\u62e1\u5f35\u5b50\uff1a
FileExtMismatchSettingsPanel.removeTypeButton.text=\u9078\u629e\u3057\u305f\u30bf\u30a4\u30d7\u3092\u524a\u9664 FileExtMismatchSettingsPanel.removeTypeButton.text=\u9078\u629e\u3057\u305f\u30bf\u30a4\u30d7\u3092\u524a\u9664
FileExtMismatchSettingsPanel.saveButton.text=\u8a2d\u5b9a\u3092\u4fdd\u5b58
FileExtMismatchSettingsPanel.jLabel1.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\uff1a FileExtMismatchSettingsPanel.jLabel1.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\uff1a
FileExtMismatchSettingsPanel.addExtButton.text=\u62e1\u5f35\u5b50\u3092\u8ffd\u52a0 FileExtMismatchSettingsPanel.addExtButton.text=\u62e1\u5f35\u5b50\u3092\u8ffd\u52a0
FileExtMismatchSettingsPanel.removeExtButton.text=\u9078\u629e\u3057\u305f\u62e1\u5f35\u5b50\u3092\u524a\u9664 FileExtMismatchSettingsPanel.removeExtButton.text=\u9078\u629e\u3057\u305f\u62e1\u5f35\u5b50\u3092\u524a\u9664

View File

@ -46,13 +46,10 @@
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jSplitPane1" pref="667" max="32767" attributes="0"/> <Component id="jSplitPane1" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Component id="saveMsgLabel" min="-2" pref="145" max="-2" attributes="0"/>
<Component id="saveButton" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="saveMsgLabel" alignment="1" min="-2" pref="145" max="-2" attributes="0"/>
</Group>
</Group> </Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
@ -63,9 +60,7 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jSplitPane1" min="-2" max="-2" attributes="0"/> <Component id="jSplitPane1" min="-2" pref="466" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="saveButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="saveMsgLabel" min="-2" max="-2" attributes="0"/> <Component id="saveMsgLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
@ -74,20 +69,6 @@
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
<SubComponents> <SubComponents>
<Component class="javax.swing.JButton" name="saveButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/modules/fileextmismatch/save16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.saveButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="saveButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JSplitPane" name="jSplitPane1"> <Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Properties> <Properties>
<Property name="dividerLocation" type="int" value="430"/> <Property name="dividerLocation" type="int" value="430"/>
@ -146,7 +127,7 @@
<Component id="removeTypeButton" min="-2" max="-2" attributes="0"/> <Component id="removeTypeButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="mimeRemoveErrLabel" min="-2" max="-2" attributes="0"/> <Component id="mimeRemoveErrLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="47" max="32767" attributes="0"/> <EmptySpace pref="83" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>

View File

@ -143,7 +143,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
jScrollPane1 = new javax.swing.JScrollPane(); jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel(); jPanel1 = new javax.swing.JPanel();
saveButton = new javax.swing.JButton();
jSplitPane1 = new javax.swing.JSplitPane(); jSplitPane1 = new javax.swing.JSplitPane();
mimePanel = new javax.swing.JPanel(); mimePanel = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel(); jLabel1 = new javax.swing.JLabel();
@ -167,15 +166,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
jPanel1.setPreferredSize(new java.awt.Dimension(687, 450)); jPanel1.setPreferredSize(new java.awt.Dimension(687, 450));
saveButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/fileextmismatch/save16.png"))); // NOI18N NON-NLS
saveButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.saveButton.text")); // NOI18N
saveButton.setEnabled(false);
saveButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
saveButtonActionPerformed(evt);
}
});
jSplitPane1.setDividerLocation(430); jSplitPane1.setDividerLocation(430);
jLabel1.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.jLabel1.text")); // NOI18N jLabel1.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.jLabel1.text")); // NOI18N
@ -247,7 +237,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addComponent(removeTypeButton) .addComponent(removeTypeButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(mimeRemoveErrLabel) .addComponent(mimeRemoveErrLabel)
.addContainerGap(47, Short.MAX_VALUE)) .addContainerGap(83, Short.MAX_VALUE))
); );
jSplitPane1.setLeftComponent(mimePanel); jSplitPane1.setLeftComponent(mimePanel);
@ -336,21 +326,17 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 667, Short.MAX_VALUE) .addComponent(jSplitPane1)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE) .addGap(0, 0, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(saveMsgLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addComponent(saveButton, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(saveMsgLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addContainerGap()) .addContainerGap())
); );
jPanel1Layout.setVerticalGroup( jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 466, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(saveButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(saveMsgLabel) .addComponent(saveMsgLabel)
.addContainerGap()) .addContainerGap())
@ -416,10 +402,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
setIsModified(); setIsModified();
}//GEN-LAST:event_addExtButtonActionPerformed }//GEN-LAST:event_addExtButtonActionPerformed
private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
store();
}//GEN-LAST:event_saveButtonActionPerformed
private void addTypeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addTypeButtonActionPerformed private void addTypeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addTypeButtonActionPerformed
String newMime = userTypeTextField.getText(); String newMime = userTypeTextField.getText();
if (newMime.isEmpty()) { if (newMime.isEmpty()) {
@ -555,7 +537,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
extErrorLabel.setText(" "); extErrorLabel.setText(" ");
saveMsgLabel.setText(NbBundle.getMessage(this.getClass(), "FileExtMismatchConfigPanel.store.msg")); saveMsgLabel.setText(NbBundle.getMessage(this.getClass(), "FileExtMismatchConfigPanel.store.msg"));
saveButton.setEnabled(false);
} else { } else {
//error //error
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this,
@ -582,7 +563,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
} }
private void setIsModified() { private void setIsModified() {
saveButton.setEnabled(true);
saveMsgLabel.setText(" "); saveMsgLabel.setText(" ");
} }
@ -592,18 +572,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
} }
public void ok() { public void ok() {
// if data is unsaved
if (saveButton.isEnabled()) {
int choice = JOptionPane.showConfirmDialog(this,
NbBundle.getMessage(this.getClass(),
"FileExtMismatchConfigPanel.ok.confDlg.msg"),
NbBundle.getMessage(this.getClass(),
"FileExtMismatchConfigPanel.confDlg.title"),
JOptionPane.YES_NO_OPTION);
if (choice == JOptionPane.YES_OPTION) {
store(); store();
}
}
clearErrLabels(); clearErrLabels();
load(); // The next time this panel is opened, we want it to be fresh load(); // The next time this panel is opened, we want it to be fresh
} }
@ -631,7 +600,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
private javax.swing.JTable mimeTable; private javax.swing.JTable mimeTable;
private javax.swing.JButton removeExtButton; private javax.swing.JButton removeExtButton;
private javax.swing.JButton removeTypeButton; private javax.swing.JButton removeTypeButton;
private javax.swing.JButton saveButton;
private javax.swing.JLabel saveMsgLabel; private javax.swing.JLabel saveMsgLabel;
private javax.swing.JTextField userExtTextField; private javax.swing.JTextField userExtTextField;
private javax.swing.JTextField userTypeTextField; private javax.swing.JTextField userTypeTextField;

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.modules.filetypeid; package org.sleuthkit.autopsy.modules.filetypeid;
import java.io.Serializable;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
@ -31,8 +32,9 @@ import org.sleuthkit.datamodel.TskCoreException;
* <p> * <p>
* Thread-safe (immutable). * Thread-safe (immutable).
*/ */
class FileType { class FileType implements Serializable {
private static final long serialVersionUID = 1L;
private final String mimeType; private final String mimeType;
private final Signature signature; private final Signature signature;
private final String interestingFilesSetName; private final String interestingFilesSetName;
@ -114,9 +116,10 @@ class FileType {
public boolean equals(Object other) { public boolean equals(Object other) {
if (other != null && other instanceof FileType) { if (other != null && other instanceof FileType) {
FileType that = (FileType) other; FileType that = (FileType) other;
if(this.getMimeType().equals(that.getMimeType()) && this.getSignature().equals(that.getSignature())) if (this.getMimeType().equals(that.getMimeType()) && this.getSignature().equals(that.getSignature())) {
return true; return true;
} }
}
return false; return false;
} }
@ -134,14 +137,16 @@ class FileType {
* <p> * <p>
* Thread-safe (immutable). * Thread-safe (immutable).
*/ */
static class Signature { static class Signature implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(Signature.class.getName()); private static final Logger logger = Logger.getLogger(Signature.class.getName());
/** /**
* The way the signature byte sequence should be interpreted. * The way the signature byte sequence should be interpreted.
*/ */
enum Type { enum Type {
RAW, ASCII RAW, ASCII
}; };
@ -156,8 +161,8 @@ class FileType {
* *
* @param signatureBytes The signature bytes. * @param signatureBytes The signature bytes.
* @param offset The offset of the signature bytes. * @param offset The offset of the signature bytes.
* @param type The type of data in the byte array. Impacts * @param type The type of data in the byte array. Impacts how
* how it is displayed to the user in the UI. * it is displayed to the user in the UI.
*/ */
Signature(final byte[] signatureBytes, long offset, Type type) { Signature(final byte[] signatureBytes, long offset, Type type) {
this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
@ -167,8 +172,8 @@ class FileType {
} }
/** /**
* Creates a file signature consisting of an ASCII string at a * Creates a file signature consisting of an ASCII string at a specific
* specific offset within a file. * offset within a file.
* *
* @param signatureString The ASCII string * @param signatureString The ASCII string
* @param offset The offset of the signature bytes. * @param offset The offset of the signature bytes.
@ -204,7 +209,8 @@ class FileType {
* @param offset The offset of the signature bytes. * @param offset The offset of the signature bytes.
* @param type The type of data in the byte array. Impacts * @param type The type of data in the byte array. Impacts
* how it is displayed to the user in the UI. * how it is displayed to the user in the UI.
* @param isRelativeToStart Determines whether this signature is relative to start. * @param isRelativeToStart Determines whether this signature is
* relative to start.
*/ */
Signature(final byte[] signatureBytes, long offset, Type type, boolean isRelativeToStart) { Signature(final byte[] signatureBytes, long offset, Type type, boolean isRelativeToStart) {
this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
@ -214,12 +220,13 @@ class FileType {
} }
/** /**
* Creates a file signature consisting of an ASCII string at a * Creates a file signature consisting of an ASCII string at a specific
* specific offset within a file. * offset within a file.
* *
* @param signatureString The ASCII string * @param signatureString The ASCII string
* @param offset The offset of the signature bytes. * @param offset The offset of the signature bytes.
* @param isRelativeToStart Determines whether this signature is relative to start. * @param isRelativeToStart Determines whether this signature is
* relative to start.
*/ */
Signature(String signatureString, long offset, boolean isRelativeToStart) { Signature(String signatureString, long offset, boolean isRelativeToStart) {
this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII); this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII);
@ -236,7 +243,8 @@ class FileType {
* *
* @param signatureBytes The signature bytes. * @param signatureBytes The signature bytes.
* @param offset The offset of the signature bytes. * @param offset The offset of the signature bytes.
* @param isRelativeToStart Determines whether this signature is relative to start. * @param isRelativeToStart Determines whether this signature is
* relative to start.
*/ */
Signature(final byte[] signatureBytes, long offset, boolean isRelativeToStart) { Signature(final byte[] signatureBytes, long offset, boolean isRelativeToStart) {
this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
@ -289,8 +297,9 @@ class FileType {
return false; // File is too small, offset lies outside file. return false; // File is too small, offset lies outside file.
} }
long actualOffset = offset; long actualOffset = offset;
if(!isRelativeToStart) if (!isRelativeToStart) {
actualOffset = file.getSize() - 1 - offset; actualOffset = file.getSize() - 1 - offset;
}
if (file.getSize() < (actualOffset + signatureBytes.length)) { if (file.getSize() < (actualOffset + signatureBytes.length)) {
return false; /// too small, can't contain this signature return false; /// too small, can't contain this signature
} }
@ -315,9 +324,10 @@ class FileType {
Signature that = (Signature) other; Signature that = (Signature) other;
if (Arrays.equals(this.getSignatureBytes(), that.getSignatureBytes()) if (Arrays.equals(this.getSignatureBytes(), that.getSignatureBytes())
&& this.getOffset() == that.getOffset() && this.getOffset() == that.getOffset()
&& this.getType().equals(that.getType())) && this.getType().equals(that.getType())) {
return true; return true;
} }
}
return false; return false;
} }

View File

@ -133,48 +133,20 @@ public class FileTypeDetector {
* Gets the MIME type of a file, detecting it if it is not already known. If * Gets the MIME type of a file, detecting it if it is not already known. If
* detection is necessary, the result is added to the case database. * detection is necessary, the result is added to the case database.
* *
* IMPORTANT: This method should not be called except by ingest modules; all * IMPORTANT: This method should only be called by ingest modules. All
* other clients should call AbstractFile.getMIMEType, and may call * other clients should call AbstractFile.getMIMEType, and may call
* FileTypeDetector.detect, if AbstractFile.getMIMEType returns null. * FileTypeDetector.detect, if AbstractFile.getMIMEType returns null.
* *
* @param file The file. * @param file The file.
* *
* @return A MIME type name. * @return A MIME type name. If file type could not be detected or results
* were uncertain, octet-stream is returned.
* *
* @throws TskCoreException if detection is required and there is a problem * @throws TskCoreException if detection is required and there is a problem
* writing the result to the case database. * writing the result to the case database.
*/ */
@SuppressWarnings("deprecation")
public String getFileType(AbstractFile file) throws TskCoreException { public String getFileType(AbstractFile file) throws TskCoreException {
String mimeType = file.getMIMEType(); return detect(file, true);
if (null != mimeType) {
return mimeType;
}
mimeType = detect(file);
Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType);
/*
* Add the file type attribute to the general info artifact. Note that
* no property change is fired for this blackboard posting because
* general info artifacts are different from other artifacts, e.g., they
* are not displayed in the results tree.
*
* SPECIAL NOTE: Adding a file type attribute to the general info
* artifact is meant to be replaced by the use of the MIME type field of
* the AbstractFile class (tsk_files.mime_type in the case database).
* The attribute is still added here to support backward compatibility,
* but it introduces a check-then-act race condition that can lead to
* duplicate attributes. Various mitigation strategies were considered.
* It was decided to go with the policy that this method would not be
* called outside of ingest (see note in method docs), at least until
* such time as the attribute is no longer created.
*/
BlackboardArtifact getInfoArt = file.getGenInfoArtifact();
BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType);
getInfoArt.addAttribute(batt);
return mimeType;
} }
/** /**
@ -186,9 +158,39 @@ public class FileTypeDetector {
* @return A MIME type name. If file type could not be detected or results * @return A MIME type name. If file type could not be detected or results
* were uncertain, octet-stream is returned. * were uncertain, octet-stream is returned.
* *
* @throws TskCoreException * @throws TskCoreException If there is a problem writing the result to the
* case database.
*/ */
public String detect(AbstractFile file) throws TskCoreException { public String detect(AbstractFile file) throws TskCoreException {
return detect(file, false);
}
/**
* Detects the MIME type of a file. The result is saved to the case database
* only if the add to case dastabase flag is set.
*
* @param file The file to test.
* @param addToCaseDb Whether the MIME type should be added to the case
* database. This flag is part of a partial workaround
* for a check-then-act-race condition (see notes in
* comments for details).
*
* @return A MIME type name. If file type could not be detected or results
* were uncertain, octet-stream is returned.
*
* @throws TskCoreException If there is a problem writing the result to the
* case database.
*/
private String detect(AbstractFile file, boolean addToCaseDb) throws TskCoreException {
/*
* Check to see if the file has already been typed. This is the "check"
* part of a check-then-act race condition (see note below).
*/
String mimeType = file.getMIMEType();
if (null != mimeType) {
return mimeType;
}
/* /*
* Mark non-regular files (refer to TskData.TSK_FS_META_TYPE_ENUM), * Mark non-regular files (refer to TskData.TSK_FS_META_TYPE_ENUM),
* zero-sized files, unallocated space, and unused blocks (refer to * zero-sized files, unallocated space, and unused blocks (refer to
@ -198,18 +200,21 @@ public class FileTypeDetector {
|| (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
|| (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)
|| (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) { || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) {
return MimeTypes.OCTET_STREAM; mimeType = MimeTypes.OCTET_STREAM;
} }
/* /*
* Give precedence to user-defined types. * If the file is a regular file, give precedence to user-defined types.
*/ */
String mimeType = detectUserDefinedType(file);
if (null == mimeType) { if (null == mimeType) {
mimeType = detectUserDefinedType(file, addToCaseDb);
}
/* /*
* The file does not match a user-defined type. Send the initial * If the file does not match a user-defined type, send the initial
* bytes to Tika. * bytes to Tika.
*/ */
if (null == mimeType) {
try { try {
byte buf[]; byte buf[];
int len = file.read(buffer, 0, BUFFER_SIZE); int len = file.read(buffer, 0, BUFFER_SIZE);
@ -237,25 +242,63 @@ public class FileTypeDetector {
mimeType = MimeTypes.OCTET_STREAM; mimeType = MimeTypes.OCTET_STREAM;
} }
} }
/*
* If adding the result to the case database, do so now.
*
* NOTE: This condtional is a way to deal with the check-then-act race
* condition created by the gap between querying the MIME type and
* recording it. It is not really a problem for the mime_type column of
* the tsk_files table, but it can lead to duplicate blackboard posts,
* and the posts are required to maintain backward compatibility.
* Various mitigation strategies were considered. It was decided to go
* with the policy that only ingest modules are allowed to add file
* types to the case database, at least until such time as file types
* are no longer posted to the blackboard. Of course, this is not a
* perfect solution. It's not really enforceable for community
* contributed plug ins and it does not handle the unlikely but possible
* scenario of multiple processes typing the same file for a multi-user
* case.
*/
if (addToCaseDb) {
/*
* Add the MIME type to the files table in the case database.
*/
Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType);
/*
* Post to the blackboard, adding the file type attribute to the
* general info artifact. A property change is not fired for this
* posting because general info artifacts are different from other
* artifacts, e.g., they are not displayed in the results tree.
*/
BlackboardArtifact getInfoArt = file.getGenInfoArtifact();
@SuppressWarnings("deprecation")
BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType);
getInfoArt.addAttribute(batt);
}
return mimeType; return mimeType;
} }
/** /**
* Determines whether or not the a file matches a user-defined or Autopsy * Determines whether or not the a file matches a user-defined or Autopsy
* predefined file type. If a match is found and the file type definition * predefined file type. If postToBlackBoard is true, and a match is found,
* calls for an alert on a match, an interesting file hit artifact is posted * and the file type definition calls for an alert on a match, an
* to the blackboard. * interesting file hit artifact is posted to the blackboard.
* *
* @param file The file to test. * @param file The file to test.
* @param postToBlackBoard Whether an interesting file hit could be posted
* to the blackboard.
* *
* @return The file type name string or null, if no match is detected. * @return The file type name string or null, if no match is detected.
* *
* @throws TskCoreException * @throws TskCoreException
*/ */
private String detectUserDefinedType(AbstractFile file) throws TskCoreException { private String detectUserDefinedType(AbstractFile file, boolean postToBlackBoard) throws TskCoreException {
for (FileType fileType : userDefinedFileTypes) { for (FileType fileType : userDefinedFileTypes) {
if (fileType.matches(file)) { if (fileType.matches(file)) {
if (fileType.alertOnMatch()) { if (postToBlackBoard && fileType.alertOnMatch()) {
/* /*
* Create an interesting file hit artifact. * Create an interesting file hit artifact.
*/ */

View File

@ -19,7 +19,9 @@
package org.sleuthkit.autopsy.modules.filetypeid; package org.sleuthkit.autopsy.modules.filetypeid;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.file.Path; import java.nio.file.Path;
@ -27,6 +29,7 @@ import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import javax.persistence.PersistenceException;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@ -34,10 +37,13 @@ import org.w3c.dom.NodeList;
import javax.xml.bind.DatatypeConverter; import javax.xml.bind.DatatypeConverter;
import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerException;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.io.NbObjectInputStream;
import org.openide.util.io.NbObjectOutputStream;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature; import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature;
import org.sleuthkit.datamodel.TskCoreException;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -59,7 +65,8 @@ import org.xml.sax.SAXException;
final class UserDefinedFileTypesManager { final class UserDefinedFileTypesManager {
private static final Logger logger = Logger.getLogger(UserDefinedFileTypesManager.class.getName()); private static final Logger logger = Logger.getLogger(UserDefinedFileTypesManager.class.getName());
private static final String USER_DEFINED_TYPE_DEFINITIONS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS private static final String USER_DEFINED_TYPES_XML_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS
private static final String USER_DEFINED_TYPES_SERIALIZATION_FILE = "UserFileTypeDefinitions.settings";
private static final String FILE_TYPES_TAG_NAME = "FileTypes"; //NON-NLS private static final String FILE_TYPES_TAG_NAME = "FileTypes"; //NON-NLS
private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS
private static final String MIME_TYPE_TAG_NAME = "MimeType"; //NON-NLS private static final String MIME_TYPE_TAG_NAME = "MimeType"; //NON-NLS
@ -246,12 +253,19 @@ final class UserDefinedFileTypesManager {
*/ */
private void loadUserDefinedFileTypes() throws UserDefinedFileTypesException { private void loadUserDefinedFileTypes() throws UserDefinedFileTypesException {
try { try {
String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE); File serialized = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE));
File file = new File(filePath); if (serialized.exists()) {
if (file.exists() && file.canRead()) { for (FileType fileType : readFileTypesSerialized()) {
for (FileType fileType : XmlReader.readFileTypes(filePath)) {
addUserDefinedFileType(fileType); addUserDefinedFileType(fileType);
} }
} else {
String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_XML_FILE);
File xmlFile = new File(filePath);
if (xmlFile.exists()) {
for (FileType fileType : XMLDefinitionsReader.readFileTypes(filePath)) {
addUserDefinedFileType(fileType);
}
}
} }
} catch (IOException | ParserConfigurationException | SAXException ex) { } catch (IOException | ParserConfigurationException | SAXException ex) {
@ -282,14 +296,8 @@ final class UserDefinedFileTypesManager {
* types. * types.
*/ */
synchronized void setUserDefinedFileTypes(List<FileType> newFileTypes) throws UserDefinedFileTypesException { synchronized void setUserDefinedFileTypes(List<FileType> newFileTypes) throws UserDefinedFileTypesException {
try { String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE);
String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE); writeFileTypes(newFileTypes, filePath);
XmlWriter.writeFileTypes(newFileTypes, filePath);
} catch (ParserConfigurationException | FileNotFoundException | UnsupportedEncodingException | TransformerException ex) {
throwUserDefinedFileTypesException(ex, "UserDefinedFileTypesManager.saveFileTypes.errorMessage");
} catch (IOException ex) {
throwUserDefinedFileTypesException(ex, "UserDefinedFileTypesManager.saveFileTypes.errorMessage");
}
} }
/** /**
@ -305,13 +313,7 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Provides a mechanism for writing a set of file type definitions to an XML * Writes a set of file types to a file.
* file.
*/
private static class XmlWriter {
/**
* Writes a set of file type definitions to an XML file.
* *
* @param fileTypes A collection of file types. * @param fileTypes A collection of file types.
* @param filePath The path to the destination file. * @param filePath The path to the destination file.
@ -322,110 +324,41 @@ final class UserDefinedFileTypesManager {
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
* @throws TransformerException * @throws TransformerException
*/ */
private static void writeFileTypes(List<FileType> fileTypes, String filePath) throws ParserConfigurationException, IOException, FileNotFoundException, UnsupportedEncodingException, TransformerException { private static void writeFileTypes(List<FileType> fileTypes, String filePath) throws UserDefinedFileTypesException {
Document doc = XMLUtil.createDocument(); try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) {
Element fileTypesElem = doc.createElement(FILE_TYPES_TAG_NAME); UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes);
doc.appendChild(fileTypesElem); out.writeObject(settings);
for (FileType fileType : fileTypes) { } catch (IOException ex) {
Element fileTypeElem = XmlWriter.createFileTypeElement(fileType, doc); throw new UserDefinedFileTypesException(String.format("Failed to write settings to %s", filePath), ex);
fileTypesElem.appendChild(fileTypeElem);
}
XMLUtil.saveDocument(doc, ENCODING_FOR_XML_FILE, filePath);
}
/**
* Creates an XML representation of a file type.
*
* @param fileType The file type object.
* @param doc The WC3 DOM object to use to create the XML.
*
* @return An XML element.
*/
private static Element createFileTypeElement(FileType fileType, Document doc) {
Element fileTypeElem = doc.createElement(FILE_TYPE_TAG_NAME);
XmlWriter.addMimeTypeElement(fileType, fileTypeElem, doc);
XmlWriter.addSignatureElement(fileType, fileTypeElem, doc);
XmlWriter.addInterestingFilesSetElement(fileType, fileTypeElem, doc);
XmlWriter.addAlertAttribute(fileType, fileTypeElem);
return fileTypeElem;
}
/**
* Add a MIME type child element to a file type XML element.
*
* @param fileType The file type to use as a content source.
* @param fileTypeElem The parent file type element.
* @param doc The WC3 DOM object to use to create the XML.
*/
private static void addMimeTypeElement(FileType fileType, Element fileTypeElem, Document doc) {
Element typeNameElem = doc.createElement(MIME_TYPE_TAG_NAME);
typeNameElem.setTextContent(fileType.getMimeType());
fileTypeElem.appendChild(typeNameElem);
}
/**
* Add a signature child element to a file type XML element.
*
* @param fileType The file type to use as a content source.
* @param fileTypeElem The parent file type element.
* @param doc The WC3 DOM object to use to create the XML.
*/
private static void addSignatureElement(FileType fileType, Element fileTypeElem, Document doc) {
Signature signature = fileType.getSignature();
Element signatureElem = doc.createElement(SIGNATURE_TAG_NAME);
Element bytesElem = doc.createElement(BYTES_TAG_NAME);
bytesElem.setTextContent(DatatypeConverter.printHexBinary(signature.getSignatureBytes()));
signatureElem.appendChild(bytesElem);
Element offsetElem = doc.createElement(OFFSET_TAG_NAME);
offsetElem.setTextContent(DatatypeConverter.printLong(signature.getOffset()));
offsetElem.setAttribute(RELATIVE_ATTRIBUTE, String.valueOf(signature.isRelativeToStart()));
signatureElem.appendChild(offsetElem);
signatureElem.setAttribute(SIGNATURE_TYPE_ATTRIBUTE, signature.getType().toString());
fileTypeElem.appendChild(signatureElem);
}
/**
* Add an interesting files set element to a file type XML element.
*
* @param fileType The file type to use as a content source.
* @param fileTypeElem The parent file type element.
* @param doc The WC3 DOM object to use to create the XML.
*/
private static void addInterestingFilesSetElement(FileType fileType, Element fileTypeElem, Document doc) {
if (!fileType.getFilesSetName().isEmpty()) {
Element filesSetElem = doc.createElement(INTERESTING_FILES_SET_TAG_NAME);
filesSetElem.setTextContent(fileType.getFilesSetName());
fileTypeElem.appendChild(filesSetElem);
} }
} }
/** /**
* Add an alert attribute to a file type XML element. * Reads the file types
* *
* @param fileType The file type to use as a content source. * @param filePath the file path where the file types are to be read
* @param fileTypeElem The parent file type element. *
* @return the file types
*
* @throws ParserConfigurationException If the file cannot be read
*/ */
private static void addAlertAttribute(FileType fileType, Element fileTypeElem) { private static List<FileType> readFileTypesSerialized() throws UserDefinedFileTypesException {
fileTypeElem.setAttribute(ALERT_ATTRIBUTE, Boolean.toString(fileType.alertOnMatch())); File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE));
try {
try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) {
UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject();
return filesSetsSettings.getUserDefinedFileTypes();
} }
} catch (IOException | ClassNotFoundException ex) {
/** throw new UserDefinedFileTypesException("Couldn't read serialized settings.", ex);
* Private constructor suppresses creation of instanmces of this utility
* class.
*/
private XmlWriter() {
} }
} }
/** /**
* Provides a mechanism for reading a set of file type definitions from an * Provides a mechanism for reading a set of file type definitions from an
* XML file. * XML file.
*/ */
private static class XmlReader { private static class XMLDefinitionsReader {
/** /**
* Reads a set of file type definitions from an XML file. * Reads a set of file type definitions from an XML file.
@ -434,7 +367,7 @@ final class UserDefinedFileTypesManager {
* *
* @return A collection of file types read from the XML file. * @return A collection of file types read from the XML file.
*/ */
private static List<FileType> readFileTypes(String filePath) throws IOException, ParserConfigurationException, SAXException { private static List<FileType> readFileTypes(String filePath) throws IOException, SAXException, ParserConfigurationException {
List<FileType> fileTypes = new ArrayList<>(); List<FileType> fileTypes = new ArrayList<>();
/* /*
* RC: Commenting out the loadDocument overload that validates * RC: Commenting out the loadDocument overload that validates
@ -453,7 +386,7 @@ final class UserDefinedFileTypesManager {
NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME); NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME);
for (int i = 0; i < fileTypeElems.getLength(); ++i) { for (int i = 0; i < fileTypeElems.getLength(); ++i) {
Element fileTypeElem = (Element) fileTypeElems.item(i); Element fileTypeElem = (Element) fileTypeElems.item(i);
FileType fileType = XmlReader.parseFileType(fileTypeElem); FileType fileType = XMLDefinitionsReader.parseFileType(fileTypeElem);
fileTypes.add(fileType); fileTypes.add(fileType);
} }
} }
@ -472,10 +405,10 @@ final class UserDefinedFileTypesManager {
* @throws NumberFormatException * @throws NumberFormatException
*/ */
private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException { private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException {
String mimeType = XmlReader.parseMimeType(fileTypeElem); String mimeType = XMLDefinitionsReader.parseMimeType(fileTypeElem);
Signature signature = XmlReader.parseSignature(fileTypeElem); Signature signature = XMLDefinitionsReader.parseSignature(fileTypeElem);
String filesSetName = XmlReader.parseInterestingFilesSet(fileTypeElem); String filesSetName = XMLDefinitionsReader.parseInterestingFilesSet(fileTypeElem);
boolean alert = XmlReader.parseAlert(fileTypeElem); boolean alert = XMLDefinitionsReader.parseAlert(fileTypeElem);
return new FileType(mimeType, signature, filesSetName, alert); return new FileType(mimeType, signature, filesSetName, alert);
} }
@ -573,7 +506,7 @@ final class UserDefinedFileTypesManager {
* Private constructor suppresses creation of instanmces of this utility * Private constructor suppresses creation of instanmces of this utility
* class. * class.
*/ */
private XmlReader() { private XMLDefinitionsReader() {
} }
} }

View File

@ -0,0 +1,45 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.modules.filetypeid;
import java.io.Serializable;
import java.util.List;
/**
* Settings object for user defined file types
*/
class UserDefinedFileTypesSettings implements Serializable {
private static final long serialVersionUID = 1L;
private List<FileType> userDefinedFileTypes;
UserDefinedFileTypesSettings(List<FileType> userDefinedFileTypes) {
this.userDefinedFileTypes = userDefinedFileTypes;
}
/**
* Gets the list of file types contained within the settings
*
* @return the userDefinedFileTypes
*/
public List<FileType> getUserDefinedFileTypes() {
return userDefinedFileTypes;
}
}

View File

@ -14,8 +14,8 @@ ArtifactSelectionDialog.selectAllButton.text=Select All
ReportGenerationPanel.closeButton.text=Close ReportGenerationPanel.closeButton.text=Close
ReportProgressPanel.reportLabel.text=reportLabel ReportProgressPanel.reportLabel.text=reportLabel
ReportProgressPanel.pathLabel.text=pathLabel ReportProgressPanel.pathLabel.text=pathLabel
ReportProgressPanel.separationLabel.text=- ReportProgressPanel.separationLabel.text=:
ReportProgressPanel.processingLabel.text=processingLabel ReportProgressPanel.statusMessageLabel.text=processingLabel
ReportGenerationPanel.titleLabel.text=Report Generation Progress ReportGenerationPanel.titleLabel.text=Report Generation Progress
ReportVisualPanel2.taggedResultsRadioButton.text=Tagged Results ReportVisualPanel2.taggedResultsRadioButton.text=Tagged Results
ReportVisualPanel2.allResultsRadioButton.text=All Results ReportVisualPanel2.allResultsRadioButton.text=All Results

View File

@ -1,247 +1,246 @@
OpenIDE-Module-Name=\u30EC\u30DD\u30FC\u30C8 OpenIDE-Module-Name=\u30ec\u30dd\u30fc\u30c8
CTL_ReportWizardAction=\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C CTL_ReportWizardAction=\u30ec\u30dd\u30fc\u30c8\u3092\u5b9f\u884c
ArtifactSelectionDialog.titleLabel.text=\u3069\u306E\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u306B\u3064\u3044\u3066\u30EC\u30DD\u30FC\u30C8\u3059\u308B\u304B\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\uFF1A ArtifactSelectionDialog.titleLabel.text=\u3069\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306b\u3064\u3044\u3066\u30ec\u30dd\u30fc\u30c8\u3059\u308b\u304b\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\uff1a
ArtifactSelectionDialog.okButton.text=OK ArtifactSelectionDialog.okButton.text=OK
ReportVisualPanel1.reportModulesLabel.text=\u30EC\u30DD\u30FC\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\uFF1A ReportVisualPanel1.reportModulesLabel.text=\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\uff1a
DefaultReportConfigurationPanel.infoLabel.text=\u3053\u306E\u30EC\u30DD\u30FC\u30C8\u306F\u6B21\u306E\u30B9\u30AF\u30EA\u30FC\u30F3\u3067\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002 DefaultReportConfigurationPanel.infoLabel.text=\u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u6b21\u306e\u30b9\u30af\u30ea\u30fc\u30f3\u3067\u8a2d\u5b9a\u3055\u308c\u307e\u3059\u3002
ReportVisualPanel2.dataLabel.text=\u3069\u306E\u30C7\u30FC\u30BF\u306B\u3064\u3044\u3066\u30EC\u30DD\u30FC\u30C8\u3059\u308B\u304B\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\uFF1A ReportVisualPanel2.dataLabel.text=\u3069\u306e\u30c7\u30fc\u30bf\u306b\u3064\u3044\u3066\u30ec\u30dd\u30fc\u30c8\u3059\u308b\u304b\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\uff1a
ReportVisualPanel2.deselectAllButton.text=\u5168\u3066\u9078\u629E\u89E3\u9664 ReportVisualPanel2.deselectAllButton.text=\u5168\u3066\u9078\u629e\u89e3\u9664
ReportVisualPanel2.selectAllButton.text=\u5168\u3066\u9078\u629E ReportVisualPanel2.selectAllButton.text=\u5168\u3066\u9078\u629e
ReportVisualPanel2.advancedButton.text=\u30C7\u30FC\u30BF\u30BF\u30A4\u30D7 ReportVisualPanel2.advancedButton.text=\u30c7\u30fc\u30bf\u30bf\u30a4\u30d7
ArtifactSelectionDialog.deselectAllButton.text=\u5168\u3066\u9078\u629E\u89E3\u9664 ArtifactSelectionDialog.deselectAllButton.text=\u5168\u3066\u9078\u629e\u89e3\u9664
ArtifactSelectionDialog.selectAllButton.text=\u5168\u3066\u9078\u629E ArtifactSelectionDialog.selectAllButton.text=\u5168\u3066\u9078\u629e
ReportGenerationPanel.closeButton.text=\u9589\u3058\u308B ReportGenerationPanel.closeButton.text=\u9589\u3058\u308b
ReportProgressPanel.reportLabel.text=\u30EC\u30DD\u30FC\u30C8\u30E9\u30D9\u30EB ReportProgressPanel.reportLabel.text=\u30ec\u30dd\u30fc\u30c8\u30e9\u30d9\u30eb
ReportProgressPanel.pathLabel.text=\u30D1\u30B9\u30E9\u30D9\u30EB ReportProgressPanel.pathLabel.text=\u30d1\u30b9\u30e9\u30d9\u30eb
ReportProgressPanel.separationLabel.text=- ReportProgressPanel.separationLabel.text=:
ReportProgressPanel.processingLabel.text=\u30D7\u30ED\u30BB\u30B7\u30F3\u30B0\u30E9\u30D9\u30EB ReportProgressPanel.statusMessageLabel.text=\u30d7\u30ed\u30bb\u30b7\u30f3\u30b0\u30e9\u30d9\u30eb
ReportGenerationPanel.titleLabel.text=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u30D7\u30ED\u30B0\u30EC\u30B9 ReportGenerationPanel.titleLabel.text=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u30d7\u30ed\u30b0\u30ec\u30b9
ReportVisualPanel2.taggedResultsRadioButton.text=\u30BF\u30B0\u3055\u308C\u305F\u7D50\u679C ReportVisualPanel2.taggedResultsRadioButton.text=\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c
ReportVisualPanel2.allResultsRadioButton.text=\u5168\u3066\u306E\u7D50\u679C ReportVisualPanel2.allResultsRadioButton.text=\u5168\u3066\u306e\u7d50\u679c
ReportWizardFileOptionsVisualPanel.selectAllButton.text=\u5168\u3066\u9078\u629E ReportWizardFileOptionsVisualPanel.selectAllButton.text=\u5168\u3066\u9078\u629e
ReportWizardFileOptionsVisualPanel.deselectAllButton.text=\u5168\u3066\u9078\u629E\u89E3\u9664 ReportWizardFileOptionsVisualPanel.deselectAllButton.text=\u5168\u3066\u9078\u629e\u89e3\u9664
ReportWizardFileOptionsVisualPanel.jLabel1.text=\u30D5\u30A1\u30A4\u30EB\u30EC\u30DD\u30FC\u30C8\u306B\u542B\u3081\u308B\u30A2\u30A4\u30C6\u30E0\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\uFF1A ReportWizardFileOptionsVisualPanel.jLabel1.text=\u30d5\u30a1\u30a4\u30eb\u30ec\u30dd\u30fc\u30c8\u306b\u542b\u3081\u308b\u30a2\u30a4\u30c6\u30e0\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\uff1a
ArtifactSelectionDialog.dlgTitle.text=\u30A2\u30C9\u30D0\u30F3\u30B9\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u9078\u629E ArtifactSelectionDialog.dlgTitle.text=\u30a2\u30c9\u30d0\u30f3\u30b9\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u9078\u629e
FileReportDataTypes.filename.text=\u540D\u524D FileReportDataTypes.filename.text=\u540d\u524d
FileReportDataTypes.fileExt.text=\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u5B50 FileReportDataTypes.fileExt.text=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50
FileReportDataTypes.fileType.text=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7 FileReportDataTypes.fileType.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7
FileReportDataTypes.isDel.text=\u306F\u524A\u9664\u3055\u308C\u307E\u3057\u305F FileReportDataTypes.isDel.text=\u306f\u524a\u9664\u3055\u308c\u307e\u3057\u305f
FileReportDataTypes.aTime.text=\u6700\u5F8C\u306E\u30A2\u30AF\u30BB\u30B9 FileReportDataTypes.aTime.text=\u6700\u5f8c\u306e\u30a2\u30af\u30bb\u30b9
FileReportDataTypes.crTime.text=\u4F5C\u6210\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB FileReportDataTypes.crTime.text=\u4f5c\u6210\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb
FileReportDataTypes.mTime.text=\u6700\u5F8C\u306E\u4FEE\u6B63 FileReportDataTypes.mTime.text=\u6700\u5f8c\u306e\u4fee\u6b63
FileReportDataTypes.size.text=\u30B5\u30A4\u30BA FileReportDataTypes.size.text=\u30b5\u30a4\u30ba
FileReportDataTypes.address.text=\u30A2\u30C9\u30EC\u30B9 FileReportDataTypes.address.text=\u30a2\u30c9\u30ec\u30b9
FileReportDataTypes.hash.text=\u30CF\u30C3\u30B7\u30E5\u5024 FileReportDataTypes.hash.text=\u30cf\u30c3\u30b7\u30e5\u5024
FileReportDataTypes.knownStatus.text=\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9 FileReportDataTypes.knownStatus.text=\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9
FileReportDataTypes.perms.text=\u30D1\u30FC\u30DF\u30C3\u30B7\u30E7\u30F3 FileReportDataTypes.perms.text=\u30d1\u30fc\u30df\u30c3\u30b7\u30e7\u30f3
FileReportDataTypes.path.text=\u30D5\u30EB\u30D1\u30B9 FileReportDataTypes.path.text=\u30d5\u30eb\u30d1\u30b9
FileReportText.getName.text=\u30D5\u30A1\u30A4\u30EB - \u30C6\u30AD\u30B9\u30C8 FileReportText.getName.text=\u30d5\u30a1\u30a4\u30eb - \u30c6\u30ad\u30b9\u30c8
FileReportText.getDesc.text=\u30B1\u30FC\u30B9\u306E\u500B\u5225\u30D5\u30A1\u30A4\u30EB\u306B\u3064\u3044\u3066\u306E\u60C5\u5831\u3092\u6301\u3064\u3001\u30BF\u30D6\u533A\u5207\u308A\u30C6\u30AD\u30B9\u30C8\u30D5\u30A1\u30A4\u30EB\u3002 FileReportText.getDesc.text=\u30b1\u30fc\u30b9\u306e\u500b\u5225\u30d5\u30a1\u30a4\u30eb\u306b\u3064\u3044\u3066\u306e\u60c5\u5831\u3092\u6301\u3064\u3001\u30bf\u30d6\u533a\u5207\u308a\u30c6\u30ad\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u3002
ReportBodyFile.progress.querying=\u30D5\u30A1\u30A4\u30EB\u306E\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u4E2D\u2026 ReportBodyFile.progress.querying=\u30d5\u30a1\u30a4\u30eb\u306e\u30af\u30a8\u30ea\u3092\u5b9f\u884c\u4e2d\u2026
ReportBodyFile.ingestWarning.text=\u8B66\u544A\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B5\u30FC\u30D3\u30B9\u304C\u5B8C\u4E86\u3059\u308B\u524D\u306B\u30EC\u30DD\u30FC\u30C8\u304C\u5B9F\u884C\u3055\u308C\u307E\u3057\u305F\uFF01 ReportBodyFile.ingestWarning.text=\u8b66\u544a\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b5\u30fc\u30d3\u30b9\u304c\u5b8c\u4e86\u3059\u308b\u524d\u306b\u30ec\u30dd\u30fc\u30c8\u304c\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f\uff01
ReportBodyFile.progress.loading=\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026 ReportBodyFile.progress.loading=\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u2026
ReportBodyFile.progress.processing={0}\u3092\u51E6\u7406\u4E2D\u2026 ReportBodyFile.progress.processing={0}\u3092\u51e6\u7406\u4e2d\u2026
ReportBodyFile.getName.text=TSK\u30DC\u30C7\u30A3\u30D5\u30A1\u30A4\u30EB ReportBodyFile.getName.text=TSK\u30dc\u30c7\u30a3\u30d5\u30a1\u30a4\u30eb
ReportBodyFile.getDesc.text=\u5404\u30D5\u30A1\u30A4\u30EB\u306EMAC\u30BF\u30A4\u30E0\u3092\u542B\u3080\u3001\u30DC\u30C7\u30A3\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F\u30EC\u30DD\u30FC\u30C8\u3002\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30D3\u30E5\u30FC\u306B\u3053\u306E\u5F62\u5F0F\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002 ReportBodyFile.getDesc.text=\u5404\u30d5\u30a1\u30a4\u30eb\u306eMAC\u30bf\u30a4\u30e0\u3092\u542b\u3080\u3001\u30dc\u30c7\u30a3\u30d5\u30a1\u30a4\u30eb\u5f62\u5f0f\u30ec\u30dd\u30fc\u30c8\u3002\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30d3\u30e5\u30fc\u306b\u3053\u306e\u5f62\u5f0f\u3092\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002
ReportBodyFile.getFilePath.text=BodyFile.txt ReportBodyFile.getFilePath.text=BodyFile.txt
ReportBranding.defaultReportTitle.text=Autopsy\u30D5\u30A9\u30EC\u30F3\u30B8\u30C3\u30AF\u30EC\u30DD\u30FC\u30C8 ReportBranding.defaultReportTitle.text=Autopsy\u30d5\u30a9\u30ec\u30f3\u30b8\u30c3\u30af\u30ec\u30dd\u30fc\u30c8
ReportBranding.defaultReportFooter.text=Autopsy\u30AA\u30FC\u30D7\u30F3\u30BD\u30FC\u30B9\u30FB\u30C7\u30B8\u30BF\u30EB\u30FB\u30D5\u30A9\u30EC\u30F3\u30B8\u30C3\u30AF\u30FB\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u306B\u3088\u308A\u63D0\u4F9B - www.sleuthkit.org ReportBranding.defaultReportFooter.text=Autopsy\u30aa\u30fc\u30d7\u30f3\u30bd\u30fc\u30b9\u30fb\u30c7\u30b8\u30bf\u30eb\u30fb\u30d5\u30a9\u30ec\u30f3\u30b8\u30c3\u30af\u30fb\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u306b\u3088\u308a\u63d0\u4f9b - www.sleuthkit.org
ReportExcel.numAartifacts.text=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u6570\uFF1A ReportExcel.numAartifacts.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u6570\uff1a
ReportExcel.getName.text=\u7D50\u679C - Excel ReportExcel.getName.text=\u7d50\u679c - Excel
ReportExcel.getDesc.text=\u7D50\u679C\u306B\u95A2\u3059\u308B\u30EC\u30DD\u30FC\u30C8\u3002Excel(XLS)\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u3067\u30A2\u30A4\u30C6\u30E0\u306E\u30BF\u30B0\u4ED8\u3051\u304C\u3055\u308C\u3066\u3044\u307E\u3059\u3002 ReportExcel.getDesc.text=\u7d50\u679c\u306b\u95a2\u3059\u308b\u30ec\u30dd\u30fc\u30c8\u3002Excel(XLS)\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u30a2\u30a4\u30c6\u30e0\u306e\u30bf\u30b0\u4ed8\u3051\u304c\u3055\u308c\u3066\u3044\u307e\u3059\u3002
ReportExcel.sheetName.text=\u30B5\u30DE\u30EA\u30FC ReportExcel.sheetName.text=\u30b5\u30de\u30ea\u30fc
ReportExcel.cellVal.summary=\u30B5\u30DE\u30EA\u30FC ReportExcel.cellVal.summary=\u30b5\u30de\u30ea\u30fc
ReportExcel.cellVal.caseName=\u30B1\u30FC\u30B9\u540D\uFF1A ReportExcel.cellVal.caseName=\u30b1\u30fc\u30b9\u540d\uff1a
ReportExcel.cellVal.caseNum=\u30B1\u30FC\u30B9\u756A\u53F7\uFF1A ReportExcel.cellVal.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a
ReportExcel.cellVal.examiner=\u8ABF\u67FB\u62C5\u5F53\u8005\uFF1A ReportExcel.cellVal.examiner=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a
ReportExcel.cellVal.numImages=\u30A4\u30E1\u30FC\u30B8\u6570\uFF1A ReportExcel.cellVal.numImages=\u30a4\u30e1\u30fc\u30b8\u6570\uff1a
ReportGenerationPanel.confDlg.sureToClose.msg=\u3053\u306E\u30C0\u30A4\u30A2\u30ED\u30B0\u3092\u672C\u5F53\u306B\u9589\u3058\u307E\u3059\u304B\uFF1F\n\u5168\u3066\u306E\u30EC\u30DD\u30FC\u30C8\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3059\u3002 ReportGenerationPanel.confDlg.sureToClose.msg=\u3053\u306e\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u672c\u5f53\u306b\u9589\u3058\u307e\u3059\u304b\uff1f\n\u5168\u3066\u306e\u30ec\u30dd\u30fc\u30c8\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3059\u3002
ReportGenerationPanel.confDlg.title.closing=\u9589\u3058\u3066\u3044\u307E\u3059 ReportGenerationPanel.confDlg.title.closing=\u9589\u3058\u3066\u3044\u307e\u3059
ReportGenerator.displayProgress.title.text=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u30D7\u30ED\u30B0\u30EC\u30B9\u2026 ReportGenerator.displayProgress.title.text=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u30d7\u30ed\u30b0\u30ec\u30b9\u2026
ReportGenerator.progress.queryingDb.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u4E2D\u2026 ReportGenerator.progress.queryingDb.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30af\u30a8\u30ea\u3092\u5b9f\u884c\u4e2d\u2026
ReportGenerator.progress.processingFile.text={0}\u3092\u51E6\u7406\u4E2D ReportGenerator.progress.processingFile.text={0}\u3092\u51e6\u7406\u4e2d
ReportGenerator.artifactTable.taggedResults.text=\u6B21\u306E\u4E2D\u306E\u4E00\u3064\u3067\u30BF\u30B0\u3055\u308C\u305F\u7D50\u679C\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\uFF1A ReportGenerator.artifactTable.taggedResults.text=\u6b21\u306e\u4e2d\u306e\u4e00\u3064\u3067\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\uff1a
ReportGenerator.progress.processing={0}\u3092\u51E6\u7406\u4E2D\u2026 ReportGenerator.progress.processing={0}\u3092\u51e6\u7406\u4e2d\u2026
ReportGenerator.msgShow.skippingArtType.title=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30BF\u30A4\u30D7{0}\u3092\u30EC\u30DD\u30FC\u30C8\u3067\u30B9\u30AD\u30C3\u30D7\u3057\u3066\u3044\u307E\u3059 ReportGenerator.msgShow.skippingArtType.title=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30bf\u30a4\u30d7{0}\u3092\u30ec\u30dd\u30fc\u30c8\u3067\u30b9\u30ad\u30c3\u30d7\u3057\u3066\u3044\u307e\u3059
ReportGenerator.msgShow.skippingArtType.msg=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u3059\u308B\u306E\u306B\u4E0D\u660E\u306A\u30B3\u30E9\u30E0 ReportGenerator.msgShow.skippingArtType.msg=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u3059\u308b\u306e\u306b\u4e0d\u660e\u306a\u30b3\u30e9\u30e0
ReportGenerator.msgShow.skippingArtRow.title=\u30BF\u30A4\u30D7{0}\u306E\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u884C\u3092\u30EC\u30DD\u30FC\u30C8\u3067\u30B9\u30AD\u30C3\u30D7\u3057\u3066\u3044\u307E\u3059 ReportGenerator.msgShow.skippingArtRow.title=\u30bf\u30a4\u30d7{0}\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u884c\u3092\u30ec\u30dd\u30fc\u30c8\u3067\u30b9\u30ad\u30c3\u30d7\u3057\u3066\u3044\u307e\u3059
ReportGenerator.msgShow.skippingArtRow.msg=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u3059\u308B\u306E\u306B\u4E0D\u660E\u306A\u30B3\u30E9\u30E0 ReportGenerator.msgShow.skippingArtRow.msg=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u3059\u308b\u306e\u306b\u4e0d\u660e\u306a\u30b3\u30e9\u30e0
ReportGenerator.makeContTagTab.taggedFiles.msg=\u306E\u4E2D\u306E\u4E00\u3064\u3067\u30BF\u30B0\u3055\u308C\u305F\u7D50\u679C\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\uFF1A ReportGenerator.makeContTagTab.taggedFiles.msg=\u306e\u4e2d\u306e\u4e00\u3064\u3067\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\uff1a
ReportGenerator.makeBbArtTagTab.taggedRes.msg=\u3053\u306E\u30EC\u30DD\u30FC\u30C8\u306B\u306F\u6B21\u3067\u30BF\u30B0\u3055\u308C\u305F\u7D50\u679C\u3057\u304B\u542B\u307E\u308C\u307E\u305B\u3093\uFF1A ReportGenerator.makeBbArtTagTab.taggedRes.msg=\u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306b\u306f\u6b21\u3067\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c\u3057\u304b\u542b\u307e\u308c\u307e\u305b\u3093\uff1a
ReportGenerator.tagTable.header.resultType=\u7D50\u679C\u30BF\u30A4\u30D7 ReportGenerator.tagTable.header.resultType=\u7d50\u679c\u30bf\u30a4\u30d7
ReportGenerator.tagTable.header.tag=\u30BF\u30B0 ReportGenerator.tagTable.header.tag=\u30bf\u30b0
ReportGenerator.tagTable.header.comment=\u30B3\u30E1\u30F3\u30C8 ReportGenerator.tagTable.header.comment=\u30b3\u30e1\u30f3\u30c8
ReportGenerator.tagTable.header.srcFile=\u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB ReportGenerator.tagTable.header.srcFile=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb
ReportGenerator.progress.createdThumb.text=\u30B5\u30E0\u30CD\u30A4\u30EB\u3092\u4F5C\u6210\u4E2D\u2026 ReportGenerator.progress.createdThumb.text=\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u4f5c\u6210\u4e2d\u2026
ReportGenerator.thumbnailTable.name=\u30B5\u30E0\u30CD\u30A4\u30EB ReportGenerator.thumbnailTable.name=\u30b5\u30e0\u30cd\u30a4\u30eb
ReportGenerator.thumbnailTable.desc=\u30BF\u30B0\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u3084\u7D50\u679C\u306B\u95A2\u9023\u3059\u308B\u30A4\u30E1\u30FC\u30B8\u306E\u30B5\u30E0\u30CD\u30A4\u30EB\u304C\u542B\u307E\u308C\u307E\u3059\u3002 ReportGenerator.thumbnailTable.desc=\u30bf\u30b0\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3084\u7d50\u679c\u306b\u95a2\u9023\u3059\u308b\u30a4\u30e1\u30fc\u30b8\u306e\u30b5\u30e0\u30cd\u30a4\u30eb\u304c\u542b\u307e\u308c\u307e\u3059\u3002
ReportGenerator.writeKwHits.userSrchs=\u30E6\u30FC\u30B6\u691C\u7D22 ReportGenerator.writeKwHits.userSrchs=\u30e6\u30fc\u30b6\u691c\u7d22
ReportGenerator.progress.processingList={0} ({1})\u3092\u51E6\u7406\u4E2D\u2026 ReportGenerator.progress.processingList={0} ({1})\u3092\u51e6\u7406\u4e2d\u2026
ReportGenerator.artTableColHdr.url=URL ReportGenerator.artTableColHdr.url=URL
ReportGenerator.artTableColHdr.title=\u30BF\u30A4\u30C8\u30EB ReportGenerator.artTableColHdr.title=\u30bf\u30a4\u30c8\u30eb
ReportGenerator.artTableColHdr.dateCreated=\u4F5C\u6210\u65E5\u4ED8 ReportGenerator.artTableColHdr.dateCreated=\u4f5c\u6210\u65e5\u4ed8
ReportGenerator.artTableColHdr.program=\u30D7\u30ED\u30B0\u30E9\u30E0 ReportGenerator.artTableColHdr.program=\u30d7\u30ed\u30b0\u30e9\u30e0
ReportGenerator.artTableColHdr.srcFile=\u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB ReportGenerator.artTableColHdr.srcFile=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb
ReportGenerator.artTableColHdr.dateTime=\u65E5\u4ED8\uFF0F\u6642\u523B ReportGenerator.artTableColHdr.dateTime=\u65e5\u4ed8\uff0f\u6642\u523b
ReportGenerator.artTableColHdr.name=\u540D\u524D ReportGenerator.artTableColHdr.name=\u540d\u524d
ReportGenerator.artTableColHdr.value=\u30D0\u30EA\u30E5\u30FC ReportGenerator.artTableColHdr.value=\u30d0\u30ea\u30e5\u30fc
ReportGenerator.artTableColHdr.dateAccessed=\u30A2\u30AF\u30BB\u30B9\u65E5\u4ED8 ReportGenerator.artTableColHdr.dateAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u4ed8
ReportGenerator.artTableColHdr.referrer=\u30EA\u30D5\u30A1\u30E9 ReportGenerator.artTableColHdr.referrer=\u30ea\u30d5\u30a1\u30e9
ReportGenerator.artTableColHdr.dest=\u30C7\u30B9\u30C6\u30A3\u30CD\u30FC\u30B7\u30E7\u30F3 ReportGenerator.artTableColHdr.dest=\u30c7\u30b9\u30c6\u30a3\u30cd\u30fc\u30b7\u30e7\u30f3
ReportGenerator.artTableColHdr.sourceUrl=\u30BD\u30FC\u30B9URL ReportGenerator.artTableColHdr.sourceUrl=\u30bd\u30fc\u30b9URL
ReportGenerator.artTableColHdr.path=\u30D1\u30B9 ReportGenerator.artTableColHdr.path=\u30d1\u30b9
ReportGenerator.artTableColHdr.progName=\u30D7\u30ED\u30B0\u30E9\u30E0\u540D ReportGenerator.artTableColHdr.progName=\u30d7\u30ed\u30b0\u30e9\u30e0\u540d
ReportGenerator.artTableColHdr.instDateTime=\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u65E5\u4ED8\uFF0F\u6642\u523B ReportGenerator.artTableColHdr.instDateTime=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65e5\u4ed8\uff0f\u6642\u523b
ReportGenerator.artTableColHdr.preview=\u30D7\u30EC\u30D3\u30E5\u30FC ReportGenerator.artTableColHdr.preview=\u30d7\u30ec\u30d3\u30e5\u30fc
ReportGenerator.artTableColHdr.file=\u30D5\u30A1\u30A4\u30EB ReportGenerator.artTableColHdr.file=\u30d5\u30a1\u30a4\u30eb
ReportGenerator.artTableColHdr.size=\u30B5\u30A4\u30BA ReportGenerator.artTableColHdr.size=\u30b5\u30a4\u30ba
ReportGenerator.artTableColHdr.deviceId=\u6A5F\u5668ID ReportGenerator.artTableColHdr.deviceId=\u6a5f\u5668ID
ReportGenerator.artTableColHdr.text=\u30C6\u30AD\u30B9\u30C8 ReportGenerator.artTableColHdr.text=\u30c6\u30ad\u30b9\u30c8
ReportGenerator.artTableColHdr.domain=\u30C9\u30E1\u30A4\u30F3 ReportGenerator.artTableColHdr.domain=\u30c9\u30e1\u30a4\u30f3
ReportGenerator.artTableColHdr.devManufacturer=\u6A5F\u5668\u30E1\u30FC\u30AB\u30FC ReportGenerator.artTableColHdr.devManufacturer=\u6a5f\u5668\u30e1\u30fc\u30ab\u30fc
ReportGenerator.artTableColHdr.devModel=\u6A5F\u5668\u30E2\u30C7\u30EB ReportGenerator.artTableColHdr.devModel=\u6a5f\u5668\u30e2\u30c7\u30eb
ReportGenerator.artTableColHdr.personName=\u4EBA\u540D ReportGenerator.artTableColHdr.personName=\u4eba\u540d
ReportGenerator.artTableColHdr.phoneNumber=\u96FB\u8A71\u756A\u53F7 ReportGenerator.artTableColHdr.phoneNumber=\u96fb\u8a71\u756a\u53f7
ReportGenerator.artTableColHdr.phoneNumHome=\u96FB\u8A71\u756A\u53F7\uFF08\u81EA\u5B85\uFF09 ReportGenerator.artTableColHdr.phoneNumHome=\u96fb\u8a71\u756a\u53f7\uff08\u81ea\u5b85\uff09
ReportGenerator.artTableColHdr.phoneNumOffice=\u96FB\u8A71\u756A\u53F7\uFF08\u4F1A\u793E\uFF09 ReportGenerator.artTableColHdr.phoneNumOffice=\u96fb\u8a71\u756a\u53f7\uff08\u4f1a\u793e\uff09
ReportGenerator.artTableColHdr.phoneNumMobile=\u96FB\u8A71\u756A\u53F7\uFF08\u643A\u5E2F\uFF09 ReportGenerator.artTableColHdr.phoneNumMobile=\u96fb\u8a71\u756a\u53f7\uff08\u643a\u5e2f\uff09
ReportGenerator.artTableColHdr.email=Email ReportGenerator.artTableColHdr.email=Email
ReportGenerator.artTableColHdr.msgType=\u30E1\u30C3\u30BB\u30FC\u30B8\u30BF\u30A4\u30D7 ReportGenerator.artTableColHdr.msgType=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7
ReportGenerator.artTableColHdr.latitude=\u7DEF\u5EA6 ReportGenerator.artTableColHdr.latitude=\u7def\u5ea6
ReportGenerator.artTableColHdr.longitude=\u7D4C\u5EA6 ReportGenerator.artTableColHdr.longitude=\u7d4c\u5ea6
ReportGenerator.artTableColHdr.dateTaken=\u64AE\u5F71\u65E5\u4ED8 ReportGenerator.artTableColHdr.dateTaken=\u64ae\u5f71\u65e5\u4ed8
ReportGenerator.artTableColHdr.subject=\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8 ReportGenerator.artTableColHdr.subject=\u30b5\u30d6\u30b8\u30a7\u30af\u30c8
ReportGenerator.artTableColHdr.calendarEntryType=\u30AB\u30EC\u30F3\u30C0\u30FC\u30A8\u30F3\u30C8\u30EA\u30BF\u30A4\u30D7 ReportGenerator.artTableColHdr.calendarEntryType=\u30ab\u30ec\u30f3\u30c0\u30fc\u30a8\u30f3\u30c8\u30ea\u30bf\u30a4\u30d7
ReportGenerator.artTableColHdr.description=\u8AAC\u660E ReportGenerator.artTableColHdr.description=\u8aac\u660e
ReportGenerator.artTableColHdr.startDateTime=\u958B\u59CB\u65E5\u4ED8\uFF0F\u6642\u523B ReportGenerator.artTableColHdr.startDateTime=\u958b\u59cb\u65e5\u4ed8\uff0f\u6642\u523b
ReportGenerator.artTableColHdr.shortCut=\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8 ReportGenerator.artTableColHdr.shortCut=\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8
ReportGenerator.artTableColHdr.endDateTime=\u4FEE\u4E86\u65E5\u4ED8\uFF0F\u6642\u523B ReportGenerator.artTableColHdr.endDateTime=\u4fee\u4e86\u65e5\u4ed8\uff0f\u6642\u523b
ReportGenerator.artTableColHdr.location=\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3 ReportGenerator.artTableColHdr.location=\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3
ReportGenerator.artTableColHdr.deviceName=\u6A5F\u5668\u540D ReportGenerator.artTableColHdr.deviceName=\u6a5f\u5668\u540d
ReportGenerator.artTableColHdr.deviceAddress=\u6A5F\u5668\u30A2\u30C9\u30EC\u30B9 ReportGenerator.artTableColHdr.deviceAddress=\u6a5f\u5668\u30a2\u30c9\u30ec\u30b9
ReportGenerator.artTableColHdr.altitude=\u6A19\u9AD8 ReportGenerator.artTableColHdr.altitude=\u6a19\u9ad8
ReportGenerator.artTableColHdr.locationAddress=\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\u30A2\u30C9\u30EC\u30B9 ReportGenerator.artTableColHdr.locationAddress=\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u30a2\u30c9\u30ec\u30b9
ReportGenerator.artTableColHdr.category=\u30AB\u30C6\u30B4\u30EA\u30FC ReportGenerator.artTableColHdr.category=\u30ab\u30c6\u30b4\u30ea\u30fc
ReportGenerator.artTableColHdr.userId=\u30E6\u30FC\u30B6ID ReportGenerator.artTableColHdr.userId=\u30e6\u30fc\u30b6ID
ReportGenerator.artTableColHdr.password=\u30D1\u30B9\u30EF\u30FC\u30C9 ReportGenerator.artTableColHdr.password=\u30d1\u30b9\u30ef\u30fc\u30c9
ReportGenerator.artTableColHdr.replytoAddress=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9 ReportGenerator.artTableColHdr.replytoAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
ReportGenerator.artTableColHdr.mailServer=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0 ReportGenerator.artTableColHdr.mailServer=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
ReportGenerator.artTableColHdr.tags=\u30BF\u30B0 ReportGenerator.artTableColHdr.tags=\u30bf\u30b0
ReportHTML.addThumbRows.dataType.title=\u30BF\u30B0\u4ED8\u3051\u3055\u308C\u305F\u30A4\u30E1\u30FC\u30B8 - {0} ReportHTML.addThumbRows.dataType.title=\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30a4\u30e1\u30fc\u30b8 - {0}
ReportHTML.addThumbRows.dataType.msg=\u30A4\u30E1\u30FC\u30B8\u3092\u542B\u3080\u30BF\u30B0\u4ED8\u3051\u3055\u308C\u305F\u7D50\u679C\u304A\u3088\u3073\u30B3\u30F3\u30C6\u30F3\u30C4\u3002 ReportHTML.addThumbRows.dataType.msg=\u30a4\u30e1\u30fc\u30b8\u3092\u542b\u3080\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u7d50\u679c\u304a\u3088\u3073\u30b3\u30f3\u30c6\u30f3\u30c4\u3002
ReportHTML.thumbLink.tags=\u30BF\u30B0\uFF1A ReportHTML.thumbLink.tags=\u30bf\u30b0\uff1a
ReportHTML.getName.text=\u7D50\u679C - HTML ReportHTML.getName.text=\u7d50\u679c - HTML
ReportHTML.getDesc.text=HTML\u5F62\u5F0F\u306E\u7D50\u679C\u304A\u3088\u3073\u30BF\u30B0\u4ED8\u3051\u3055\u308C\u305F\u30A2\u30A4\u30C6\u30E0\u306E\u30EC\u30DD\u30FC\u30C8 ReportHTML.getDesc.text=HTML\u5f62\u5f0f\u306e\u7d50\u679c\u304a\u3088\u3073\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30a2\u30a4\u30c6\u30e0\u306e\u30ec\u30dd\u30fc\u30c8
ReportHTML.writeIndex.title=\u30B1\u30FC\u30B9{0}\u306EAutopsy\u30EC\u30DD\u30FC\u30C8 ReportHTML.writeIndex.title=\u30b1\u30fc\u30b9{0}\u306eAutopsy\u30ec\u30dd\u30fc\u30c8
ReportHTML.writeNav.title=\u30EC\u30DD\u30FC\u30C8\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3 ReportHTML.writeNav.title=\u30ec\u30dd\u30fc\u30c8\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3
ReportHTML.writeNav.h1=\u30EC\u30DD\u30FC\u30C8\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3 ReportHTML.writeNav.h1=\u30ec\u30dd\u30fc\u30c8\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3
ReportHTML.writeNav.summary=\u30B1\u30FC\u30B9\u30B5\u30DE\u30EA\u30FC ReportHTML.writeNav.summary=\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc
ReportHTML.writeSum.title=\u30B1\u30FC\u30B9\u30B5\u30DE\u30EA\u30FC ReportHTML.writeSum.title=\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc
ReportHTML.writeSum.caseName=\u30B1\u30FC\u30B9\uFF1A ReportHTML.writeSum.caseName=\u30b1\u30fc\u30b9\uff1a
ReportHTML.writeSum.caseNum=\u30B1\u30FC\u30B9\u756A\u53F7\uFF1A ReportHTML.writeSum.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a
ReportHTML.writeSum.examiner=\u8ABF\u67FB\u62C5\u5F53\u8005\uFF1A ReportHTML.writeSum.examiner=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a
ReportHTML.writeSum.numImages=\u30A4\u30E1\u30FC\u30B8\u6570\uFF1A ReportHTML.writeSum.numImages=\u30a4\u30e1\u30fc\u30b8\u6570\uff1a
ReportHTML.writeSum.path=\u30D1\u30B9\uFF1A ReportHTML.writeSum.path=\u30d1\u30b9\uff1a
ReportProgressPanel.start.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB ReportProgressPanel.start.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb
ReportProgressPanel.complete.processLbl.text=\u5B8C\u4E86 ReportProgressPanel.complete.processLbl.text=\u5b8c\u4e86
ReportProgressPanel.complete.cancelButton.text=\u5B8C\u4E86 ReportProgressPanel.complete.cancelButton.text=\u5b8c\u4e86
ReportProgressPanel.cancel.cancelButton.toolTipText=\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F ReportProgressPanel.cancel.cancelButton.toolTipText=\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f
ReportWizardAction.actionName.text=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210 ReportWizardAction.actionName.text=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210
ReportWizardAction.reportWiz.title=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210 ReportWizardAction.reportWiz.title=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210
ReportWizardAction.toolBarButton.text=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210 ReportWizardAction.toolBarButton.text=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210
ReportWizardPanel1.nextButton.text=\u6B21 > ReportWizardPanel1.nextButton.text=\u6b21 >
ReportWizardPanel2.nextButton.text=\u6B21 > ReportWizardPanel2.nextButton.text=\u6b21 >
ReportGenerator.artTableColHdr.direction=\u65B9\u5411 ReportGenerator.artTableColHdr.direction=\u65b9\u5411
ReportGenerator.artTableColHdr.fromEmail=\u9001\u4FE1\u5143E\u30E1\u30FC\u30EB ReportGenerator.artTableColHdr.fromEmail=\u9001\u4fe1\u5143E\u30e1\u30fc\u30eb
ReportGenerator.artTableColHdr.toEmail=\u9001\u4FE1\u5148E\u30E1\u30FC\u30EB ReportGenerator.artTableColHdr.toEmail=\u9001\u4fe1\u5148E\u30e1\u30fc\u30eb
ReportGenerator.artTableColHdr.fromPhoneNum=\u767A\u4FE1\u8005\u96FB\u8A71\u756A\u53F7 ReportGenerator.artTableColHdr.fromPhoneNum=\u767a\u4fe1\u8005\u96fb\u8a71\u756a\u53f7
ReportGenerator.artTableColHdr.toPhoneNum=\u7740\u4FE1\u8005\u96FB\u8A71\u756A\u53F7 ReportGenerator.artTableColHdr.toPhoneNum=\u7740\u4fe1\u8005\u96fb\u8a71\u756a\u53f7
ReportGenerator.artTableColHdr.appName=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D ReportGenerator.artTableColHdr.appName=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u540d
ReportGenerator.artTableColHdr.appPath=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30D1\u30B9 ReportGenerator.artTableColHdr.appPath=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30d1\u30b9
ReportHTML.writeIndex.noFrames.msg=\u4F7F\u7528\u3057\u3066\u3044\u308B\u30D6\u30E9\u30A6\u30B6\u306F\u5F0A\u793E\u306E\u30D5\u30EC\u30FC\u30E0\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3068\u306E\u4E92\u63DB\u6027\u304C\u3042\u308A\u307E\u305B\u3093\u3002 ReportHTML.writeIndex.noFrames.msg=\u4f7f\u7528\u3057\u3066\u3044\u308b\u30d6\u30e9\u30a6\u30b6\u306f\u5f0a\u793e\u306e\u30d5\u30ec\u30fc\u30e0\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3068\u306e\u4e92\u63db\u6027\u304c\u3042\u308a\u307e\u305b\u3093\u3002
ReportHTML.writeIndex.noFrames.seeNav=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30EA\u30F3\u30AF\u306F\u4E0B\u8A18\u306E\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u30DA\u30FC\u30B8</a>\u3092\u3054\u89A7\u4E0B\u3055\u3044<a href\="nav.html"> ReportHTML.writeIndex.noFrames.seeNav=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ea\u30f3\u30af\u306f\u4e0b\u8a18\u306e\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\u30da\u30fc\u30b8</a>\u3092\u3054\u89a7\u4e0b\u3055\u3044<a href\="nav.html">
ReportHTML.writeIndex.seeSum=\u307E\u305F\u3001\u30B1\u30FC\u30B9\u30B5\u30DE\u30EA\u30FC\u306F\u4E0B\u8A18\u306E\u30B5\u30DE\u30EA\u30FC\u30DA\u30FC\u30B8</a>\u3092\u3054\u89A7\u4E0B\u3055\u3044\u3002<a href\="summary.html"> ReportHTML.writeIndex.seeSum=\u307e\u305f\u3001\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc\u306f\u4e0b\u8a18\u306e\u30b5\u30de\u30ea\u30fc\u30da\u30fc\u30b8</a>\u3092\u3054\u89a7\u4e0b\u3055\u3044\u3002<a href\="summary.html">
ReportHTML.writeSum.warningMsg=<span>\u8B66\u544A\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B5\u30FC\u30D3\u30B9\u304C\u5B8C\u4E86\u3059\u308B\u524D\u306B\u30EC\u30DD\u30FC\u30C8\u304C\u5B9F\u884C\u3055\u308C\u307E\u3057\u305F\uFF01</span> ReportHTML.writeSum.warningMsg=<span>\u8b66\u544a\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b5\u30fc\u30d3\u30b9\u304c\u5b8c\u4e86\u3059\u308b\u524d\u306b\u30ec\u30dd\u30fc\u30c8\u304c\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f\uff01</span>
ReportHTML.writeSum.noExaminer=<i>\u8ABF\u67FB\u62C5\u5F53\u8005\u7121\u3057</i> ReportHTML.writeSum.noExaminer=<i>\u8abf\u67fb\u62c5\u5f53\u8005\u7121\u3057</i>
ReportHTML.writeSum.imageInfoHeading=<h2>\u30A4\u30E1\u30FC\u30B8\u60C5\u5831\uFF1A</h2> ReportHTML.writeSum.imageInfoHeading=<h2>\u30a4\u30e1\u30fc\u30b8\u60c5\u5831\uff1a</h2>
ReportHTML.writeSum.timezone=\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\uFF1A ReportHTML.writeSum.timezone=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\uff1a
ReportProgressPanel.progress.queuing=\u30AD\u30E5\u30FC\u30A4\u30F3\u30B0\u2026 ReportProgressPanel.progress.queuing=\u30ad\u30e5\u30fc\u30a4\u30f3\u30b0\u2026
ReportProgressPanel.initPathLabel.noFile=<html><u>\u30EC\u30DD\u30FC\u30C8\u30D5\u30A1\u30A4\u30EB\u7121\u3057</u></html> ReportProgressPanel.initPathLabel.noFile=<html><u>\u30ec\u30dd\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u7121\u3057</u></html>
ReportProgressPanel.start.progress.text=\u30EC\u30DD\u30FC\u30C8\u958B\u59CB\u4E2D\u2026 ReportProgressPanel.start.progress.text=\u30ec\u30dd\u30fc\u30c8\u958b\u59cb\u4e2d\u2026
ReportProgressPanel.cancel.procLbl.text=\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F ReportProgressPanel.cancel.procLbl.text=\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f
ReportVisualPanel1.getName.text=\u30EC\u30DD\u30FC\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u9078\u629E\u304A\u3088\u3073\u8A2D\u5B9A ReportVisualPanel1.getName.text=\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u9078\u629e\u304a\u3088\u3073\u8a2d\u5b9a
ReportVisualPanel2.getName.text=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30EC\u30DD\u30FC\u30C8\u3092\u8A2D\u5B9A ReportVisualPanel2.getName.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ec\u30dd\u30fc\u30c8\u3092\u8a2d\u5b9a
ReportWizardFileOptionsPanel.finishButton.text=\u7D42\u4E86 ReportWizardFileOptionsPanel.finishButton.text=\u7d42\u4e86
ReportWizardFileOptionsVisualPanel.getName.text=\u30D5\u30A1\u30A4\u30EB\u30EC\u30DD\u30FC\u30C8\u3092\u8A2D\u5B9A ReportWizardFileOptionsVisualPanel.getName.text=\u30d5\u30a1\u30a4\u30eb\u30ec\u30dd\u30fc\u30c8\u3092\u8a2d\u5b9a
ReportWizardPanel1.finishButton.text=\u7D42\u4E86 ReportWizardPanel1.finishButton.text=\u7d42\u4e86
ReportWizardPanel2.finishButton.text=\u7D42\u4E86 ReportWizardPanel2.finishButton.text=\u7d42\u4e86
ReportHTML.writeSum.reportGenOn.text={0}\u306BHTML\u30EC\u30DD\u30FC\u30C8\u306F\u751F\u6210\u3055\u308C\u307E\u3057\u305F ReportHTML.writeSum.reportGenOn.text={0}\u306bHTML\u30ec\u30dd\u30fc\u30c8\u306f\u751f\u6210\u3055\u308c\u307e\u3057\u305f
ReportHTML.writeSum.noCaseNum=<i>\u30B1\u30FC\u30B9\u756A\u53F7\u304C\u3042\u308A\u307E\u305B\u3093</i> ReportHTML.writeSum.noCaseNum=<i>\u30b1\u30fc\u30b9\u756a\u53f7\u304c\u3042\u308a\u307e\u305b\u3093</i>
ReportGenerator.errors.reportErrorTitle=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F ReportGenerator.errors.reportErrorTitle=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
ReportGenerator.errors.reportErrorText=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\uFF1A ReportGenerator.errors.reportErrorText=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a
ReportKML.getDesc.text=\u95A2\u9023\u30D5\u30A1\u30A4\u30EB\u306E\u5EA7\u6A19\u3092\u542B\u3080KML\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u306E\u30EC\u30DD\u30FC\u30C8\u3002\u3053\u306E\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u306FGoogle Earth\u30D3\u30E5\u30FC\u306B\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002 ReportKML.getDesc.text=\u95a2\u9023\u30d5\u30a1\u30a4\u30eb\u306e\u5ea7\u6a19\u3092\u542b\u3080KML\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u306e\u30ec\u30dd\u30fc\u30c8\u3002\u3053\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u306fGoogle Earth\u30d3\u30e5\u30fc\u306b\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002
ReportKML.getName.text=Google Earth/KML ReportKML.getName.text=Google Earth/KML
ReportKML.progress.loading=\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026 ReportKML.progress.loading=\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u2026
ReportKML.progress.querying=\u30D5\u30A1\u30A4\u30EB\u306E\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u4E2D\u2026 ReportKML.progress.querying=\u30d5\u30a1\u30a4\u30eb\u306e\u30af\u30a8\u30ea\u3092\u5b9f\u884c\u4e2d\u2026
ReportBodyFile.generateReport.srcModuleName.text=TSK\u30DC\u30C7\u30A3\u30D5\u30A1\u30A4\u30EB ReportBodyFile.generateReport.srcModuleName.text=TSK\u30dc\u30c7\u30a3\u30d5\u30a1\u30a4\u30eb
ReportExcel.endReport.srcModuleName.text=Excel\u30EC\u30DD\u30FC\u30C8 ReportExcel.endReport.srcModuleName.text=Excel\u30ec\u30dd\u30fc\u30c8
ReportGenerator.artTableColHdr.extension.text=\u62E1\u5F35\u5B50 ReportGenerator.artTableColHdr.extension.text=\u62e1\u5f35\u5b50
ReportGenerator.artTableColHdr.mimeType.text=MIME\u30BF\u30A4\u30D7 ReportGenerator.artTableColHdr.mimeType.text=MIME\u30bf\u30a4\u30d7
ReportHTML.writeIndex.srcModuleName.text=HTML\u30EC\u30DD\u30FC\u30C8 ReportHTML.writeIndex.srcModuleName.text=HTML\u30ec\u30dd\u30fc\u30c8
ReportKML.genReport.srcModuleName.text=KML\u30EC\u30DD\u30FC\u30C8 ReportKML.genReport.srcModuleName.text=KML\u30ec\u30dd\u30fc\u30c8
ReportGenerator.artTableColHdr.associatedArtifact=\u95A2\u4FC2\u3059\u308B\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8 ReportGenerator.artTableColHdr.associatedArtifact=\u95a2\u4fc2\u3059\u308b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8
ReportGenerator.artTableColHdr.count=\u30AB\u30A6\u30F3\u30C8 ReportGenerator.artTableColHdr.count=\u30ab\u30a6\u30f3\u30c8
ReportGenerator.artTableColHdr.devMake=\u6A5F\u5668\u578B\u540D ReportGenerator.artTableColHdr.devMake=\u6a5f\u5668\u578b\u540d
ReportGenerator.artTableColHdr.latitudeEnd=\u5230\u7740\u7DEF\u5EA6 ReportGenerator.artTableColHdr.latitudeEnd=\u5230\u7740\u7def\u5ea6
ReportGenerator.artTableColHdr.latitudeStart=\u51FA\u767A\u7DEF\u5EA6 ReportGenerator.artTableColHdr.latitudeStart=\u51fa\u767a\u7def\u5ea6
ReportGenerator.artTableColHdr.localPath=\u30ED\u30FC\u30AB\u30EB\u30D1\u30B9 ReportGenerator.artTableColHdr.localPath=\u30ed\u30fc\u30ab\u30eb\u30d1\u30b9
ReportGenerator.artTableColHdr.longitudeEnd=\u5230\u7740\u7D4C\u5EA6 ReportGenerator.artTableColHdr.longitudeEnd=\u5230\u7740\u7d4c\u5ea6
ReportGenerator.artTableColHdr.longitudeStart=\u51FA\u767A\u7D4C\u5EA6 ReportGenerator.artTableColHdr.longitudeStart=\u51fa\u767a\u7d4c\u5ea6
ReportGenerator.artTableColHdr.osInstallDate.text=\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u65E5\u4ED8 ReportGenerator.artTableColHdr.osInstallDate.text=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65e5\u4ed8
ReportGenerator.artTableColHdr.osName.text=\u30AA\u30DA\u30EC\u30FC\u30C6\u30A3\u30F3\u30B0\u30B7\u30B9\u30C6\u30E0\u540D ReportGenerator.artTableColHdr.osName.text=\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u540d
ReportGenerator.artTableColHdr.processorArchitecture.text=\u30D7\u30ED\u30BB\u30C3\u30B5\u30A2\u30FC\u30AD\u30C6\u30AF\u30C1\u30E3 ReportGenerator.artTableColHdr.processorArchitecture.text=\u30d7\u30ed\u30bb\u30c3\u30b5\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3
ReportGenerator.artTableColHdr.readStatus=\u8AAD\u307F\u53D6\u308A\u4E2D\u30B9\u30C6\u30FC\u30BF\u30B9 ReportGenerator.artTableColHdr.readStatus=\u8aad\u307f\u53d6\u308a\u4e2d\u30b9\u30c6\u30fc\u30bf\u30b9
ReportGenerator.artTableColHdr.remotePath=\u30EA\u30E2\u30FC\u30C8\u30D1\u30B9 ReportGenerator.artTableColHdr.remotePath=\u30ea\u30e2\u30fc\u30c8\u30d1\u30b9
ReportGenerator.artTableColHdr.tskDateTimeRcvd=\u53D7\u4FE1\u65E5 ReportGenerator.artTableColHdr.tskDateTimeRcvd=\u53d7\u4fe1\u65e5
ReportGenerator.artTableColHdr.tskDateTimeSent=\u9001\u4FE1\u65E5 ReportGenerator.artTableColHdr.tskDateTimeSent=\u9001\u4fe1\u65e5
ReportGenerator.artTableColHdr.tskEmailBcc=E-Mail BCC ReportGenerator.artTableColHdr.tskEmailBcc=E-Mail BCC
ReportGenerator.artTableColHdr.tskEmailCc=E-Mail CC ReportGenerator.artTableColHdr.tskEmailCc=E-Mail CC
ReportGenerator.artTableColHdr.tskEmailFrom=E-Mail\u9001\u4FE1\u5143 ReportGenerator.artTableColHdr.tskEmailFrom=E-Mail\u9001\u4fe1\u5143
ReportGenerator.artTableColHdr.tskEmailTo=E-Mail\u9001\u4FE1\u5148 ReportGenerator.artTableColHdr.tskEmailTo=E-Mail\u9001\u4fe1\u5148
ReportGenerator.artTableColHdr.tskGpsRouteCategory=\u30AB\u30C6\u30B4\u30EA ReportGenerator.artTableColHdr.tskGpsRouteCategory=\u30ab\u30c6\u30b4\u30ea
ReportGenerator.artTableColHdr.tskInterestingFilesCategory=\u30EB\u30FC\u30EB ReportGenerator.artTableColHdr.tskInterestingFilesCategory=\u30eb\u30fc\u30eb
ReportGenerator.artTableColHdr.tskMsgId=\u30E1\u30C3\u30BB\u30FC\u30B8ID ReportGenerator.artTableColHdr.tskMsgId=\u30e1\u30c3\u30bb\u30fc\u30b8ID
ReportGenerator.artTableColHdr.tskPath=\u30D1\u30B9 ReportGenerator.artTableColHdr.tskPath=\u30d1\u30b9
ReportGenerator.artTableColHdr.tskSetName=\u30BB\u30C3\u30C8\u540D ReportGenerator.artTableColHdr.tskSetName=\u30bb\u30c3\u30c8\u540d
ReportGenerator.artTableColHdr.tskSubject=\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8 ReportGenerator.artTableColHdr.tskSubject=\u30b5\u30d6\u30b8\u30a7\u30af\u30c8
ReportGenerator.artTableColHdr.urlDomainDecoded=URL\u30C9\u30E1\u30A4\u30F3 ReportGenerator.artTableColHdr.urlDomainDecoded=URL\u30c9\u30e1\u30a4\u30f3
ReportGenerator.artTableColHdr.userName=\u30E6\u30FC\u30B6\u540D ReportGenerator.artTableColHdr.userName=\u30e6\u30fc\u30b6\u540d
ReportGenerator.errList.coreExceptionWhileGenRptRow=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30EC\u30DD\u30FC\u30C8\u7528\u30ED\u30FC\u30C7\u30FC\u30BF\u306E\u751F\u6210\u4E2D\u306B\u30B3\u30A2\u30A8\u30AF\u30BB\u30D7\u30B7\u30E7\u30F3\uFF08\u4F8B\u5916\uFF09\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F ReportGenerator.errList.coreExceptionWhileGenRptRow=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ec\u30dd\u30fc\u30c8\u7528\u30ed\u30fc\u30c7\u30fc\u30bf\u306e\u751f\u6210\u4e2d\u306b\u30b3\u30a2\u30a8\u30af\u30bb\u30d7\u30b7\u30e7\u30f3\uff08\u4f8b\u5916\uff09\u304c\u691c\u51fa\u3055\u308c\u307e\u3057\u305f
ReportGenerator.errList.errGetContentFromBBArtifact=Blackboard\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u304B\u3089\u30EC\u30DD\u30FC\u30C8\u7528\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u3092\u53D6\u5F97\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 ReportGenerator.errList.errGetContentFromBBArtifact=Blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u304b\u3089\u30ec\u30dd\u30fc\u30c8\u7528\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
ReportGenerator.errList.failedGetAbstractFileByID=ID\u306B\u57FA\u3065\u304D\u30A2\u30D6\u30B9\u30C8\u30E9\u30AF\u30C8\u30D5\u30A1\u30A4\u30EB\u3092\u53D6\u5F97\u3059\u308B\u306E\u3092\u5931\u6557\u3057\u307E\u3057\u305F ReportGenerator.errList.failedGetAbstractFileByID=ID\u306b\u57fa\u3065\u304d\u30a2\u30d6\u30b9\u30c8\u30e9\u30af\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3059\u308b\u306e\u3092\u5931\u6557\u3057\u307e\u3057\u305f
ReportGenerator.errList.failedGetBBArtifacts=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u4E2D\u306BBlackboard\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 ReportGenerator.errList.failedGetBBArtifacts=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306bBlackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
ReportGenerator.errList.failedGetBBArtifactTags=Blackboard\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30BF\u30B0\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 ReportGenerator.errList.failedGetBBArtifactTags=Blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30bf\u30b0\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
ReportGenerator.errList.failedGetBBAttribs=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u4E2D\u306BBlackboard\u5C5E\u6027\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 ReportGenerator.errList.failedGetBBAttribs=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306bBlackboard\u5c5e\u6027\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
ReportGenerator.errList.failedGetContentTags=\u30B3\u30F3\u30C6\u30F3\u30C4\u30BF\u30B0\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 ReportGenerator.errList.failedGetContentTags=\u30b3\u30f3\u30c6\u30f3\u30c4\u30bf\u30b0\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
ReportGenerator.errList.failedMakeRptFolder=\u30EC\u30DD\u30FC\u30C8\u30D5\u30A9\u30EB\u30C0\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u304C\u3067\u304D\u306A\u3044\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 ReportGenerator.errList.failedMakeRptFolder=\u30ec\u30dd\u30fc\u30c8\u30d5\u30a9\u30eb\u30c0\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u304c\u3067\u304d\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
ReportGenerator.errList.failedQueryHashsetHits=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u30D2\u30C3\u30C8\u3092\u30AF\u30A8\u30EA\u3059\u308B\u306E\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 ReportGenerator.errList.failedQueryHashsetHits=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30d2\u30c3\u30c8\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
ReportGenerator.errList.failedQueryHashsetLists=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u30EA\u30B9\u30C8\u3092\u30AF\u30A8\u30EA\u3059\u308B\u306E\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 ReportGenerator.errList.failedQueryHashsetLists=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30ea\u30b9\u30c8\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
ReportGenerator.errList.failedQueryKWLists=\u30AD\u30FC\u30EF\u30FC\u30C9\u30EA\u30B9\u30C8\u3092\u30AF\u30A8\u30EA\u3059\u308B\u306E\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 ReportGenerator.errList.failedQueryKWLists=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
ReportGenerator.errList.failedQueryKWs=\u30AD\u30FC\u30EF\u30FC\u30C9\u3092\u30AF\u30A8\u30EA\u3059\u308B\u306E\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 ReportGenerator.errList.failedQueryKWs=\u30ad\u30fc\u30ef\u30fc\u30c9\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
ReportGenerator.htmlOutput.header.comment=\u30B3\u30E1\u30F3\u30C8 ReportGenerator.htmlOutput.header.comment=\u30b3\u30e1\u30f3\u30c8
ReportGenerator.htmlOutput.header.file=\u30D5\u30A1\u30A4\u30EB ReportGenerator.htmlOutput.header.file=\u30d5\u30a1\u30a4\u30eb
ReportGenerator.htmlOutput.header.hash=\u30CF\u30C3\u30B7\u30E5 ReportGenerator.htmlOutput.header.hash=\u30cf\u30c3\u30b7\u30e5
ReportGenerator.htmlOutput.header.size=\u30B5\u30A4\u30BA\uFF08\u30D0\u30A4\u30C8\uFF09 ReportGenerator.htmlOutput.header.size=\u30b5\u30a4\u30ba\uff08\u30d0\u30a4\u30c8\uff09
ReportGenerator.htmlOutput.header.tag=\u30BF\u30B0 ReportGenerator.htmlOutput.header.tag=\u30bf\u30b0
ReportGenerator.htmlOutput.header.timeAccessed=\u30A2\u30AF\u30BB\u30B9\u65E5\u6642 ReportGenerator.htmlOutput.header.timeAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u6642
ReportGenerator.htmlOutput.header.timeChanged=\u5909\u66F4\u65E5\u6642 ReportGenerator.htmlOutput.header.timeCreated=\u4f5c\u6210\u65e5\u6642
ReportGenerator.htmlOutput.header.timeCreated=\u4F5C\u6210\u65E5\u6642 ReportGenerator.htmlOutput.header.timeModified=\u4fee\u6b63\u65e5\u6642
ReportGenerator.htmlOutput.header.timeModified=\u4FEE\u6B63\u65E5\u6642 ReportGenerator.notifyErr.errsDuringRptGen=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306e\u30a8\u30e9\u30fc\uff1a
ReportGenerator.notifyErr.errsDuringRptGen=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u4E2D\u306E\u30A8\u30E9\u30FC\uFF1A ReportGenerator.errList.failedGetAbstractFileFromID=ID\u306b\u57fa\u3065\u304d\u30a2\u30d6\u30b9\u30c8\u30e9\u30af\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3059\u308b\u306e\u3092\u5931\u6557\u3057\u307e\u3057\u305f
ReportGenerator.errList.failedGetAbstractFileFromID=ID\u306B\u57FA\u3065\u304D\u30A2\u30D6\u30B9\u30C8\u30E9\u30AF\u30C8\u30D5\u30A1\u30A4\u30EB\u3092\u53D6\u5F97\u3059\u308B\u306E\u3092\u5931\u6557\u3057\u307E\u3057\u305F ReportKML.getFilePath.text=\u30ec\u30dd\u30fc\u30c8KML.kml
ReportKML.getFilePath.text=\u30EC\u30DD\u30FC\u30C8KML.kml ReportVisualPanel1.invalidModuleWarning=\u7121\u52b9\u306a\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb({0})\u306b\u906d\u9047\u3057\u307e\u3057\u305f
ReportVisualPanel1.invalidModuleWarning=\u7121\u52B9\u306A\u30EC\u30DD\u30FC\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB({0})\u306B\u906D\u9047\u3057\u307E\u3057\u305F ReportGenerationPanel.confDlg.cancelReport.msg=\u672c\u5f53\u306b\u30ec\u30dd\u30fc\u30c8\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3059\u304b\uff1f
ReportGenerationPanel.confDlg.cancelReport.msg=\u672C\u5F53\u306B\u30EC\u30DD\u30FC\u30C8\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3059\u304B\uFF1F ReportProgressPanel.complete.processLb2.text=\u5b8c\u4e86\u3057\u307e\u3057\u305f\u304c\u3001\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
ReportProgressPanel.complete.processLb2.text=\u5B8C\u4E86\u3057\u307E\u3057\u305F\u304C\u3001\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F ReportGenerationPanel.cancelButton.actionCommand=\u30ad\u30e3\u30f3\u30bb\u30eb
ReportGenerationPanel.cancelButton.actionCommand=\u30AD\u30E3\u30F3\u30BB\u30EB ReportGenerationPanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb
ReportGenerationPanel.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB

View File

@ -26,22 +26,16 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="optionSeparator" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="reportScrollPane" max="32767" attributes="0"/>
<Component id="titleSeparator" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="titleLabel" min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="522" max="32767" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0">
</Group>
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="546" max="32767" attributes="0"/> <EmptySpace min="0" pref="546" max="32767" attributes="0"/>
<Component id="cancelButton" min="-2" max="-2" attributes="0"/> <Component id="cancelButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="closeButton" min="-2" max="-2" attributes="0"/> <Component id="closeButton" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Component id="reportPanel" alignment="0" pref="680" max="32767" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
@ -51,19 +45,13 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="titleLabel" min="-2" max="-2" attributes="0"/> <Component id="reportPanel" pref="344" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="titleSeparator" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="reportScrollPane" pref="290" max="32767" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="optionSeparator" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="closeButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="closeButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -102,25 +90,6 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
</Events> </Events>
</Component> </Component>
<Container class="javax.swing.JScrollPane" name="reportScrollPane">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.LineBorderInfo">
<LineBorder>
<Color PropertyName="color" blue="b4" green="b4" id="Active Caption Border" palette="2" red="b4" type="palette"/>
</LineBorder>
</Border>
</Property>
<Property name="verticalScrollBarPolicy" type="int" value="22"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="reportScrollPane" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="reportPanel"> <Container class="javax.swing.JPanel" name="reportPanel">
<Properties> <Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor"> <Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
@ -136,43 +105,15 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="661" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="400" max="32767" attributes="0"/> <EmptySpace min="0" pref="344" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
</Container> </Container>
</SubComponents> </SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="titleLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="true" component="titleLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportGenerationPanel.titleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSeparator" name="titleSeparator">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="0" type="rgb"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSeparator" name="optionSeparator">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="0" type="rgb"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form> </Form>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -20,69 +20,89 @@ package org.sleuthkit.autopsy.report;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import javax.swing.Box; import javax.swing.Box;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus; import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus;
/**
* A panel that displays a panel used by a report generation module to show
* progress. It provides OK and Cancel buttons.
*/
class ReportGenerationPanel extends javax.swing.JPanel { class ReportGenerationPanel extends javax.swing.JPanel {
private GridBagConstraints c; private static final long serialVersionUID = 1L;
ReportProgressPanel progressPanel; private final GridBagConstraints constraints;
private Component glue; private final Component glue;
private ActionListener actionListener; private ActionListener actionListener;
ReportProgressPanel progressPanel;
/** /**
* Creates new form ReportGenerationPanel * Constructs a panel that displays a panel used by a report generation
* module to show progress. It provides OK and Cancel buttons.
*/ */
public ReportGenerationPanel() { ReportGenerationPanel() {
initComponents(); initComponents();
customInit();
}
private void customInit() {
reportPanel.setLayout(new GridBagLayout()); reportPanel.setLayout(new GridBagLayout());
c = new GridBagConstraints(); constraints = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH; constraints.fill = GridBagConstraints.BOTH;
c.gridx = 0; constraints.gridx = 0;
c.gridy = 0; constraints.gridy = 0;
c.weightx = 1.0; constraints.weightx = 1.0;
glue = Box.createVerticalGlue(); glue = Box.createVerticalGlue();
} }
/** /**
* Add a ReportProgressPanel to this panel with the given report name and * Adds a panel used by a report generation module to show progress to this
* path. * panel.
* *
* @param reportName report name * @param reportName The report name.
* @param reportPath report path * @param reportPath The report file path
* *
* @return ReportProgressPanel progress panel to update * @return The report generation progress panel.
*/
ReportProgressPanel addReport(String reportName, String reportPath) {
/*
* Remove the "glue."
*/ */
public ReportProgressPanel addReport(String reportName, String reportPath) {
// Remove the glue
reportPanel.remove(glue); reportPanel.remove(glue);
progressPanel = new ReportProgressPanel(reportName, reportPath); progressPanel = new ReportProgressPanel(reportName, reportPath);
c.weighty = 0.0; constraints.weighty = 0.0;
c.anchor = GridBagConstraints.NORTH; constraints.anchor = GridBagConstraints.NORTH;
reportPanel.add(progressPanel, c); reportPanel.add(progressPanel, constraints);
c.gridy++; constraints.gridy++;
// Add the glue back to the bottom /*
c.weighty = 1.0; * Add the "glue" back to the bottom of the panel.
c.anchor = GridBagConstraints.PAGE_END; */
reportPanel.add(glue, c); constraints.weighty = 1.0;
constraints.anchor = GridBagConstraints.PAGE_END;
reportPanel.add(glue, constraints);
// 80 px per progressPanel. /*
* Use 80 pixels per progress panel. This is a leftover from when this
* panel used to show multiple report progress panels.
*/
reportPanel.setPreferredSize(new Dimension(600, 1 * 80)); reportPanel.setPreferredSize(new Dimension(600, 1 * 80));
reportPanel.repaint(); reportPanel.repaint();
progressPanel.addPropertyChangeListener((PropertyChangeEvent evt) -> {
String propName = evt.getPropertyName();
if (propName.equals(ReportProgressPanel.ReportStatus.COMPLETE.toString())
|| propName.equals(ReportProgressPanel.ReportStatus.CANCELED.toString())) {
SwingUtilities.invokeLater(() -> {
cancelButton.setEnabled(false);
});
}
});
return progressPanel; return progressPanel;
} }
/** /**
* Close this panel and it's dialog if all reports are done. * Closes this panel and its dialog if all reports are done.
*/ */
void close() { void close() {
boolean closeable = true; boolean closeable = true;
@ -105,6 +125,15 @@ class ReportGenerationPanel extends javax.swing.JPanel {
} }
} }
/**
* Adds a close action listener to this panel.
*
* @param listener The listener to add.
*/
void addCloseAction(ActionListener listener) {
this.actionListener = listener;
}
/** /**
* This method is called from within the constructor to initialize the form. * 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
@ -116,11 +145,7 @@ class ReportGenerationPanel extends javax.swing.JPanel {
closeButton = new javax.swing.JButton(); closeButton = new javax.swing.JButton();
cancelButton = new javax.swing.JButton(); cancelButton = new javax.swing.JButton();
reportScrollPane = new javax.swing.JScrollPane();
reportPanel = new javax.swing.JPanel(); reportPanel = new javax.swing.JPanel();
titleLabel = new javax.swing.JLabel();
titleSeparator = new javax.swing.JSeparator();
optionSeparator = new javax.swing.JSeparator();
setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11)); setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11));
setPreferredSize(new java.awt.Dimension(700, 400)); setPreferredSize(new java.awt.Dimension(700, 400));
@ -142,10 +167,6 @@ class ReportGenerationPanel extends javax.swing.JPanel {
} }
}); });
reportScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(java.awt.SystemColor.activeCaptionBorder));
reportScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
reportScrollPane.setFont(reportScrollPane.getFont().deriveFont(reportScrollPane.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
reportPanel.setFont(reportPanel.getFont().deriveFont(reportPanel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); reportPanel.setFont(reportPanel.getFont().deriveFont(reportPanel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
reportPanel.setPreferredSize(new java.awt.Dimension(600, 400)); reportPanel.setPreferredSize(new java.awt.Dimension(600, 400));
@ -153,53 +174,33 @@ class ReportGenerationPanel extends javax.swing.JPanel {
reportPanel.setLayout(reportPanelLayout); reportPanel.setLayout(reportPanelLayout);
reportPanelLayout.setHorizontalGroup( reportPanelLayout.setHorizontalGroup(
reportPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) reportPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 661, Short.MAX_VALUE) .addGap(0, 0, Short.MAX_VALUE)
); );
reportPanelLayout.setVerticalGroup( reportPanelLayout.setVerticalGroup(
reportPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) reportPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE) .addGap(0, 344, Short.MAX_VALUE)
); );
reportScrollPane.setViewportView(reportPanel);
titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getStyle() | java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(titleLabel, org.openide.util.NbBundle.getMessage(ReportGenerationPanel.class, "ReportGenerationPanel.titleLabel.text")); // NOI18N
titleSeparator.setForeground(new java.awt.Color(0, 0, 0));
optionSeparator.setForeground(new java.awt.Color(0, 0, 0));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(optionSeparator)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(reportScrollPane)
.addComponent(titleSeparator, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(titleLabel)
.addGap(0, 522, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 546, Short.MAX_VALUE) .addGap(0, 546, Short.MAX_VALUE)
.addComponent(cancelButton) .addComponent(cancelButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(closeButton))) .addComponent(closeButton))
.addComponent(reportPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 680, Short.MAX_VALUE))
.addContainerGap()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(titleLabel) .addComponent(reportPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 344, Short.MAX_VALUE)
.addGap(0, 0, 0)
.addComponent(titleSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(reportScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 290, Short.MAX_VALUE)
.addGap(18, 18, 18)
.addComponent(optionSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(closeButton) .addComponent(closeButton)
@ -225,17 +226,10 @@ class ReportGenerationPanel extends javax.swing.JPanel {
} }
}//GEN-LAST:event_cancelButtonActionPerformed }//GEN-LAST:event_cancelButtonActionPerformed
void addCloseAction(ActionListener l) {
this.actionListener = l;
}
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton cancelButton; private javax.swing.JButton cancelButton;
private javax.swing.JButton closeButton; private javax.swing.JButton closeButton;
private javax.swing.JSeparator optionSeparator;
private javax.swing.JPanel reportPanel; private javax.swing.JPanel reportPanel;
private javax.swing.JScrollPane reportScrollPane;
private javax.swing.JLabel titleLabel;
private javax.swing.JSeparator titleSeparator;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
} }

View File

@ -53,10 +53,12 @@ import javax.swing.SwingWorker;
import org.openide.filesystems.FileUtil; import org.openide.filesystems.FileUtil;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.EscapeUtil;
import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus; import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
@ -653,6 +655,18 @@ class ReportGenerator {
} }
ArrayList<String> rowData = new ArrayList<>(Arrays.asList(tag.getName().getDisplayName(), fileName, tag.getComment())); ArrayList<String> rowData = new ArrayList<>(Arrays.asList(tag.getName().getDisplayName(), fileName, tag.getComment()));
Content content = tag.getContent();
if (content instanceof AbstractFile) {
AbstractFile file = (AbstractFile) content;
// Add metadata about the file to HTML output
rowData.add(file.getMtimeAsDate());
rowData.add(file.getCtimeAsDate());
rowData.add(file.getAtimeAsDate());
rowData.add(file.getCrtimeAsDate());
rowData.add(Long.toString(file.getSize()));
rowData.add(file.getMd5Hash());
}
for (TableReportModule module : tableModules) { for (TableReportModule module : tableModules) {
// @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink. // @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink.
if (module instanceof ReportHTML) { if (module instanceof ReportHTML) {
@ -684,6 +698,7 @@ class ReportGenerator {
NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"), NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"),
NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(), NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(),
MessageNotifyUtil.MessageType.ERROR); MessageNotifyUtil.MessageType.ERROR);
logger.log(Level.SEVERE, "failed to generate reports", ex.getCause()); //NON-NLS
logger.log(Level.SEVERE, "failed to generate reports", ex); //NON-NLS logger.log(Level.SEVERE, "failed to generate reports", ex); //NON-NLS
} // catch and ignore if we were cancelled } // catch and ignore if we were cancelled
catch (java.util.concurrent.CancellationException ex) { catch (java.util.concurrent.CancellationException ex) {
@ -1759,11 +1774,10 @@ class ReportGenerator {
* *
* @return String unique path * @return String unique path
*/ */
private String getFileUniquePath(long objId) { private String getFileUniquePath(Content content) {
try { try {
AbstractFile af = skCase.getAbstractFileById(objId); if (content != null) {
if (af != null) { return content.getUniquePath();
return af.getUniquePath();
} else { } else {
return ""; return "";
} }
@ -1785,11 +1799,17 @@ class ReportGenerator {
private List<BlackboardAttribute> attributes; private List<BlackboardAttribute> attributes;
private HashSet<String> tags; private HashSet<String> tags;
private List<String> rowData = null; private List<String> rowData = null;
private Content content;
ArtifactData(BlackboardArtifact artifact, List<BlackboardAttribute> attrs, HashSet<String> tags) { ArtifactData(BlackboardArtifact artifact, List<BlackboardAttribute> attrs, HashSet<String> tags) {
this.artifact = artifact; this.artifact = artifact;
this.attributes = attrs; this.attributes = attrs;
this.tags = tags; this.tags = tags;
try {
this.content = Case.getCurrentCase().getSleuthkitCase().getContentById(artifact.getObjectID());
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Could not get content from database");
}
} }
public BlackboardArtifact getArtifact() { public BlackboardArtifact getArtifact() {
@ -1812,6 +1832,13 @@ class ReportGenerator {
return artifact.getObjectID(); return artifact.getObjectID();
} }
/**
* @return the content
*/
public Content getContent() {
return content;
}
/** /**
* Compares ArtifactData objects by the first attribute they have in * Compares ArtifactData objects by the first attribute they have in
* common in their List<BlackboardAttribute>. Should only be used on two * common in their List<BlackboardAttribute>. Should only be used on two
@ -1881,8 +1908,8 @@ class ReportGenerator {
List<String> orderedRowData = new ArrayList<>(); List<String> orderedRowData = new ArrayList<>();
if (ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID() == getArtifact().getArtifactTypeID()) { if (ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID() == getArtifact().getArtifactTypeID()) {
AbstractFile file = skCase.getAbstractFileById(getObjectID()); if (content != null && content instanceof AbstractFile) {
if (file != null) { AbstractFile file = (AbstractFile) content;
orderedRowData.add(file.getName()); orderedRowData.add(file.getName());
orderedRowData.add(file.getNameExtension()); orderedRowData.add(file.getNameExtension());
String mimeType = file.getMIMEType(); String mimeType = file.getMIMEType();
@ -1913,7 +1940,7 @@ class ReportGenerator {
} else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))) { } else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))) {
String pathToShow = attr.getDisplayString(); String pathToShow = attr.getDisplayString();
if (pathToShow.isEmpty()) { if (pathToShow.isEmpty()) {
pathToShow = getFileUniquePath(getObjectID()); pathToShow = getFileUniquePath(content);
} }
attributeDataArray[2] = pathToShow; attributeDataArray[2] = pathToShow;
} }
@ -1933,6 +1960,7 @@ class ReportGenerator {
return orderedRowData; return orderedRowData;
} }
} }
/** /**
@ -1999,7 +2027,11 @@ class ReportGenerator {
List<BlackboardAttribute> attributes = artData.getAttributes(); List<BlackboardAttribute> attributes = artData.getAttributes();
for (BlackboardAttribute attribute : attributes) { for (BlackboardAttribute attribute : attributes) {
if (attribute.getAttributeType().equals(this.attributeType)) { if (attribute.getAttributeType().equals(this.attributeType)) {
if (attribute.getAttributeType().getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
return attribute.getDisplayString(); return attribute.getDisplayString();
} else {
return ContentUtils.getStringTime(attribute.getValueLong(), artData.getContent());
}
} }
} }
return ""; return "";
@ -2027,7 +2059,7 @@ class ReportGenerator {
@Override @Override
public String getCellData(ArtifactData artData) { public String getCellData(ArtifactData artData) {
return getFileUniquePath(artData.getObjectID()); return getFileUniquePath(artData.getContent());
/*else if (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))) { /*else if (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))) {
return makeCommaSeparatedList(artData.getTags()); return makeCommaSeparatedList(artData.getTags());
} }

View File

@ -560,15 +560,6 @@ class ReportHTML implements TableReportModule {
return; return;
} }
AbstractFile file = (AbstractFile) content; AbstractFile file = (AbstractFile) content;
// Add metadata about the file to HTML output
row.add(file.getMtimeAsDate());
row.add(file.getCtimeAsDate());
row.add(file.getAtimeAsDate());
row.add(file.getCrtimeAsDate());
row.add(Long.toString(file.getSize()));
row.add(file.getMd5Hash());
// Add the hyperlink to the row. A column header for it was created in startTable(). // Add the hyperlink to the row. A column header for it was created in startTable().
StringBuilder localFileLink = new StringBuilder(); StringBuilder localFileLink = new StringBuilder();
// Don't make a local copy of the file if it is a directory or unallocated space. // Don't make a local copy of the file if it is a directory or unallocated space.

View File

@ -29,11 +29,8 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="processingLabel" max="32767" attributes="0"/> <Component id="statusMessageLabel" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <Component id="reportProgressBar" alignment="0" max="32767" attributes="0"/>
<Component id="reportProgressBar" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="58" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="reportLabel" min="-2" max="-2" attributes="0"/> <Component id="reportLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
@ -49,17 +46,17 @@
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="reportProgressBar" min="-2" pref="16" max="-2" attributes="0"/> <Component id="reportProgressBar" min="-2" pref="16" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="reportLabel" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="reportLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="pathLabel" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="pathLabel" alignment="3" max="32767" attributes="0"/>
<Component id="separationLabel" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="separationLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="processingLabel" min="-2" max="-2" attributes="0"/> <Component id="statusMessageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="20" max="32767" attributes="0"/> <EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -96,18 +93,7 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportProgressPanel.pathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportProgressPanel.pathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> <Property name="verticalAlignment" type="int" value="1"/>
</Component>
<Component class="javax.swing.JLabel" name="processingLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="processingLabel" italic="true" property="font" relativeSize="false" size="10"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportProgressPanel.processingLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="separationLabel"> <Component class="javax.swing.JLabel" name="separationLabel">
@ -122,5 +108,12 @@
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="statusMessageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportProgressPanel.statusMessageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,22 +19,32 @@
package org.sleuthkit.autopsy.report; package org.sleuthkit.autopsy.report;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import java.awt.*; import java.awt.*;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
/**
* A panel used by a report generation module to show progress.
*/
public class ReportProgressPanel extends javax.swing.JPanel { public class ReportProgressPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(ReportProgressPanel.class.getName()); private static final Logger logger = Logger.getLogger(ReportProgressPanel.class.getName());
private ReportStatus STATUS; private static final Color GREEN = new Color(50, 205, 50);
private static final Color RED = new Color(178, 34, 34);
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private ReportStatus status;
// Enum to represent if a report is waiting, /**
// running, done, or has been canceled * Used by a report generation module to communicate report generation
* status to this panel and its listeners.
*/
public enum ReportStatus { public enum ReportStatus {
QUEUING, QUEUING,
@ -45,64 +55,60 @@ public class ReportProgressPanel extends javax.swing.JPanel {
} }
/** /**
* Creates new form ReportProgressPanel * Constructs a panel used by report generation module to show progress.
*
* @param reportName The name of the report being generated.
* @param reportPath The path to the report file.
*/ */
public ReportProgressPanel(String reportName, String reportPath) { public ReportProgressPanel(String reportName, String reportPath) {
initComponents(); initComponents();
customInit(reportName, reportPath);
}
private void customInit(String reportName, String reportPath) {
reportProgressBar.setIndeterminate(true); reportProgressBar.setIndeterminate(true);
reportProgressBar.setMaximum(100); reportProgressBar.setMaximum(100);
reportLabel.setText(reportName); reportLabel.setText(reportName);
processingLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.progress.queuing")); statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.progress.queuing"));
STATUS = ReportStatus.QUEUING; status = ReportStatus.QUEUING;
if (null != reportPath) {
if (reportPath != null) {
pathLabel.setText("<html><u>" + shortenPath(reportPath) + "</u></html>"); //NON-NLS pathLabel.setText("<html><u>" + shortenPath(reportPath) + "</u></html>"); //NON-NLS
pathLabel.setToolTipText(reportPath); pathLabel.setToolTipText(reportPath);
String linkPath = reportPath;
// Add the "link" effect to the pathLabel
final String linkPath = reportPath;
pathLabel.addMouseListener(new MouseListener() { pathLabel.addMouseListener(new MouseListener() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent mouseEvent) {
} }
@Override @Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent mouseEvent) {
} }
@Override @Override
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent mouseEvent) {
File file = new File(linkPath); File file = new File(linkPath);
try { try {
Desktop.getDesktop().open(file); Desktop.getDesktop().open(file);
} catch (IOException ex) { } catch (IOException ioex) {
} catch (IllegalArgumentException ex) { logger.log(Level.SEVERE, "Error opening report file", ioex);
} catch (IllegalArgumentException iaEx) {
logger.log(Level.SEVERE, "Error opening report file", iaEx);
try { try {
// try to open the parent path if the file doens't exist
Desktop.getDesktop().open(file.getParentFile()); Desktop.getDesktop().open(file.getParentFile());
} catch (IOException ex1) { } catch (IOException ioEx2) {
logger.log(Level.SEVERE, "Error opening report file parent", ioEx2);
} }
} }
} }
@Override @Override
public void mouseEntered(MouseEvent e) { public void mouseEntered(MouseEvent e3) {
pathLabel.setForeground(Color.DARK_GRAY); pathLabel.setForeground(Color.DARK_GRAY);
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
} }
@Override @Override
public void mouseExited(MouseEvent e) { public void mouseExited(MouseEvent e4) {
pathLabel.setForeground(Color.BLACK); pathLabel.setForeground(Color.BLACK);
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} }
}); });
} else { } else {
pathLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.initPathLabel.noFile")); pathLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.initPathLabel.noFile"));
@ -110,185 +116,196 @@ public class ReportProgressPanel extends javax.swing.JPanel {
} }
/** /**
* Return a shortened version of the given path. * Adds a property change listener to this panel.
*
* @param listener The listener to be added.
*/ */
private String shortenPath(String path) { @Override
if (path.length() > 100) { public void addPropertyChangeListener(PropertyChangeListener listener) {
path = path.substring(0, 10 + path.substring(10).indexOf(File.separator) + 1) + "..." this.pcs.addPropertyChangeListener(listener);
+ path.substring((path.length() - 70) + path.substring(path.length() - 70).indexOf(File.separator));
}
return path;
} }
/** /**
* Return the current ReportStatus of this report. * Removes a property change listener from this panel.
* *
* @return ReportStatus status of this report * @param listener The listener to be removed.
*/
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
this.pcs.removePropertyChangeListener(listener);
}
/**
* Gets the current status of the generation of the report.
*
* @return The report generation status as a ReportStatus enum.
*/ */
public ReportStatus getStatus() { public ReportStatus getStatus() {
return STATUS; return status;
} }
/** /**
* Start the JProgressBar for this report. * Starts the progress bar component of this panel.
*
* Enables the cancelButton, updates the processingLabel, and changes this
* report's ReportStatus.
*/ */
public void start() { public void start() {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(() -> {
@Override statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.start.progress.text"));
public void run() { status = ReportStatus.RUNNING;
processingLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.start.progress.text"));
STATUS = ReportStatus.RUNNING;
}
}); });
} }
/** /**
* Set the maximum progress for this report's JProgressBar. * Sets the maximum value of the progress bar component of this panel.
* *
* @param max maximum progress for JProgressBar * @param max The maximum value.
*/ */
public void setMaximumProgress(final int max) { public void setMaximumProgress(int max) {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(() -> {
@Override if (status != ReportStatus.CANCELED) {
public void run() {
if (STATUS != ReportStatus.CANCELED) {
reportProgressBar.setMaximum(max); reportProgressBar.setMaximum(max);
} }
}
}); });
} }
/** /**
* Increment the JProgressBar for this report by one unit. * Increments the current value of the progress bar component of this panel
* by one unit.
*/ */
public void increment() { public void increment() {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(() -> {
@Override if (status != ReportStatus.CANCELED) {
public void run() {
if (STATUS != ReportStatus.CANCELED) {
reportProgressBar.setValue(reportProgressBar.getValue() + 1); reportProgressBar.setValue(reportProgressBar.getValue() + 1);
} }
}
}); });
} }
/** /**
* Set the value of the JProgressBar for this report. * Sets the current value of the progress bar component of this panel.
* *
* @param value value to be set at * @param value The value to be set.
*/ */
public void setProgress(final int value) { public void setProgress(int value) {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(() -> {
@Override if (status != ReportStatus.CANCELED) {
public void run() {
if (STATUS != ReportStatus.CANCELED) {
reportProgressBar.setValue(value); reportProgressBar.setValue(value);
} }
}
}); });
} }
/** /**
* Changes the status of the JProgressBar to be determinate or * Changes the the progress bar component of this panel to be determinate or
* indeterminate. * indeterminate.
* *
* @param indeterminate sets the JProgressBar to be indeterminate if true, * @param indeterminate True if the progress bar should be set to
* determinate otherwise * indeterminate.
*/ */
public void setIndeterminate(final boolean indeterminate) { public void setIndeterminate(boolean indeterminate) {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(() -> {
@Override if (status != ReportStatus.CANCELED) {
public void run() {
if (STATUS != ReportStatus.CANCELED) {
reportProgressBar.setIndeterminate(indeterminate); reportProgressBar.setIndeterminate(indeterminate);
} }
});
}
/**
* Changes the status message label component of this panel to show a given
* processing status message. For example, updateStatusLabel("Now processing
* files...") sets the label text to "Now processing files..."
*
* @param statusMessage String to use as label text.
*/
public void updateStatusLabel(String statusMessage) {
EventQueue.invokeLater(() -> {
if (status != ReportStatus.CANCELED) {
statusMessageLabel.setText(statusMessage);
} }
}); });
} }
/** /**
* Change the text of this report's status label. The text given will be the * Makes the components of this panel indicate the final status of
* full text used. e.g. updateStatusLabel("Now processing files...") sets * generation of the report.
* the label to "Now processing files..."
* *
* @param status String to use as status * @param reportStatus The final status, must be COMPLETE or ERROR.
*/
public void updateStatusLabel(final String status) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (STATUS != ReportStatus.CANCELED) {
processingLabel.setText(status);
}
}
});
}
/**
* Declare the report completed. This will fill the JProgressBar, update the
* cancelButton to completed, and disallow any cancellation of this report.
*
* @deprecated Use {@link #complete(ReportStatus)}
*/
@Deprecated
public void complete() {
complete(ReportStatus.COMPLETE);
}
/**
* Declare the report completed ands sets if completed successfully or with
* errors. This will fill the JProgressBar, update the cancelButton to
* completed, and disallow any cancellation of this report.
*
* @param reportStatus set to appropriate ResultStatus enum.
*/ */
public void complete(ReportStatus reportStatus) { public void complete(ReportStatus reportStatus) {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(() -> {
@Override
public void run() {
// make sure we disable an indeterminate
reportProgressBar.setIndeterminate(false); reportProgressBar.setIndeterminate(false);
if (status != ReportStatus.CANCELED) {
if (STATUS != ReportStatus.CANCELED) {
switch (reportStatus) { switch (reportStatus) {
case COMPLETE: { case COMPLETE: {
STATUS = ReportStatus.COMPLETE; ReportStatus oldValue = status;
processingLabel.setForeground(Color.BLACK); status = ReportStatus.COMPLETE;
processingLabel.setText( statusMessageLabel.setForeground(Color.BLACK);
NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLbl.text")); statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLbl.text"));
reportProgressBar.setValue(reportProgressBar.getMaximum()); reportProgressBar.setValue(reportProgressBar.getMaximum());
reportProgressBar.setStringPainted(true); reportProgressBar.setStringPainted(true);
// set reportProgressBar color as green. reportProgressBar.setForeground(GREEN);
reportProgressBar.setForeground(new Color(50, 205, 50));
reportProgressBar.setString("Complete"); //NON-NLS reportProgressBar.setString("Complete"); //NON-NLS
pcs.firePropertyChange(ReportStatus.COMPLETE.toString(), oldValue, status);
break; break;
} }
case ERROR: { case ERROR: {
STATUS = ReportStatus.ERROR; ReportStatus oldValue = status;
processingLabel.setForeground(new Color(178, 34, 34)); status = ReportStatus.ERROR;
processingLabel.setText( statusMessageLabel.setForeground(RED);
NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLb2.text")); statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLb2.text"));
reportProgressBar.setValue(reportProgressBar.getMaximum()); reportProgressBar.setValue(reportProgressBar.getMaximum());
reportProgressBar.setStringPainted(true); reportProgressBar.setStringPainted(true);
// set reportProgressBar color as red. reportProgressBar.setForeground(RED);
reportProgressBar.setForeground(new Color(178, 34, 34));
reportProgressBar.setString("Error"); //NON-NLS reportProgressBar.setString("Error"); //NON-NLS
pcs.firePropertyChange(ReportStatus.COMPLETE.toString(), oldValue, status);
break; break;
} }
// add finer grained result codes here.
default: { default: {
logger.log(Level.SEVERE, "Invalid ReportStatus code {0}", reportStatus); //NON-NLS
break; break;
} }
} }
} }
}
}); });
// Do something with the button to change the icon and make not clickable }
/**
* Makes the components of this panel indicate generation of the report was
* cancelled.
*/
void cancel() {
switch (status) {
case COMPLETE:
break;
case CANCELED:
break;
case ERROR:
break;
default:
ReportStatus oldValue = status;
status = ReportStatus.CANCELED;
reportProgressBar.setIndeterminate(false);
reportProgressBar.setValue(0);
reportProgressBar.setStringPainted(true);
reportProgressBar.setForeground(RED); // Red
reportProgressBar.setString("Cancelled"); //NON-NLS
pcs.firePropertyChange(ReportStatus.CANCELED.toString(), oldValue, status);
statusMessageLabel.setForeground(RED);
statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.cancel.procLbl.text"));
break;
}
}
/**
* Gets a shortened version of a file path.
*
* @param path The path to shorten.
*
* @return The shortened path.
*/
private String shortenPath(String path) {
if (path.length() > 100) {
return path.substring(0, 10 + path.substring(10).indexOf(File.separator) + 1) + "..."
+ path.substring((path.length() - 70) + path.substring(path.length() - 70).indexOf(File.separator));
} else {
return path;
}
} }
/** /**
@ -303,8 +320,8 @@ public class ReportProgressPanel extends javax.swing.JPanel {
reportProgressBar = new javax.swing.JProgressBar(); reportProgressBar = new javax.swing.JProgressBar();
reportLabel = new javax.swing.JLabel(); reportLabel = new javax.swing.JLabel();
pathLabel = new javax.swing.JLabel(); pathLabel = new javax.swing.JLabel();
processingLabel = new javax.swing.JLabel();
separationLabel = new javax.swing.JLabel(); separationLabel = new javax.swing.JLabel();
statusMessageLabel = new javax.swing.JLabel();
setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11)); setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11));
setMinimumSize(new java.awt.Dimension(486, 68)); setMinimumSize(new java.awt.Dimension(486, 68));
@ -316,13 +333,13 @@ public class ReportProgressPanel extends javax.swing.JPanel {
pathLabel.setFont(pathLabel.getFont().deriveFont(pathLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); pathLabel.setFont(pathLabel.getFont().deriveFont(pathLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.pathLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.pathLabel.text")); // NOI18N
pathLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
processingLabel.setFont(processingLabel.getFont().deriveFont((processingLabel.getFont().getStyle() | java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, 10));
org.openide.awt.Mnemonics.setLocalizedText(processingLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.processingLabel.text")); // NOI18N
separationLabel.setFont(separationLabel.getFont().deriveFont(separationLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); separationLabel.setFont(separationLabel.getFont().deriveFont(separationLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(separationLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.separationLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(separationLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.separationLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(statusMessageLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.statusMessageLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
@ -330,10 +347,8 @@ public class ReportProgressPanel extends javax.swing.JPanel {
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(processingLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(statusMessageLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(reportProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(reportProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(58, 58, 58))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(reportLabel) .addComponent(reportLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -350,45 +365,32 @@ public class ReportProgressPanel extends javax.swing.JPanel {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(reportLabel) .addComponent(reportLabel)
.addComponent(pathLabel) .addComponent(pathLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(separationLabel)) .addComponent(separationLabel))
.addGap(0, 0, 0) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(processingLabel) .addComponent(statusMessageLabel)
.addContainerGap(20, Short.MAX_VALUE)) .addGap(13, 13, 13))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
/**
* Cancels the current report, based on it's status. If the report is
* complete or has already been completed, nothing happens.
*/
void cancel() {
switch (STATUS) {
case COMPLETE:
break;
case CANCELED:
break;
case ERROR:
break;
default:
STATUS = ReportStatus.CANCELED;
reportProgressBar.setIndeterminate(false);
reportProgressBar.setValue(0);
reportProgressBar.setStringPainted(true);
// set reportProgressBar color as red.
reportProgressBar.setForeground(new Color(178, 34, 34));
reportProgressBar.setString("Cancelled"); //NON-NLS
processingLabel.setForeground(new Color(178, 34, 34));
processingLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.cancel.procLbl.text"));
break;
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel pathLabel; private javax.swing.JLabel pathLabel;
private javax.swing.JLabel processingLabel;
private javax.swing.JLabel reportLabel; private javax.swing.JLabel reportLabel;
private javax.swing.JProgressBar reportProgressBar; private javax.swing.JProgressBar reportProgressBar;
private javax.swing.JLabel separationLabel; private javax.swing.JLabel separationLabel;
private javax.swing.JLabel statusMessageLabel;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
/**
* Makes the components of this panel indicate the generation of the report
* is completed.
*
* @deprecated Use {@link #complete(ReportStatus)}
*/
@Deprecated
public void complete() {
complete(ReportStatus.COMPLETE);
}
} }

View File

@ -1,4 +1,4 @@
CTL_MakeTimeline="Timeline" CTL_MakeTimeline=Timeline
CTL_TimeLineTopComponentAction=TimeLineTopComponent CTL_TimeLineTopComponentAction=TimeLineTopComponent
CTL_TimeLineTopComponent=Timeline Window CTL_TimeLineTopComponent=Timeline Window
HINT_TimeLineTopComponent=This is a Timeline window HINT_TimeLineTopComponent=This is a Timeline window
@ -24,7 +24,5 @@ TimelinePanel.jButton7.text=3d
TimelinePanel.jButton2.text=1m TimelinePanel.jButton2.text=1m
TimelinePanel.jButton3.text=3m TimelinePanel.jButton3.text=3m
TimelinePanel.jButton4.text=2w TimelinePanel.jButton4.text=2w
OpenTimelineAction.title=Timeline
OpenTimeLineAction.msgdlg.text=Could not create timeline, there are no data sources.
ProgressWindow.progressHeader.text=\ ProgressWindow.progressHeader.text=\

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013 Basis Technology Corp. * Copyright 2013-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,8 +18,8 @@
*/ */
package org.sleuthkit.autopsy.timeline; package org.sleuthkit.autopsy.timeline;
import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JOptionPane;
import org.openide.awt.ActionID; import org.openide.awt.ActionID;
import org.openide.awt.ActionReference; import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences; import org.openide.awt.ActionReferences;
@ -27,10 +27,10 @@ import org.openide.awt.ActionRegistration;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.Installer; import org.sleuthkit.autopsy.core.Installer;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.timeline.Timeline") @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.timeline.Timeline")
@ -58,35 +58,39 @@ public class OpenTimelineAction extends CallableSystemAction {
return Case.isCaseOpen() && fxInited;// && Case.getCurrentCase().hasData(); return Case.isCaseOpen() && fxInited;// && Case.getCurrentCase().hasData();
} }
@NbBundle.Messages({
"OpenTimelineAction.settingsErrorMessage=Failed to initialize timeline settings.",
"OpenTimeLineAction.msgdlg.text=Could not create timeline, there are no data sources."})
@Override @Override
@ThreadConfined(type = ThreadConfined.ThreadType.AWT) @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
public void performAction() { public void performAction() {
//check case try {
if (!Case.isCaseOpen()) { Case currentCase = Case.getCurrentCase();
return;
}
final Case currentCase = Case.getCurrentCase();
if (currentCase.hasData() == false) { if (currentCase.hasData() == false) {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), MessageNotifyUtil.Message.info(Bundle.OpenTimeLineAction_msgdlg_text());
NbBundle.getMessage(this.getClass(), "OpenTimeLineAction.msgdlg.text"));
LOGGER.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS LOGGER.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS
return; return;
} }
try {
if (timeLineController == null) { if (timeLineController == null) {
timeLineController = new TimeLineController(currentCase); timeLineController = new TimeLineController(currentCase);
} else if (timeLineController.getAutopsyCase() != currentCase) { } else if (timeLineController.getAutopsyCase() != currentCase) {
timeLineController.closeTimeLine(); timeLineController.shutDownTimeLine();
timeLineController = new TimeLineController(currentCase); timeLineController = new TimeLineController(currentCase);
} }
timeLineController.openTimeLine(); timeLineController.openTimeLine();
} catch (IOException iOException) {
MessageNotifyUtil.Message.error(Bundle.OpenTimelineAction_settingsErrorMessage());
LOGGER.log(Level.SEVERE, "Failed to initialize per case timeline settings.", iOException);
}
} catch (IllegalStateException e) {
//there is no case... Do nothing.
}
} }
@Override @Override
public String getName() { public String getName() {
return NbBundle.getMessage(TimeLineTopComponent.class, "OpenTimelineAction.title"); return NbBundle.getMessage(OpenTimelineAction.class, "CTL_MakeTimeline");
} }
@Override @Override

View File

@ -0,0 +1,177 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.timeline;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.casemodule.Case;
/**
* Provides access to per-case timeline properties (key-value store).
*/
class PerCaseTimelineProperties {
private static final String STALE_KEY = "stale"; //NON-NLS
private static final String WAS_INGEST_RUNNING_KEY = "was_ingest_running"; // NON-NLS
private final Case autoCase;
private final Path propertiesPath;
PerCaseTimelineProperties(Case c) {
Objects.requireNonNull(c, "Case must not be null");
this.autoCase = c;
propertiesPath = Paths.get(autoCase.getModuleDirectory(), "Timeline", "timeline.properties"); //NON-NLS
}
/**
* Is the DB stale, i.e. does it need to be updated because new datasources
* (eg) have been added to the case.
*
* @return true if the db is stale
*
* @throws IOException if there is a problem reading the state from disk
*/
public synchronized boolean isDBStale() throws IOException {
String stale = getProperty(STALE_KEY);
return StringUtils.isBlank(stale) ? true : Boolean.valueOf(stale);
}
/**
* record the state of the events db as stale(true) or not stale(false).
*
* @param stale the new state of the event db. true for stale, false for not
* stale.
*
* @throws IOException if there was a problem writing the state to disk.
*/
public synchronized void setDbStale(Boolean stale) throws IOException {
setProperty(STALE_KEY, stale.toString());
}
/**
* Was ingest running the last time the database was updated?
*
* @return true if ingest was running the last time the db was updated
*
* @throws IOException if there was a problem reading from disk
*/
public synchronized boolean wasIngestRunning() throws IOException {
String stale = getProperty(WAS_INGEST_RUNNING_KEY);
return StringUtils.isBlank(stale) ? true : Boolean.valueOf(stale);
}
/**
* record whether ingest was running during the last time the database was
* updated
*
* @param ingestRunning true if ingest was running
*
* @throws IOException if there was a problem writing to disk
*/
public synchronized void setIngestRunning(Boolean ingestRunning) throws IOException {
setProperty(WAS_INGEST_RUNNING_KEY, ingestRunning.toString());
}
/**
* Get a {@link Path} to the properties file. If the file does not exist, it
* will be created.
*
* @return the Path to the properties file.
*
* @throws IOException if there was a problem creating the properties file
*/
private synchronized Path getPropertiesPath() throws IOException {
if (!Files.exists(propertiesPath)) {
Path parent = propertiesPath.getParent();
Files.createDirectories(parent);
Files.createFile(propertiesPath);
}
return propertiesPath;
}
/**
* Returns the property with the given key.
*
* @param propertyKey - The property key to get the value for.
*
* @return - the value associated with the property.
*
* @throws IOException if there was a problem reading the property from disk
*/
private synchronized String getProperty(String propertyKey) throws IOException {
return getProperties().getProperty(propertyKey);
}
/**
* Sets the given property to the given value.
*
* @param propertyKey - The key of the property to be modified.
* @param propertyValue - the value to set the property to.
*
* @throws IOException if there was a problem writing the property to disk
*/
private synchronized void setProperty(String propertyKey, String propertyValue) throws IOException {
Path propertiesFile = getPropertiesPath();
Properties props = getProperties(propertiesFile);
props.setProperty(propertyKey, propertyValue);
try (OutputStream fos = Files.newOutputStream(propertiesFile)) {
props.store(fos, ""); //NON-NLS
}
}
/**
* Get a {@link Properties} object used to store the timeline properties.
*
* @return a properties object
*
* @throws IOException if there was a problem reading the .properties file
*/
private synchronized Properties getProperties() throws IOException {
return getProperties(getPropertiesPath());
}
/**
* Gets a {@link Properties} object populated form the given .properties
* file.
*
* @param propertiesFile a path to the .properties file to load
*
* @return a properties object
*
* @throws IOException if there was a problem reading the .properties file
*/
private synchronized Properties getProperties(final Path propertiesFile) throws IOException {
try (InputStream inputStream = Files.newInputStream(propertiesFile)) {
Properties props = new Properties();
props.load(inputStream);
return props;
}
}
}

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2015-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -61,9 +61,9 @@ public class PromptDialogManager {
static { static {
Image x = null; Image x = null;
try { try {
x = new Image(new URL("nbresloc:/org/netbeans/core/startup/frame.gif").openStream()); //NOI18N x = new Image(new URL("nbresloc:/org/netbeans/core/startup/frame.gif").openStream()); //NON-NLS
} catch (IOException ex) { } catch (IOException ex) {
LOGGER.log(Level.WARNING, "Failed to load branded icon for progress dialog.", ex); //NOI18N NON-NLS LOGGER.log(Level.WARNING, "Failed to load branded icon for progress dialog.", ex); //NON-NLS
} }
LOGO = x; LOGO = x;
} }
@ -75,6 +75,12 @@ public class PromptDialogManager {
this.controller = controller; this.controller = controller;
} }
/**
* bring the currently managed dialog (if there is one) to the front
*
* @return true if a dialog was brought to the front, or false of there is
* no currently managed open dialog
*/
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
boolean bringCurrentDialogToFront() { boolean bringCurrentDialogToFront() {
if (currentDialog != null && currentDialog.isShowing()) { if (currentDialog != null && currentDialog.isShowing()) {
@ -86,11 +92,12 @@ public class PromptDialogManager {
@NbBundle.Messages({"PromptDialogManager.progressDialog.title=Populating Timeline Data"}) @NbBundle.Messages({"PromptDialogManager.progressDialog.title=Populating Timeline Data"})
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
public void showProgressDialog(CancellationProgressTask<?> task) { void showProgressDialog(CancellationProgressTask<?> task) {
currentDialog = new ProgressDialog(task); currentDialog = new ProgressDialog(task);
currentDialog.headerTextProperty().bind(task.titleProperty()); currentDialog.initModality(Modality.NONE);
setDialogIcons(currentDialog);
currentDialog.setTitle(Bundle.PromptDialogManager_progressDialog_title()); currentDialog.setTitle(Bundle.PromptDialogManager_progressDialog_title());
setDialogIcons(currentDialog);
currentDialog.headerTextProperty().bind(task.titleProperty());
DialogPane dialogPane = currentDialog.getDialogPane(); DialogPane dialogPane = currentDialog.getDialogPane();
dialogPane.setPrefSize(400, 200); //override autosizing which fails for some reason dialogPane.setPrefSize(400, 200); //override autosizing which fails for some reason
@ -98,6 +105,8 @@ public class PromptDialogManager {
//co-ordinate task cancelation and dialog hiding. //co-ordinate task cancelation and dialog hiding.
task.setOnCancelled(cancelled -> currentDialog.close()); task.setOnCancelled(cancelled -> currentDialog.close());
task.setOnSucceeded(succeeded -> currentDialog.close()); task.setOnSucceeded(succeeded -> currentDialog.close());
task.setOnFailed(failed -> currentDialog.close());
dialogPane.getButtonTypes().setAll(ButtonType.CANCEL); dialogPane.getButtonTypes().setAll(ButtonType.CANCEL);
final Node cancelButton = dialogPane.lookupButton(ButtonType.CANCEL); final Node cancelButton = dialogPane.lookupButton(ButtonType.CANCEL);
cancelButton.disableProperty().bind(task.cancellableProperty().not()); cancelButton.disableProperty().bind(task.cancellableProperty().not());
@ -115,14 +124,7 @@ public class PromptDialogManager {
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
static private void setDialogIcons(Dialog<?> dialog) { static private void setDialogIcons(Dialog<?> dialog) {
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow(); ((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().setAll(LOGO);
stage.getIcons().setAll(LOGO);
}
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
static private void setDialogTitle(Dialog<?> dialog) {
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
stage.setTitle(Bundle.Timeline_confirmation_dialogs_title());
} }
/** /**
@ -139,7 +141,7 @@ public class PromptDialogManager {
currentDialog.initModality(Modality.APPLICATION_MODAL); currentDialog.initModality(Modality.APPLICATION_MODAL);
currentDialog.setHeaderText(Bundle.PromptDialogManager_confirmDuringIngest_headerText()); currentDialog.setHeaderText(Bundle.PromptDialogManager_confirmDuringIngest_headerText());
setDialogIcons(currentDialog); setDialogIcons(currentDialog);
setDialogTitle(currentDialog); currentDialog.setTitle(Bundle.Timeline_confirmation_dialogs_title());
return currentDialog.showAndWait().map(SHOW_TIMELINE::equals).orElse(false); return currentDialog.showAndWait().map(SHOW_TIMELINE::equals).orElse(false);
} }
@ -152,7 +154,7 @@ public class PromptDialogManager {
currentDialog.initModality(Modality.APPLICATION_MODAL); currentDialog.initModality(Modality.APPLICATION_MODAL);
currentDialog.setHeaderText(Bundle.PromptDialogManager_rebuildPrompt_headerText()); currentDialog.setHeaderText(Bundle.PromptDialogManager_rebuildPrompt_headerText());
setDialogIcons(currentDialog); setDialogIcons(currentDialog);
setDialogTitle(currentDialog); currentDialog.setTitle(Bundle.Timeline_confirmation_dialogs_title());
DialogPane dialogPane = currentDialog.getDialogPane(); DialogPane dialogPane = currentDialog.getDialogPane();
ListView<String> listView = new ListView<>(FXCollections.observableArrayList(rebuildReasons)); ListView<String> listView = new ListView<>(FXCollections.observableArrayList(rebuildReasons));

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014-2015 Basis Technology Corp. * Copyright 2014-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -21,8 +21,7 @@ package org.sleuthkit.autopsy.timeline;
import java.awt.HeadlessException; import java.awt.HeadlessException;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.sql.ResultSet; import java.io.IOException;
import java.sql.SQLException;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -31,9 +30,10 @@ import java.util.TimeZone;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable; import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper; import javafx.beans.property.ReadOnlyBooleanWrapper;
@ -49,7 +49,6 @@ import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import javafx.concurrent.Worker; import javafx.concurrent.Worker;
import javafx.scene.control.Dialog;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@ -83,9 +82,6 @@ import org.sleuthkit.autopsy.timeline.utils.IntervalUtils;
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD; import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel; import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
import org.sleuthkit.autopsy.timeline.zooming.ZoomParams; import org.sleuthkit.autopsy.timeline.zooming.ZoomParams;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Controller in the MVC design along with model = {@link FilteredEventsModel} * Controller in the MVC design along with model = {@link FilteredEventsModel}
@ -139,9 +135,6 @@ public class TimeLineController {
private final ReadOnlyStringWrapper status = new ReadOnlyStringWrapper(); private final ReadOnlyStringWrapper status = new ReadOnlyStringWrapper();
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private Dialog<?> currentDialog;
/** /**
* status is a string that will be displayed in the status bar as a kind of * status is a string that will be displayed in the status bar as a kind of
* user hint/information when it is not empty * user hint/information when it is not empty
@ -156,12 +149,13 @@ public class TimeLineController {
status.set(string); status.set(string);
} }
private final Case autoCase; private final Case autoCase;
private final PerCaseTimelineProperties perCaseTimelineProperties;
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private final ObservableList<DescriptionFilter> quickHideMaskFilters = FXCollections.observableArrayList(); private final ObservableList<DescriptionFilter> quickHideFilters = FXCollections.observableArrayList();
public ObservableList<DescriptionFilter> getQuickHideFilters() { public ObservableList<DescriptionFilter> getQuickHideFilters() {
return quickHideMaskFilters; return quickHideFilters;
} }
/** /**
@ -219,13 +213,12 @@ public class TimeLineController {
@GuardedBy("this") @GuardedBy("this")
private final ReadOnlyObjectWrapper<ZoomParams> currentParams = new ReadOnlyObjectWrapper<>(); private final ReadOnlyObjectWrapper<ZoomParams> currentParams = new ReadOnlyObjectWrapper<>();
//all members should be access with the intrinsict lock of this object held
//selected events (ie shown in the result viewer) //selected events (ie shown in the result viewer)
@GuardedBy("this") @GuardedBy("this")
private final ObservableList<Long> selectedEventIDs = FXCollections.<Long>synchronizedObservableList(FXCollections.<Long>observableArrayList()); private final ObservableList<Long> selectedEventIDs = FXCollections.<Long>synchronizedObservableList(FXCollections.<Long>observableArrayList());
/** /**
* @return an unmodifiable list of the selected event ids * @return a list of the selected event ids
*/ */
synchronized public ObservableList<Long> getSelectedEventIDs() { synchronized public ObservableList<Long> getSelectedEventIDs() {
return selectedEventIDs; return selectedEventIDs;
@ -241,14 +234,8 @@ public class TimeLineController {
return selectedTimeRange.getReadOnlyProperty(); return selectedTimeRange.getReadOnlyProperty();
} }
public ReadOnlyBooleanProperty getNewEventsFlag() { public ReadOnlyBooleanProperty eventsDBStaleProperty() {
return newEventsFlag.getReadOnlyProperty(); return eventsDBStale.getReadOnlyProperty();
}
private final ReadOnlyBooleanWrapper needsHistogramRebuild = new ReadOnlyBooleanWrapper(false);
public ReadOnlyBooleanProperty getNeedsHistogramRebuild() {
return needsHistogramRebuild.getReadOnlyProperty();
} }
synchronized public ReadOnlyBooleanProperty getCanAdvance() { synchronized public ReadOnlyBooleanProperty getCanAdvance() {
@ -258,28 +245,26 @@ public class TimeLineController {
synchronized public ReadOnlyBooleanProperty getCanRetreat() { synchronized public ReadOnlyBooleanProperty getCanRetreat() {
return historyManager.getCanRetreat(); return historyManager.getCanRetreat();
} }
private final ReadOnlyBooleanWrapper newEventsFlag = new ReadOnlyBooleanWrapper(false); private final ReadOnlyBooleanWrapper eventsDBStale = new ReadOnlyBooleanWrapper(true);
private final PromptDialogManager promptDialogManager = new PromptDialogManager(this); private final PromptDialogManager promptDialogManager = new PromptDialogManager(this);
public TimeLineController(Case autoCase) { public TimeLineController(Case autoCase) throws IOException {
this.autoCase = autoCase; this.autoCase = autoCase;
this.perCaseTimelineProperties = new PerCaseTimelineProperties(autoCase);
eventsDBStale.set(perCaseTimelineProperties.isDBStale());
eventsRepository = new EventsRepository(autoCase, currentParams.getReadOnlyProperty());
/* /*
* as the history manager's current state changes, modify the tags * as the history manager's current state changes, modify the tags
* filter to be in sync, and expose that as propery from * filter to be in sync, and expose that as propery from
* TimeLineController. Do we need to do this with datasource or hash hit * TimeLineController. Do we need to do this with datasource or hash hit
* filters? * filters?
*/ */
historyManager.currentState().addListener(new InvalidationListener() { historyManager.currentState().addListener((Observable observable) -> {
public void invalidated(Observable observable) {
ZoomParams historyManagerParams = historyManager.getCurrentState(); ZoomParams historyManagerParams = historyManager.getCurrentState();
eventsRepository.syncTagsFilter(historyManagerParams.getFilter().getTagsFilter()); eventsRepository.syncTagsFilter(historyManagerParams.getFilter().getTagsFilter());
currentParams.set(historyManagerParams); currentParams.set(historyManagerParams);
}
}); });
eventsRepository = new EventsRepository(autoCase, currentParams.getReadOnlyProperty());
filteredEvents = eventsRepository.getEventsModel(); filteredEvents = eventsRepository.getEventsModel();
InitialZoomState = new ZoomParams(filteredEvents.getSpanningInterval(), InitialZoomState = new ZoomParams(filteredEvents.getSpanningInterval(),
@ -306,54 +291,52 @@ public class TimeLineController {
} }
/** /**
* rebuld the repo. * rebuild the repo using the given repo builder (expected to be a member
* reference to {@link EventsRepository#rebuildRepository(java.util.function.Consumer)
* } or {@link EventsRepository#rebuildTags(java.util.function.Consumer) })
* and display the ui when it is done.
* *
* @return False if the repo was not rebuilt because because the user * @param repoBuilder
* aborted after prompt about ingest running. True if the repo was
* rebuilt.
*/ */
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
void rebuildRepo() { private void rebuildRepoHelper(Function<Consumer<Worker.State>, CancellationProgressTask<?>> repoBuilder) {
SwingUtilities.invokeLater(this::closeTimelineWindow); SwingUtilities.invokeLater(this::closeTimelineWindow);
final CancellationProgressTask<?> rebuildRepository = eventsRepository.rebuildRepository(); boolean ingestRunning = IngestManager.getInstance().isIngestRunning();
rebuildRepository.stateProperty().addListener((stateProperty, oldState, newSate) -> { final CancellationProgressTask<?> rebuildRepository = repoBuilder.apply(newSate -> {
setIngestRunning(ingestRunning);
//this will be on JFX thread //this will be on JFX thread
if (newSate == Worker.State.SUCCEEDED) { switch (newSate) {
//TODO: this looks hacky. what is going on? should this be an event? case SUCCEEDED:
needsHistogramRebuild.set(true); setEventsDBStale(false);
needsHistogramRebuild.set(false);
SwingUtilities.invokeLater(TimeLineController.this::showWindow); SwingUtilities.invokeLater(TimeLineController.this::showWindow);
//TODO: should this be an event?
newEventsFlag.set(false);
historyManager.reset(filteredEvents.zoomParametersProperty().get()); historyManager.reset(filteredEvents.zoomParametersProperty().get());
TimeLineController.this.showFullRange(); TimeLineController.this.showFullRange();
break;
case FAILED:
case CANCELLED:
setEventsDBStale(true);
break;
} }
}); });
promptDialogManager.showProgressDialog(rebuildRepository); promptDialogManager.showProgressDialog(rebuildRepository);
}
/**
* rebuld the entire repo.
*/
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
void rebuildRepo() {
rebuildRepoHelper(eventsRepository::rebuildRepository);
} }
/** /**
* Since tags might have changed while TimeLine wasn't listening, drop the * Since tags might have changed while TimeLine wasn't listening, drop the
* tags table and rebuild it by querying for all the tags and inserting them * tags table and rebuild it by querying for all the tags and inserting them
* in to the TimeLine DB. * in to the TimeLine DB.
*
*/ */
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
void rebuildTagsTable() { void rebuildTagsTable() {
rebuildRepoHelper(eventsRepository::rebuildTags);
SwingUtilities.invokeLater(this::closeTimelineWindow);
CancellationProgressTask<?> rebuildTags = eventsRepository.rebuildTags();
rebuildTags.stateProperty().addListener((stateProperty, oldState, newSate) -> {
//this will be on JFX thread
if (newSate == Worker.State.SUCCEEDED) {
SwingUtilities.invokeLater(TimeLineController.this::showWindow);
showFullRange();
}
});
promptDialogManager.showProgressDialog(rebuildTags);
} }
@ThreadConfined(type = ThreadConfined.ThreadType.AWT) @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
@ -370,7 +353,7 @@ public class TimeLineController {
} }
@ThreadConfined(type = ThreadConfined.ThreadType.AWT) @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
public void closeTimeLine() { public void shutDownTimeLine() {
if (mainFrame != null) { if (mainFrame != null) {
listeningToAutopsy = false; listeningToAutopsy = false;
IngestManager.getInstance().removeIngestModuleEventListener(ingestModuleListener); IngestManager.getInstance().removeIngestModuleEventListener(ingestModuleListener);
@ -409,7 +392,7 @@ public class TimeLineController {
/* /*
* if the repo was not rebuilt at minimum rebuild the tags which * if the repo was not rebuilt at minimum rebuild the tags which
* may have been updated without our knowing it, since we * may have been updated without our knowing it, since we
* can't/aren't checking them. This should at elast be quick. * can't/aren't checking them. This should at least be quick.
* //TODO: can we check the tags to see if we need to do this? * //TODO: can we check the tags to see if we need to do this?
*/ */
if (checkAndPromptForRebuild() == false) { if (checkAndPromptForRebuild() == false) {
@ -425,7 +408,7 @@ public class TimeLineController {
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private boolean checkAndPromptForRebuild() { private boolean checkAndPromptForRebuild() {
//if the repo is empty just (r)ebuild it with out asking, they can always cancel part way through; //if the repo is empty just (r)ebuild it with out asking, they can always cancel part way through;
if (eventsRepository.getLastObjID() == -1) { if (eventsRepository.countAllEvents() == 0) {
rebuildRepo(); rebuildRepo();
return true; return true;
} }
@ -440,7 +423,6 @@ public class TimeLineController {
return false; return false;
} }
@SuppressWarnings("deprecation") // TODO (EUR-733): Do not use SleuthkitCase.getLastObjectId
@ThreadConfined(type = ThreadConfined.ThreadType.ANY) @ThreadConfined(type = ThreadConfined.ThreadType.ANY)
@NbBundle.Messages({"TimeLineController.errorTitle=Timeline error.", @NbBundle.Messages({"TimeLineController.errorTitle=Timeline error.",
"TimeLineController.outOfDate.errorMessage=Error determing if the timeline is out of date. We will assume it should be updated. See the logs for more details.", "TimeLineController.outOfDate.errorMessage=Error determing if the timeline is out of date. We will assume it should be updated. See the logs for more details.",
@ -450,23 +432,23 @@ public class TimeLineController {
"TimeLineController.rebuildReasons.incompleteOldSchema=The Timeline events database was previously populated without incomplete information: Some features may be unavailable or non-functional unless you update the events database."}) "TimeLineController.rebuildReasons.incompleteOldSchema=The Timeline events database was previously populated without incomplete information: Some features may be unavailable or non-functional unless you update the events database."})
private ArrayList<String> getRebuildReasons() { private ArrayList<String> getRebuildReasons() {
ArrayList<String> rebuildReasons = new ArrayList<>(); ArrayList<String> rebuildReasons = new ArrayList<>();
try {
//if ingest was running during last rebuild, prompt to rebuild //if ingest was running during last rebuild, prompt to rebuild
if (eventsRepository.getWasIngestRunning()) { if (perCaseTimelineProperties.wasIngestRunning()) {
rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_ingestWasRunning()); rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_ingestWasRunning());
} }
final SleuthkitCase sleuthkitCase = autoCase.getSleuthkitCase();
try { } catch (IOException ex) {
//if the last artifact and object ids don't match between skc and tldb, prompt to rebuild LOGGER.log(Level.SEVERE, "Error determing the state of the timeline db. We will assume the it is out of date.", ex); // NON-NLS
if (sleuthkitCase.getLastObjectId() != eventsRepository.getLastObjID()
|| getCaseLastArtifactID(sleuthkitCase) != eventsRepository.getLastArtfactID()) {
rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_outOfDate());
}
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error determing last object id from sleutkit case. We will assume the timeline is out of date.", ex); // NON-NLS
MessageNotifyUtil.Notify.error(Bundle.TimeLineController_errorTitle(), MessageNotifyUtil.Notify.error(Bundle.TimeLineController_errorTitle(),
Bundle.TimeLineController_outOfDate_errorMessage()); Bundle.TimeLineController_outOfDate_errorMessage());
rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_outOfDateError()); rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_outOfDateError());
} }
//if the events db is stale, prompt to rebuild
if (isEventsDBStale()) {
rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_outOfDate());
}
// if the TLDB schema has been upgraded since last time TL ran, prompt for rebuild // if the TLDB schema has been upgraded since last time TL ran, prompt for rebuild
if (eventsRepository.hasNewColumns() == false) { if (eventsRepository.hasNewColumns() == false) {
rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_incompleteOldSchema()); rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_incompleteOldSchema());
@ -474,21 +456,6 @@ public class TimeLineController {
return rebuildReasons; return rebuildReasons;
} }
public static long getCaseLastArtifactID(final SleuthkitCase sleuthkitCase) {
//TODO: push this into sleuthkitCase
long caseLastArtfId = -1;
String query = "select Max(artifact_id) as max_id from blackboard_artifacts"; // NON-NLS //NOI18N
try (CaseDbQuery dbQuery = sleuthkitCase.executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet();
while (resultSet.next()) {
caseLastArtfId = resultSet.getLong("max_id"); // NON-NLS //NOI18N
}
} catch (TskCoreException | SQLException ex) {
LOGGER.log(Level.SEVERE, "Error getting last artifact id: ", ex); // NON-NLS //NOI18N
}
return caseLastArtfId;
}
/** /**
* request a time range the same length as the given period and centered * request a time range the same length as the given period and centered
* around the middle of the currently selected range * around the middle of the currently selected range
@ -752,6 +719,38 @@ public class TimeLineController {
} }
} }
/**
* is the events db out of date
*
* @return true if the events db is out of date , false otherwise
*/
public boolean isEventsDBStale() {
return eventsDBStale.get();
}
/**
*
* @param stale the value of stale
*/
private void setEventsDBStale(final Boolean stale) {
eventsDBStale.set(stale);
try {
perCaseTimelineProperties.setDbStale(stale);
} catch (IOException ex) {
MessageNotifyUtil.Notify.error("Timeline", "Failed to mark the timeline db as " + (stale ? "" : "not ") + "stale. Some results may be out of date or missing.");
LOGGER.log(Level.SEVERE, "Error marking the timeline db as stale.", ex);
}
}
private void setIngestRunning(boolean ingestRunning) {
try {
perCaseTimelineProperties.setIngestRunning(ingestRunning);
} catch (IOException ex) {
MessageNotifyUtil.Notify.error("Timeline", "Failed to mark the timeline db as populated while ingest was" + (ingestRunning ? "" : "not ") + "running. Some results may be out of date or missing.");
LOGGER.log(Level.SEVERE, "Error marking the ingest state while the timeline db was populated.", ex);
}
}
private class AutopsyIngestModuleListener implements PropertyChangeListener { private class AutopsyIngestModuleListener implements PropertyChangeListener {
@Override @Override
@ -773,12 +772,10 @@ public class TimeLineController {
switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) { switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) {
case CONTENT_CHANGED: case CONTENT_CHANGED:
case DATA_ADDED:
break; break;
case DATA_ADDED:
case FILE_DONE: case FILE_DONE:
Platform.runLater(() -> { Platform.runLater(() -> setEventsDBStale(true));
newEventsFlag.set(true);
});
break; break;
} }
} }
@ -804,32 +801,26 @@ public class TimeLineController {
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
switch (Case.Events.valueOf(evt.getPropertyName())) { switch (Case.Events.valueOf(evt.getPropertyName())) {
case BLACKBOARD_ARTIFACT_TAG_ADDED: case BLACKBOARD_ARTIFACT_TAG_ADDED:
executor.submit(() -> { executor.submit(() -> filteredEvents.handleArtifactTagAdded((BlackBoardArtifactTagAddedEvent) evt));
filteredEvents.handleArtifactTagAdded((BlackBoardArtifactTagAddedEvent) evt);
});
break; break;
case BLACKBOARD_ARTIFACT_TAG_DELETED: case BLACKBOARD_ARTIFACT_TAG_DELETED:
executor.submit(() -> { executor.submit(() -> filteredEvents.handleArtifactTagDeleted((BlackBoardArtifactTagDeletedEvent) evt));
filteredEvents.handleArtifactTagDeleted((BlackBoardArtifactTagDeletedEvent) evt);
});
break; break;
case CONTENT_TAG_ADDED: case CONTENT_TAG_ADDED:
executor.submit(() -> { executor.submit(() -> filteredEvents.handleContentTagAdded((ContentTagAddedEvent) evt));
filteredEvents.handleContentTagAdded((ContentTagAddedEvent) evt);
});
break; break;
case CONTENT_TAG_DELETED: case CONTENT_TAG_DELETED:
executor.submit(() -> { executor.submit(() -> filteredEvents.handleContentTagDeleted((ContentTagDeletedEvent) evt));
filteredEvents.handleContentTagDeleted((ContentTagDeletedEvent) evt);
});
break; break;
case DATA_SOURCE_ADDED: case DATA_SOURCE_ADDED:
Platform.runLater(() -> {
setEventsDBStale(true);
SwingUtilities.invokeLater(TimeLineController.this::confirmOutOfDateRebuildIfWindowOpen); SwingUtilities.invokeLater(TimeLineController.this::confirmOutOfDateRebuildIfWindowOpen);
});
break; break;
case CURRENT_CASE: case CURRENT_CASE:
OpenTimelineAction.invalidateController(); OpenTimelineAction.invalidateController();
SwingUtilities.invokeLater(TimeLineController.this::closeTimeLine); SwingUtilities.invokeLater(TimeLineController.this::shutDownTimeLine);
break; break;
} }
} }

View File

@ -42,7 +42,7 @@ import org.sleuthkit.datamodel.TskCoreException;
public enum MiscTypes implements EventType, ArtifactEventType { public enum MiscTypes implements EventType, ArtifactEventType {
MESSAGE(NbBundle.getMessage(MiscTypes.class, "MiscTypes.message.name"), "message.png", // NON-NLS MESSAGE(NbBundle.getMessage(MiscTypes.class, "MiscTypes.message.name"), "message.png", // NON-NLS
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_MESSAGE), new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_MESSAGE),
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE)),
artf -> { artf -> {
@ -56,7 +56,7 @@ public enum MiscTypes implements EventType, ArtifactEventType {
}, },
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT))), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT))),
GPS_ROUTE(NbBundle.getMessage(MiscTypes.class, "MiscTypes.GPSRoutes.name"), "gps-search.png", // NON-NLS GPS_ROUTE(NbBundle.getMessage(MiscTypes.class, "MiscTypes.GPSRoutes.name"), "gps-search.png", // NON-NLS
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_GPS_ROUTE), new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_GPS_ROUTE),
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)),
@ -68,7 +68,7 @@ public enum MiscTypes implements EventType, ArtifactEventType {
return String.format("from %1$s %2$s to %3$s %4$s", stringValueOf(latStart), stringValueOf(longStart), stringValueOf(latEnd), stringValueOf(longEnd)); // NON-NLS return String.format("from %1$s %2$s to %3$s %4$s", stringValueOf(latStart), stringValueOf(longStart), stringValueOf(latEnd), stringValueOf(longEnd)); // NON-NLS
}), }),
GPS_TRACKPOINT(NbBundle.getMessage(MiscTypes.class, "MiscTypes.GPSTrackpoint.name"), "gps-trackpoint.png", // NON-NLS GPS_TRACKPOINT(NbBundle.getMessage(MiscTypes.class, "MiscTypes.GPSTrackpoint.name"), "gps-trackpoint.png", // NON-NLS
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT), new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT),
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)),
artf -> { artf -> {
@ -78,13 +78,13 @@ public enum MiscTypes implements EventType, ArtifactEventType {
}, },
EMPTY_EXTRACTOR), EMPTY_EXTRACTOR),
CALL_LOG(NbBundle.getMessage(MiscTypes.class, "MiscTypes.Calls.name"), "calllog.png", // NON-NLS CALL_LOG(NbBundle.getMessage(MiscTypes.class, "MiscTypes.Calls.name"), "calllog.png", // NON-NLS
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_CALLLOG), new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_CALLLOG),
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION))), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION))),
EMAIL(NbBundle.getMessage(MiscTypes.class, "MiscTypes.Email.name"), "mail-icon-16.png", // NON-NLS EMAIL(NbBundle.getMessage(MiscTypes.class, "MiscTypes.Email.name"), "mail-icon-16.png", // NON-NLS
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_EMAIL_MSG), new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_EMAIL_MSG),
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT),
artf -> { artf -> {
final BlackboardAttribute emailFrom = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_FROM)); final BlackboardAttribute emailFrom = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_FROM));
@ -94,7 +94,7 @@ public enum MiscTypes implements EventType, ArtifactEventType {
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT)),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN))), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN))),
RECENT_DOCUMENTS(NbBundle.getMessage(MiscTypes.class, "MiscTypes.recentDocuments.name"), "recent_docs.png", // NON-NLS RECENT_DOCUMENTS(NbBundle.getMessage(MiscTypes.class, "MiscTypes.recentDocuments.name"), "recent_docs.png", // NON-NLS
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_RECENT_OBJECT), new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_RECENT_OBJECT),
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)).andThen( new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)).andThen(
(String t) -> (StringUtils.substringBeforeLast(StringUtils.substringBeforeLast(t, "\\"), "\\"))), (String t) -> (StringUtils.substringBeforeLast(StringUtils.substringBeforeLast(t, "\\"), "\\"))),
@ -117,13 +117,13 @@ public enum MiscTypes implements EventType, ArtifactEventType {
} }
}, },
INSTALLED_PROGRAM(NbBundle.getMessage(MiscTypes.class, "MiscTypes.installedPrograms.name"), "programs.png", // NON-NLS INSTALLED_PROGRAM(NbBundle.getMessage(MiscTypes.class, "MiscTypes.installedPrograms.name"), "programs.png", // NON-NLS
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_INSTALLED_PROG), new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_INSTALLED_PROG),
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)),
EMPTY_EXTRACTOR, EMPTY_EXTRACTOR,
EMPTY_EXTRACTOR), EMPTY_EXTRACTOR),
EXIF(NbBundle.getMessage(MiscTypes.class, "MiscTypes.exif.name"), "camera-icon-16.png", // NON-NLS EXIF(NbBundle.getMessage(MiscTypes.class, "MiscTypes.exif.name"), "camera-icon-16.png", // NON-NLS
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_METADATA_EXIF), new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_METADATA_EXIF),
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)),
@ -139,7 +139,7 @@ public enum MiscTypes implements EventType, ArtifactEventType {
return "error loading file name"; return "error loading file name";
}), }),
DEVICES_ATTACHED(NbBundle.getMessage(MiscTypes.class, "MiscTypes.devicesAttached.name"), "usb_devices.png", // NON-NLS DEVICES_ATTACHED(NbBundle.getMessage(MiscTypes.class, "MiscTypes.devicesAttached.name"), "usb_devices.png", // NON-NLS
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED), new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED),
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)),

View File

@ -1,35 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.timeline.datamodel.eventtype;
import org.sleuthkit.datamodel.BlackboardArtifact;
/**
*
*/
class TypeUtils {
//TODO: this will be unncessary once their is BlackboardArtifact.Type constructr that takes a BlackboardArtifact.ARTIFACT_TYPE
static BlackboardArtifact.Type fromEnum(BlackboardArtifact.ARTIFACT_TYPE type) {
return new BlackboardArtifact.Type(type.getTypeID(), type.getLabel(), type.getDisplayName());
}
private TypeUtils() {
}
}

View File

@ -37,7 +37,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
WEB_DOWNLOADS(NbBundle.getMessage(WebTypes.class, "WebTypes.webDownloads.name"), WEB_DOWNLOADS(NbBundle.getMessage(WebTypes.class, "WebTypes.webDownloads.name"),
"downloads.png", // NON-NLS "downloads.png", // NON-NLS
TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD), new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD),
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED), new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED),
TopPrivateDomainExtractor.getInstance(), TopPrivateDomainExtractor.getInstance(),
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)), new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)),
@ -61,7 +61,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
//TODO: review description separators //TODO: review description separators
WEB_COOKIE(NbBundle.getMessage(WebTypes.class, "WebTypes.webCookies.name"), WEB_COOKIE(NbBundle.getMessage(WebTypes.class, "WebTypes.webCookies.name"),
"cookies.png", // NON-NLS "cookies.png", // NON-NLS
TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE), new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE),
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME), new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME),
TopPrivateDomainExtractor.getInstance(), TopPrivateDomainExtractor.getInstance(),
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME)), new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME)),
@ -69,7 +69,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
//TODO: review description separators //TODO: review description separators
WEB_BOOKMARK(NbBundle.getMessage(WebTypes.class, "WebTypes.webBookmarks.name"), WEB_BOOKMARK(NbBundle.getMessage(WebTypes.class, "WebTypes.webBookmarks.name"),
"bookmarks.png", // NON-NLS "bookmarks.png", // NON-NLS
TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK), new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK),
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED), new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED),
TopPrivateDomainExtractor.getInstance(), TopPrivateDomainExtractor.getInstance(),
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)), new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)),
@ -77,7 +77,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
//TODO: review description separators //TODO: review description separators
WEB_HISTORY(NbBundle.getMessage(WebTypes.class, "WebTypes.webHistory.name"), WEB_HISTORY(NbBundle.getMessage(WebTypes.class, "WebTypes.webHistory.name"),
"history.png", // NON-NLS "history.png", // NON-NLS
TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY), new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY),
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED), new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED),
TopPrivateDomainExtractor.getInstance(), TopPrivateDomainExtractor.getInstance(),
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)), new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)),
@ -85,7 +85,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
//TODO: review description separators //TODO: review description separators
WEB_SEARCH(NbBundle.getMessage(WebTypes.class, "WebTypes.webSearch.name"), WEB_SEARCH(NbBundle.getMessage(WebTypes.class, "WebTypes.webSearch.name"),
"searchquery.png", // NON-NLS "searchquery.png", // NON-NLS
TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY), new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY),
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED), new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED),
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT)), new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT)),
TopPrivateDomainExtractor.getInstance(), TopPrivateDomainExtractor.getInstance(),

View File

@ -84,28 +84,6 @@ import org.sqlite.SQLiteJDBCLoader;
*/ */
public class EventDB { public class EventDB {
/**
*
* enum to represent keys stored in db_info table
*/
private enum DBInfoKey {
LAST_ARTIFACT_ID("last_artifact_id"), // NON-NLS
LAST_OBJECT_ID("last_object_id"), // NON-NLS
WAS_INGEST_RUNNING("was_ingest_running"); // NON-NLS
private final String keyName;
private DBInfoKey(String keyName) {
this.keyName = keyName;
}
@Override
public String toString() {
return keyName;
}
}
private static final org.sleuthkit.autopsy.coreutils.Logger LOGGER = Logger.getLogger(EventDB.class.getName()); private static final org.sleuthkit.autopsy.coreutils.Logger LOGGER = Logger.getLogger(EventDB.class.getName());
static { static {
@ -142,14 +120,12 @@ public class EventDB {
private final String dbPath; private final String dbPath;
private PreparedStatement getDBInfoStmt;
private PreparedStatement getEventByIDStmt; private PreparedStatement getEventByIDStmt;
private PreparedStatement getMaxTimeStmt; private PreparedStatement getMaxTimeStmt;
private PreparedStatement getMinTimeStmt; private PreparedStatement getMinTimeStmt;
private PreparedStatement getDataSourceIDsStmt; private PreparedStatement getDataSourceIDsStmt;
private PreparedStatement getHashSetNamesStmt; private PreparedStatement getHashSetNamesStmt;
private PreparedStatement insertRowStmt; private PreparedStatement insertRowStmt;
private PreparedStatement recordDBInfoStmt;
private PreparedStatement insertHashSetStmt; private PreparedStatement insertHashSetStmt;
private PreparedStatement insertHashHitStmt; private PreparedStatement insertHashHitStmt;
private PreparedStatement insertTagStmt; private PreparedStatement insertTagStmt;
@ -394,14 +370,6 @@ public class EventDB {
return resultIDs; return resultIDs;
} }
long getLastArtfactID() {
return getDBInfo(DBInfoKey.LAST_ARTIFACT_ID, -1);
}
long getLastObjID() {
return getDBInfo(DBInfoKey.LAST_OBJECT_ID, -1);
}
/** /**
* this relies on the fact that no tskObj has ID 0 but 0 is the default * this relies on the fact that no tskObj has ID 0 but 0 is the default
* value for the datasource_id column in the events table. * value for the datasource_id column in the events table.
@ -489,10 +457,6 @@ public class EventDB {
return -1l; return -1l;
} }
boolean getWasIngestRunning() {
return getDBInfo(DBInfoKey.WAS_INGEST_RUNNING, 0) != 0;
}
/** /**
* create the table and indices if they don't already exist * create the table and indices if they don't already exist
* *
@ -614,8 +578,6 @@ public class EventDB {
getMaxTimeStmt = prepareStatement("SELECT Max(time) AS max FROM events"); // NON-NLS getMaxTimeStmt = prepareStatement("SELECT Max(time) AS max FROM events"); // NON-NLS
getMinTimeStmt = prepareStatement("SELECT Min(time) AS min FROM events"); // NON-NLS getMinTimeStmt = prepareStatement("SELECT Min(time) AS min FROM events"); // NON-NLS
getEventByIDStmt = prepareStatement("SELECT * FROM events WHERE event_id = ?"); // NON-NLS getEventByIDStmt = prepareStatement("SELECT * FROM events WHERE event_id = ?"); // NON-NLS
recordDBInfoStmt = prepareStatement("INSERT OR REPLACE INTO db_info (key, value) values (?, ?)"); // NON-NLS
getDBInfoStmt = prepareStatement("SELECT value FROM db_info WHERE key = ?"); // NON-NLS
insertHashSetStmt = prepareStatement("INSERT OR IGNORE INTO hash_sets (hash_set_name) values (?)"); //NON-NLS insertHashSetStmt = prepareStatement("INSERT OR IGNORE INTO hash_sets (hash_set_name) values (?)"); //NON-NLS
selectHashSetStmt = prepareStatement("SELECT hash_set_id FROM hash_sets WHERE hash_set_name = ?"); //NON-NLS selectHashSetStmt = prepareStatement("SELECT hash_set_id FROM hash_sets WHERE hash_set_name = ?"); //NON-NLS
insertHashHitStmt = prepareStatement("INSERT OR IGNORE INTO hash_set_hits (hash_set_id, event_id) values (?,?)"); //NON-NLS insertHashHitStmt = prepareStatement("INSERT OR IGNORE INTO hash_set_hits (hash_set_id, event_id) values (?,?)"); //NON-NLS
@ -938,18 +900,6 @@ public class EventDB {
return eventIDs; return eventIDs;
} }
void recordLastArtifactID(long lastArtfID) {
recordDBInfo(DBInfoKey.LAST_ARTIFACT_ID, lastArtfID);
}
void recordLastObjID(Long lastObjID) {
recordDBInfo(DBInfoKey.LAST_OBJECT_ID, lastObjID);
}
void recordWasIngestRunning(boolean wasIngestRunning) {
recordDBInfo(DBInfoKey.WAS_INGEST_RUNNING, (wasIngestRunning ? 1 : 0));
}
void rollBackTransaction(EventTransaction trans) { void rollBackTransaction(EventTransaction trans) {
trans.rollback(); trans.rollback();
} }
@ -983,8 +933,7 @@ public class EventDB {
try { try {
LOGGER.log(Level.INFO, String.format("sqlite-jdbc version %s loaded in %s mode", // NON-NLS LOGGER.log(Level.INFO, String.format("sqlite-jdbc version %s loaded in %s mode", // NON-NLS
SQLiteJDBCLoader.getVersion(), SQLiteJDBCLoader.isNativeMode() SQLiteJDBCLoader.getVersion(), SQLiteJDBCLoader.isNativeMode() ? "native" : "pure-java")); // NON-NLS
? "native" : "pure-java")); // NON-NLS
} catch (Exception exception) { } catch (Exception exception) {
LOGGER.log(Level.SEVERE, "Failed to determine if sqlite-jdbc is loaded in native or pure-java mode.", exception); //NON-NLS LOGGER.log(Level.SEVERE, "Failed to determine if sqlite-jdbc is loaded in native or pure-java mode.", exception); //NON-NLS
} }
@ -1220,28 +1169,6 @@ public class EventDB {
return useSubTypes ? "sub_type" : "base_type"; //NON-NLS return useSubTypes ? "sub_type" : "base_type"; //NON-NLS
} }
private long getDBInfo(DBInfoKey key, long defaultValue) {
DBLock.lock();
try {
getDBInfoStmt.setString(1, key.toString());
try (ResultSet rs = getDBInfoStmt.executeQuery()) {
long result = defaultValue;
while (rs.next()) {
result = rs.getLong("value"); // NON-NLS
}
return result;
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, "failed to read key: " + key + " from db_info", ex); // NON-NLS
} finally {
DBLock.unlock();
}
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, "failed to set key: " + key + " on getDBInfoStmt ", ex); // NON-NLS
}
return defaultValue;
}
private PreparedStatement prepareStatement(String queryString) throws SQLException { private PreparedStatement prepareStatement(String queryString) throws SQLException {
PreparedStatement prepareStatement = con.prepareStatement(queryString); PreparedStatement prepareStatement = con.prepareStatement(queryString);
@ -1249,20 +1176,6 @@ public class EventDB {
return prepareStatement; return prepareStatement;
} }
private void recordDBInfo(DBInfoKey key, long value) {
DBLock.lock();
try {
recordDBInfoStmt.setString(1, key.toString());
recordDBInfoStmt.setLong(2, value);
recordDBInfoStmt.executeUpdate();
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, "failed to set dbinfo key: " + key + " value: " + value, ex); // NON-NLS
} finally {
DBLock.unlock();
}
}
/** /**
* inner class that can reference access database connection * inner class that can reference access database connection
*/ */

View File

@ -35,6 +35,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javafx.application.Platform; import javafx.application.Platform;
@ -44,6 +45,7 @@ import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.collections.ObservableMap; import javafx.collections.ObservableMap;
import javafx.concurrent.Worker;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.joda.time.Interval; import org.joda.time.Interval;
@ -54,9 +56,7 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.casemodule.services.TagsManager;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.timeline.CancellationProgressTask; import org.sleuthkit.autopsy.timeline.CancellationProgressTask;
import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe; import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel; import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
@ -168,7 +168,7 @@ public class EventsRepository {
*/ */
public Long getMaxTime() { public Long getMaxTime() {
return maxCache.getUnchecked("max"); // NON-NLS return maxCache.getUnchecked("max"); // NON-NLS
// return eventDB.getMaxTime();
} }
/** /**
@ -176,31 +176,7 @@ public class EventsRepository {
*/ */
public Long getMinTime() { public Long getMinTime() {
return minCache.getUnchecked("min"); // NON-NLS return minCache.getUnchecked("min"); // NON-NLS
// return eventDB.getMinTime();
}
private void recordLastArtifactID(long lastArtfID) {
eventDB.recordLastArtifactID(lastArtfID);
}
private void recordWasIngestRunning(Boolean wasIngestRunning) {
eventDB.recordWasIngestRunning(wasIngestRunning);
}
private void recordLastObjID(Long lastObjID) {
eventDB.recordLastObjID(lastObjID);
}
public boolean getWasIngestRunning() {
return eventDB.getWasIngestRunning();
}
public Long getLastObjID() {
return eventDB.getLastObjID();
}
public long getLastArtfactID() {
return eventDB.getLastArtfactID();
} }
public TimeLineEvent getEventById(Long eventID) { public TimeLineEvent getEventById(Long eventID) {
@ -227,6 +203,10 @@ public class EventsRepository {
return eventCountsCache.getUnchecked(params); return eventCountsCache.getUnchecked(params);
} }
synchronized public int countAllEvents() {
return eventDB.countAllEvents();
}
private void invalidateCaches() { private void invalidateCaches() {
minCache.invalidateAll(); minCache.invalidateAll();
maxCache.invalidateAll(); maxCache.invalidateAll();
@ -331,18 +311,6 @@ public class EventsRepository {
} }
} }
/**
*
* @param lastObjId the value of lastObjId
* @param lastArtfID the value of lastArtfID
* @param injestRunning the value of injestRunning
*/
public void recordDBPopulationState(final long lastObjId, final long lastArtfID, final Boolean injestRunning) {
recordLastObjID(lastObjId);
recordLastArtifactID(lastArtfID);
recordWasIngestRunning(injestRunning);
}
public boolean areFiltersEquivalent(RootFilter f1, RootFilter f2) { public boolean areFiltersEquivalent(RootFilter f1, RootFilter f2) {
return SQLHelper.getSQLWhere(f1).equals(SQLHelper.getSQLWhere(f2)); return SQLHelper.getSQLWhere(f1).equals(SQLHelper.getSQLWhere(f2));
} }
@ -352,27 +320,56 @@ public class EventsRepository {
return dbWorker.isRunning(); return dbWorker.isRunning();
} }
/**
*
* rebuild the entire repo.
*
* @param onStateChange called when he background task changes state.
* Clients can use this to handle failure, or cleanup
* operations for example.
*
* @return the task that will rebuild the repo in a background thread. The
* task has already been started.
*/
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
public CancellationProgressTask<Void> rebuildRepository() { public CancellationProgressTask<Void> rebuildRepository(Consumer<Worker.State> onStateChange) {
return rebuildRepository(DBPopulationMode.FULL); return rebuildRepository(DBPopulationMode.FULL, onStateChange);
}
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
public CancellationProgressTask<Void> rebuildTags() {
return rebuildRepository(DBPopulationMode.TAGS_ONLY);
} }
/** /**
* *
* @param mode the value of mode * drop and rebuild the tags in the repo.
*
* @param onStateChange called when he background task changes state.
* Clients can use this to handle failure, or cleanup
* operations for example.
*
* @return the task that will rebuild the repo in a background thread. The
* task has already been started.
*/ */
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private CancellationProgressTask<Void> rebuildRepository(final DBPopulationMode mode) { public CancellationProgressTask<Void> rebuildTags(Consumer<Worker.State> onStateChange) {
return rebuildRepository(DBPopulationMode.TAGS_ONLY, onStateChange);
}
/**
* rebuild the repo.
*
* @param mode the rebuild mode to use.
* @param onStateChange called when he background task changes state.
* Clients can use this to handle failure, or cleanup
* operations for example.
*
* @return the task that will rebuild the repo in a background thread. The
* task has already been started.
*/
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private CancellationProgressTask<Void> rebuildRepository(final DBPopulationMode mode, Consumer<Worker.State> onStateChange) {
LOGGER.log(Level.INFO, "(re)starting {0} db population task", mode); //NON-NLS LOGGER.log(Level.INFO, "(re)starting {0} db population task", mode); //NON-NLS
if (dbWorker != null) { if (dbWorker != null) {
dbWorker.cancel(); dbWorker.cancel();
} }
dbWorker = new DBPopulationWorker(mode); dbWorker = new DBPopulationWorker(mode, onStateChange);
workerExecutor.execute(dbWorker); workerExecutor.execute(dbWorker);
return dbWorker; return dbWorker;
} }
@ -437,10 +434,11 @@ public class EventsRepository {
} }
} }
DBPopulationWorker(DBPopulationMode mode) { DBPopulationWorker(DBPopulationMode mode, Consumer<Worker.State> onStateChange) {
skCase = autoCase.getSleuthkitCase(); skCase = autoCase.getSleuthkitCase();
tagsManager = autoCase.getServices().getTagsManager(); tagsManager = autoCase.getServices().getTagsManager();
this.dbPopulationMode = mode; this.dbPopulationMode = mode;
this.stateProperty().addListener(stateObservable -> onStateChange.accept(getState()));
} }
void restartProgressHandle(String title, String message, Double workDone, double total, Boolean cancellable) { void restartProgressHandle(String title, String message, Double workDone, double total, Boolean cancellable) {
@ -470,11 +468,6 @@ public class EventsRepository {
protected Void call() throws Exception { protected Void call() throws Exception {
EventDB.EventTransaction trans = null; EventDB.EventTransaction trans = null;
//save paramaters for recording later
long lastObjId = skCase.getLastObjectId();
long lastArtfID = TimeLineController.getCaseLastArtifactID(skCase);
boolean injestRunning = IngestManager.getInstance().isIngestRunning();
if (dbPopulationMode == DBPopulationMode.FULL) { if (dbPopulationMode == DBPopulationMode.FULL) {
//drop old db, and add back MAC and artifact events //drop old db, and add back MAC and artifact events
LOGGER.log(Level.INFO, "Beginning population of timeline db."); // NON-NLS LOGGER.log(Level.INFO, "Beginning population of timeline db."); // NON-NLS
@ -513,9 +506,6 @@ public class EventsRepository {
Platform.runLater(() -> cancellable.set(false)); Platform.runLater(() -> cancellable.set(false));
restartProgressHandle(Bundle.progressWindow_msg_commitingDb(), "", -1D, 1, false); restartProgressHandle(Bundle.progressWindow_msg_commitingDb(), "", -1D, 1, false);
eventDB.commitTransaction(trans); eventDB.commitTransaction(trans);
if (isCancelRequested() == false) {
recordDBPopulationState(lastObjId, lastArtfID, injestRunning);
}
eventDB.analyze(); eventDB.analyze();
populateFilterData(skCase); populateFilterData(skCase);

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.timeline.filters;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableBooleanValue;
/** /**
* Base implementation of a {@link Filter}. Implements active property. * Base implementation of a {@link Filter}. Implements active property.
@ -38,7 +39,7 @@ public abstract class AbstractFilter implements Filter {
} }
@Override @Override
public SimpleBooleanProperty getDisabledProperty() { public ObservableBooleanValue disabledProperty() {
return disabled; return disabled;
} }
@ -67,11 +68,11 @@ public abstract class AbstractFilter implements Filter {
return "[" + (isSelected() ? "x" : " ") + "]"; // NON-NLS return "[" + (isSelected() ? "x" : " ") + "]"; // NON-NLS
} }
public final boolean isActive() { public boolean isActive() {
return activeProperty.get(); return activeProperty.get();
} }
public final BooleanBinding activeProperty() { public BooleanBinding activeProperty() {
return activeProperty; return activeProperty;
} }
} }

View File

@ -67,6 +67,13 @@ public abstract class CompoundFilter<SubFilterType extends Filter> extends Abstr
} }
}); });
this.subFilters.setAll(subFilters); this.subFilters.setAll(subFilters);
this.selectedProperty().addListener(activeProperty -> {
getSubFilters().forEach(subFilter -> subFilter.setDisabled(isActive() == false));
});
this.disabledProperty().addListener(activeProperty -> {
getSubFilters().forEach(subFilter -> subFilter.setDisabled(isActive() == false));
});
} }
private void addSubFilterListeners(List<? extends SubFilterType> newSubfilters) { private void addSubFilterListeners(List<? extends SubFilterType> newSubfilters) {

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.timeline.filters;
import java.util.Comparator; import java.util.Comparator;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableBooleanValue;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
/** /**
@ -29,7 +30,6 @@ import org.openide.util.NbBundle;
public class DataSourcesFilter extends UnionFilter<DataSourceFilter> { public class DataSourcesFilter extends UnionFilter<DataSourceFilter> {
public DataSourcesFilter() { public DataSourcesFilter() {
getDisabledProperty().bind(Bindings.size(getSubFilters()).lessThanOrEqualTo(1));
setSelected(false); setSelected(false);
} }
@ -69,7 +69,6 @@ public class DataSourcesFilter extends UnionFilter<DataSourceFilter> {
.map(DataSourceFilter::getDataSourceID) .map(DataSourceFilter::getDataSourceID)
.filter(t -> t == dataSourceFilter.getDataSourceID()) .filter(t -> t == dataSourceFilter.getDataSourceID())
.findAny().isPresent() == false) { .findAny().isPresent() == false) {
dataSourceFilter.getDisabledProperty().bind(getDisabledProperty());
getSubFilters().add(dataSourceFilter); getSubFilters().add(dataSourceFilter);
getSubFilters().sort(Comparator.comparing(DataSourceFilter::getDisplayName)); getSubFilters().sort(Comparator.comparing(DataSourceFilter::getDisplayName));
} }
@ -100,4 +99,10 @@ public class DataSourcesFilter extends UnionFilter<DataSourceFilter> {
public int hashCode() { public int hashCode() {
return 9; return 9;
} }
@Override
public ObservableBooleanValue disabledProperty() {
return Bindings.or(super.disabledProperty(), Bindings.size(getSubFilters()).lessThanOrEqualTo(1));
}
} }

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.timeline.filters;
import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableBooleanValue;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
@ -77,7 +78,7 @@ public interface Filter {
*/ */
void setDisabled(Boolean act); void setDisabled(Boolean act);
SimpleBooleanProperty getDisabledProperty(); ObservableBooleanValue disabledProperty();
boolean isDisabled(); boolean isDisabled();

View File

@ -8,6 +8,7 @@ package org.sleuthkit.autopsy.timeline.filters;
import java.util.Comparator; import java.util.Comparator;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableBooleanValue;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
/** /**
@ -16,13 +17,12 @@ import org.openide.util.NbBundle;
public class HashHitsFilter extends UnionFilter<HashSetFilter> { public class HashHitsFilter extends UnionFilter<HashSetFilter> {
@Override @Override
@NbBundle.Messages("hashHitsFilter.displayName.text=Only Hash Set Hits") @NbBundle.Messages("hashHitsFilter.displayName.text=Hash Sets")
public String getDisplayName() { public String getDisplayName() {
return Bundle.hashHitsFilter_displayName_text(); return Bundle.hashHitsFilter_displayName_text();
} }
public HashHitsFilter() { public HashHitsFilter() {
getDisabledProperty().bind(Bindings.size(getSubFilters()).lessThan(1));
setSelected(false); setSelected(false);
} }
@ -81,4 +81,9 @@ public class HashHitsFilter extends UnionFilter<HashSetFilter> {
getSubFilters().sort(Comparator.comparing(HashSetFilter::getDisplayName)); getSubFilters().sort(Comparator.comparing(HashSetFilter::getDisplayName));
} }
} }
@Override
public ObservableBooleanValue disabledProperty() {
return Bindings.or(super.disabledProperty(), Bindings.isEmpty(getSubFilters()));
}
} }

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.timeline.filters;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javafx.beans.binding.BooleanBinding;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
/** /**
@ -108,4 +109,17 @@ public class RootFilter extends IntersectionFilter<Filter> {
} }
return areSubFiltersEqual(this, (CompoundFilter<Filter>) obj); return areSubFiltersEqual(this, (CompoundFilter<Filter>) obj);
} }
public boolean isActive() {
return true;
}
public BooleanBinding activeProperty() {
return new BooleanBinding() {
@Override
protected boolean computeValue() {
return true;
}
};
}
} }

View File

@ -8,6 +8,7 @@ package org.sleuthkit.autopsy.timeline.filters;
import java.util.Comparator; import java.util.Comparator;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableBooleanValue;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagName;
@ -17,13 +18,12 @@ import org.sleuthkit.datamodel.TagName;
public class TagsFilter extends UnionFilter<TagNameFilter> { public class TagsFilter extends UnionFilter<TagNameFilter> {
@Override @Override
@NbBundle.Messages("tagsFilter.displayName.text=Only Events Tagged") @NbBundle.Messages("tagsFilter.displayName.text=Tags")
public String getDisplayName() { public String getDisplayName() {
return Bundle.tagsFilter_displayName_text(); return Bundle.tagsFilter_displayName_text();
} }
public TagsFilter() { public TagsFilter() {
getDisabledProperty().bind(Bindings.size(getSubFilters()).lessThan(1));
setSelected(false); setSelected(false);
} }
@ -89,5 +89,8 @@ public class TagsFilter extends UnionFilter<TagNameFilter> {
getSubFilters().sort(Comparator.comparing(TagNameFilter::getDisplayName)); getSubFilters().sort(Comparator.comparing(TagNameFilter::getDisplayName));
} }
@Override
public ObservableBooleanValue disabledProperty() {
return Bindings.or(super.disabledProperty(), Bindings.isEmpty(getSubFilters()));
}
} }

View File

@ -72,7 +72,7 @@ public class TypeFilter extends UnionFilter<TypeFilter> {
} }
@Override @Override
@NbBundle.Messages("TypeFilter.displayName.text=Event Type Filter") @NbBundle.Messages("TypeFilter.displayName.text=Event Type")
public String getDisplayName() { public String getDisplayName() {
return (eventType == RootEventType.getInstance()) return (eventType == RootEventType.getInstance())
? Bundle.TypeFilter_displayName_text() ? Bundle.TypeFilter_displayName_text()

View File

@ -74,8 +74,8 @@ public class StatusBar extends ToolBar {
taskLabel.setVisible(false); taskLabel.setVisible(false);
HBox.setHgrow(spacer, Priority.ALWAYS); HBox.setHgrow(spacer, Priority.ALWAYS);
refreshLabel.visibleProperty().bind(this.controller.getNewEventsFlag()); refreshLabel.visibleProperty().bind(this.controller.eventsDBStaleProperty());
refreshLabel.managedProperty().bind(this.controller.getNewEventsFlag()); refreshLabel.managedProperty().bind(this.controller.eventsDBStaleProperty());
taskLabel.textProperty().bind(this.controller.taskTitleProperty()); taskLabel.textProperty().bind(this.controller.taskTitleProperty());
messageLabel.textProperty().bind(this.controller.taskMessageProperty()); messageLabel.textProperty().bind(this.controller.taskMessageProperty());
progressBar.progressProperty().bind(this.controller.taskProgressProperty()); progressBar.progressProperty().bind(this.controller.taskProgressProperty());
@ -83,6 +83,5 @@ public class StatusBar extends ToolBar {
statusLabel.textProperty().bind(this.controller.getStatusProperty()); statusLabel.textProperty().bind(this.controller.getStatusProperty());
statusLabel.visibleProperty().bind(statusLabel.textProperty().isNotEmpty()); statusLabel.visibleProperty().bind(statusLabel.textProperty().isNotEmpty());
} }
} }

View File

@ -347,9 +347,9 @@ final public class VisualizationPanel extends BorderPane {
refreshTimeUI(); //populate the viz refreshTimeUI(); //populate the viz
//this should use an event(EventBus) , not this weird observable pattern //this should use an event(EventBus) , not this weird observable pattern
controller.getNeedsHistogramRebuild().addListener((observable, oldValue, newValue) -> { controller.eventsDBStaleProperty().addListener(staleProperty -> {
if (newValue) { if (controller.isEventsDBStale()) {
refreshHistorgram(); Platform.runLater(VisualizationPanel.this::refreshHistorgram);
} }
}); });
refreshHistorgram(); refreshHistorgram();

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.timeline.ui.filtering;
import java.util.function.Supplier; import java.util.function.Supplier;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableBooleanValue;
import javafx.scene.control.CheckBox; import javafx.scene.control.CheckBox;
import javafx.scene.control.IndexedCell; import javafx.scene.control.IndexedCell;
import org.sleuthkit.autopsy.timeline.filters.AbstractFilter; import org.sleuthkit.autopsy.timeline.filters.AbstractFilter;
@ -29,7 +30,7 @@ class FilterCheckBoxCellFactory<X extends AbstractFilter> extends AbstractFXCell
private final CheckBox checkBox = new CheckBox(); private final CheckBox checkBox = new CheckBox();
private SimpleBooleanProperty selectedProperty; private SimpleBooleanProperty selectedProperty;
private SimpleBooleanProperty disabledProperty; private ObservableBooleanValue disabledProperty;
@Override @Override
protected void configureCell(IndexedCell<? extends X> cell, X item, boolean empty, Supplier<X> supplier) { protected void configureCell(IndexedCell<? extends X> cell, X item, boolean empty, Supplier<X> supplier) {
@ -37,18 +38,17 @@ class FilterCheckBoxCellFactory<X extends AbstractFilter> extends AbstractFXCell
checkBox.selectedProperty().unbindBidirectional(selectedProperty); checkBox.selectedProperty().unbindBidirectional(selectedProperty);
} }
if (disabledProperty != null) { if (disabledProperty != null) {
checkBox.disableProperty().unbindBidirectional(disabledProperty); checkBox.disableProperty().unbind();//disabledProperty);
} }
if (item == null) { if (item == null) {
cell.setText(null);
cell.setGraphic(null); cell.setGraphic(null);
} else { } else {
cell.setText(item.getDisplayName()); checkBox.setText(item.getDisplayName());
selectedProperty = item.selectedProperty(); selectedProperty = item.selectedProperty();
checkBox.selectedProperty().bindBidirectional(selectedProperty); checkBox.selectedProperty().bindBidirectional(selectedProperty);
disabledProperty = item.getDisabledProperty(); disabledProperty = item.disabledProperty();
checkBox.disableProperty().bindBidirectional(disabledProperty); checkBox.disableProperty().bind(disabledProperty);
cell.setGraphic(checkBox); cell.setGraphic(checkBox);
} }
} }

View File

@ -1,5 +1,6 @@
Manifest-Version: 1.0 Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.corelibs/3 OpenIDE-Module: org.sleuthkit.autopsy.corelibs/3
OpenIDE-Module-Implementation-Version: 4
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corelibs/Bundle.properties OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corelibs/Bundle.properties
OpenIDE-Module-Specification-Version: 1.1 OpenIDE-Module-Specification-Version: 1.1
AutoUpdate-Show-In-Client: true AutoUpdate-Show-In-Client: true

View File

@ -1,5 +1,5 @@
Manifest-Version: 1.0 Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.imagegallery/1 OpenIDE-Module: org.sleuthkit.autopsy.imagegallery/2
OpenIDE-Module-Implementation-Version: 1 OpenIDE-Module-Implementation-Version: 2
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/imagegallery/Bundle.properties OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/imagegallery/Bundle.properties

View File

@ -5,4 +5,4 @@ license.file=LICENSE-2.0.txt
nbm.homepage=http://www.sleuthkit.org/ nbm.homepage=http://www.sleuthkit.org/
nbm.needs.restart=true nbm.needs.restart=true
project.license=imagegallery project.license=imagegallery
spec.version.base=1.0 spec.version.base=2.0

View File

@ -103,7 +103,7 @@
<compile-dependency/> <compile-dependency/>
<run-dependency> <run-dependency>
<release-version>10</release-version> <release-version>10</release-version>
<specification-version>10.0.11</specification-version> <specification-version>10.5</specification-version>
</run-dependency> </run-dependency>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -23,16 +23,16 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
@ -149,13 +149,13 @@ public enum FileTypeUtils {
return Collections.unmodifiableSet(supportedExtensions); return Collections.unmodifiableSet(supportedExtensions);
} }
static synchronized FileTypeDetector getFileTypeDetector() { static synchronized FileTypeDetector getFileTypeDetector() throws FileTypeDetector.FileTypeDetectorInitException {
/*
* TODO: EUR-740 recreate FileTypeDetector when the user creates new
* user defined file types
*/
if (isNull(FILE_TYPE_DETECTOR)) { if (isNull(FILE_TYPE_DETECTOR)) {
try {
FILE_TYPE_DETECTOR = new FileTypeDetector(); FILE_TYPE_DETECTOR = new FileTypeDetector();
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
LOGGER.log(Level.SEVERE, "Failed to initialize File Type Detector, will fall back on extensions in some situations.", ex); //NON-NLS
}
} }
return FILE_TYPE_DETECTOR; return FILE_TYPE_DETECTOR;
} }
@ -169,24 +169,12 @@ public enum FileTypeUtils {
* *
* @return true if this file is supported or false if not * @return true if this file is supported or false if not
*/ */
public static boolean isDrawable(AbstractFile file) throws TskCoreException { public static boolean isDrawable(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException {
return hasDrawableMimeType(file).orElseGet(() -> { return hasDrawableMIMEType(file);
return FileTypeUtils.supportedExtensions.contains(file.getNameExtension().toLowerCase())
|| ImageUtils.isJpegFileHeader(file)
|| ImageUtils.isPngFileHeader(file);
});
}
public static boolean isGIF(AbstractFile file) {
return ImageUtils.isGIF(file);
}
public static Optional<String> getMimeType(AbstractFile file) throws TskCoreException {
return Optional.ofNullable(file.getMIMEType());
} }
static boolean isDrawableMimeType(String mimeType) { static boolean isDrawableMimeType(String mimeType) {
if (isNull(mimeType)) { if (StringUtils.isBlank(mimeType)) {
return false; return false;
} else { } else {
String mimeTypeLower = mimeType.toLowerCase(); String mimeTypeLower = mimeType.toLowerCase();
@ -197,6 +185,10 @@ public enum FileTypeUtils {
} }
/** /**
*
* TODO: EUR-740 recreate FileTypeDetector when the user creates new user
* defined file types
*
* does the given file have drawable/supported mime type * does the given file have drawable/supported mime type
* *
* @param file * @param file
@ -205,8 +197,9 @@ public enum FileTypeUtils {
* type. False if a non image/video mimetype. empty Optional if a * type. False if a non image/video mimetype. empty Optional if a
* mimetype could not be detected. * mimetype could not be detected.
*/ */
static Optional<Boolean> hasDrawableMimeType(AbstractFile file) throws TskCoreException { static boolean hasDrawableMIMEType(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException {
return getMimeType(file).map(FileTypeUtils::isDrawableMimeType); String mimeType = getFileTypeDetector().detect(file).toLowerCase();
return isDrawableMimeType(mimeType) || (mimeType.equals("audio/x-aiff") && "tiff".equalsIgnoreCase(file.getNameExtension()));
} }
/** /**
@ -218,16 +211,31 @@ public enum FileTypeUtils {
* application/x-shockwave-flash, etc) or, if no mimetype is * application/x-shockwave-flash, etc) or, if no mimetype is
* available, a video extension. * available, a video extension.
*/ */
public static boolean isVideoFile(AbstractFile file) { public static boolean hasVideoMIMEType(AbstractFile file) {
try { try {
return getMimeType(file) String mimeType = getFileTypeDetector().detect(file).toLowerCase();
.map(String::toLowerCase) return mimeType.startsWith("video/") || videoMimeTypes.contains(mimeType);
.map(mimeType } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) {
-> mimeType.startsWith("video/") LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex);
|| videoMimeTypes.contains(mimeType)) return false;
.orElseGet(() -> FileTypeUtils.videoExtensions.contains(file.getNameExtension())); }
} catch (TskCoreException ex) { }
return FileTypeUtils.videoExtensions.contains(file.getNameExtension());
/**
* Get the unique path for the content, or if that fails, just return the
* name.
*
* @param content
*
* @return
*/
static String getContentPathSafe(Content content) {
try {
return content.getUniquePath();
} catch (TskCoreException tskCoreException) {
String contentName = content.getName();
LOGGER.log(Level.SEVERE, "Failed to get unique path for " + contentName, tskCoreException); //NOI18N NON-NLS
return contentName;
} }
} }
} }

View File

@ -20,16 +20,13 @@ package org.sleuthkit.autopsy.imagegallery;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.Observable; import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyBooleanProperty;
@ -79,14 +76,12 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewState;
import org.sleuthkit.autopsy.imagegallery.gui.NoGroupsDialog; import org.sleuthkit.autopsy.imagegallery.gui.NoGroupsDialog;
import org.sleuthkit.autopsy.imagegallery.gui.Toolbar; import org.sleuthkit.autopsy.imagegallery.gui.Toolbar;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.FileSystem;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.VirtualDirectory;
/** /**
* Connects different parts of ImageGallery together and is hub for flow of * Connects different parts of ImageGallery together and is hub for flow of
@ -853,23 +848,15 @@ public final class ImageGalleryController implements Executor {
if (known) { if (known) {
taskDB.removeFile(f.getId(), tr); //remove known files taskDB.removeFile(f.getId(), tr); //remove known files
} else { } else {
Optional<String> mimeType = FileTypeUtils.getMimeType(f);
if (mimeType.isPresent()) { try {
//mime type if (FileTypeUtils.hasDrawableMIMEType(f)) { //supported mimetype => analyzed
if (FileTypeUtils.isDrawableMimeType(mimeType.get())) { //supported mimetype => analyzed
taskDB.updateFile(DrawableFile.create(f, true, false), tr); taskDB.updateFile(DrawableFile.create(f, true, false), tr);
} else { //unsupported mimtype => analyzed but shouldn't include } else { //unsupported mimtype => analyzed but shouldn't include
taskDB.removeFile(f.getId(), tr); taskDB.removeFile(f.getId(), tr);
} }
} else { } catch (FileTypeDetector.FileTypeDetectorInitException ex) {
//no mime tyoe throw new RuntimeException(ex);
if (FileTypeUtils.isDrawable(f)) {
//no mime type but supported => add as not analyzed
taskDB.insertFile(DrawableFile.create(f, false, false), tr);
} else {
//no mime type, not supported => remove ( should never get here)
taskDB.removeFile(f.getId(), tr);
}
} }
} }
} }
@ -916,37 +903,8 @@ public final class ImageGalleryController implements Executor {
@Override @Override
List<AbstractFile> getFiles() throws TskCoreException { List<AbstractFile> getFiles() throws TskCoreException {
if (dataSource instanceof Image) { long datasourceID = dataSource.getDataSource().getId();
List<FileSystem> fileSystems = ((Image) dataSource).getFileSystems(); return tskCase.findAllFilesWhere("data_source_obj_id = " + datasourceID + " AND " + DRAWABLE_QUERY);
if (fileSystems.isEmpty()) {
/*
* no filesystems, don't bother with the initial population,
* just sort things out on file_done events
*/
progressHandle.finish();
return Collections.emptyList();
}
//use this clause to only grab files from the newly added filesystems.
String fsQuery = fileSystems.stream()
.map(fileSystem -> String.valueOf(fileSystem.getId()))
.collect(Collectors.joining(" OR fs_obj_id = ", "(fs_obj_id = ", ") ")); //NON-NLS
return tskCase.findAllFilesWhere(fsQuery + " AND " + DRAWABLE_QUERY); //NON-NLS
} else if (dataSource instanceof VirtualDirectory) {
/*
* fs_obj_id is set only for file system files, so we will match
* the VirtualDirectory's name in the parent path.
*
* TODO: A future database schema could probably make this
* cleaner. If we had a datasource_id column in the files table
* we could just match agains that.
*/
return tskCase.findAllFilesWhere(" parent_path LIKE '/" + dataSource.getName() + "/%' AND " + DRAWABLE_QUERY); //NON-NLS
} else {
String msg = "Uknown datasource type: " + dataSource.getClass().getName();
LOGGER.log(Level.SEVERE, msg);
throw new IllegalArgumentException(msg);
}
} }
@Override @Override
@ -1002,10 +960,11 @@ public final class ImageGalleryController implements Executor {
//this file would have gotten scooped up in initial grab, but actually we don't need it //this file would have gotten scooped up in initial grab, but actually we don't need it
queueDBWorkerTask(new RemoveFileTask(file, db)); queueDBWorkerTask(new RemoveFileTask(file, db));
} }
} catch (TskCoreException ex) { } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) {
//TODO: What to do here? //TODO: What to do here?
LOGGER.log(Level.WARNING, "Unable to determine if file is drawable and not known. Not making any changes to DB", ex); //NON-NLS LOGGER.log(Level.SEVERE, "Unable to determine if file is drawable and not known. Not making any changes to DB", ex); //NON-NLS
throw new RuntimeException(ex); MessageNotifyUtil.Notify.error("Image Gallery Error",
"Unable to determine if file is drawable and not known. Not making any changes to DB. See the logs for details.");
} }
} }
} else { //TODO: keep track of what we missed for later } else { //TODO: keep track of what we missed for later

View File

@ -22,11 +22,11 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
@ -105,7 +105,7 @@ public class ImageGalleryModule {
* @return true if the given {@link AbstractFile} is "drawable" and not * @return true if the given {@link AbstractFile} is "drawable" and not
* 'known', else false * 'known', else false
*/ */
public static boolean isDrawableAndNotKnown(AbstractFile abstractFile) throws TskCoreException { public static boolean isDrawableAndNotKnown(AbstractFile abstractFile) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException {
return (abstractFile.getKnown() != TskData.FileKnown.KNOWN) && FileTypeUtils.isDrawable(abstractFile); return (abstractFile.getKnown() != TskData.FileKnown.KNOWN) && FileTypeUtils.isDrawable(abstractFile);
} }
} }

View File

@ -126,7 +126,7 @@ public enum ThumbnailCache {
*/ */
private Image load(DrawableFile file) { private Image load(DrawableFile file) {
if (FileTypeUtils.isGIF(file.getAbstractFile())) { if (ImageUtils.isGIF(file.getAbstractFile())) {
//directly read gif to preserve potential animation, //directly read gif to preserve potential animation,
//NOTE: not saved to disk! //NOTE: not saved to disk!
return new Image(new BufferedInputStream(new ReadContentInputStream(file.getAbstractFile())), MAX_THUMBNAIL_SIZE, MAX_THUMBNAIL_SIZE, true, true); return new Image(new BufferedInputStream(new ReadContentInputStream(file.getAbstractFile())), MAX_THUMBNAIL_SIZE, MAX_THUMBNAIL_SIZE, true, true);

View File

@ -1176,8 +1176,7 @@ public final class DrawableDB {
*/ */
public boolean isVideoFile(AbstractFile f) { public boolean isVideoFile(AbstractFile f) {
return isNull(f) ? false return isNull(f) ? false
: videoFileMap.computeIfAbsent(f.getId(), id -> FileTypeUtils.isVideoFile(f)); : videoFileMap.computeIfAbsent(f.getId(), id -> FileTypeUtils.hasVideoMIMEType(f));
} }
/** /**
@ -1242,8 +1241,8 @@ public final class DrawableDB {
String fileIdsList = "(" + StringUtils.join(fileIDs, ",") + " )"; String fileIdsList = "(" + StringUtils.join(fileIDs, ",") + " )";
//count the fileids that are in the given list and don't have a non-zero category assigned to them. //count the fileids that are in the given list and don't have a non-zero category assigned to them.
String name String name =
= "SELECT COUNT(obj_id) FROM tsk_files where obj_id IN " + fileIdsList //NON-NLS "SELECT COUNT(obj_id) FROM tsk_files where obj_id IN " + fileIdsList //NON-NLS
+ " AND obj_id NOT IN (SELECT obj_id FROM content_tags WHERE content_tags.tag_name_id IN " + catTagNameIDs + ")"; //NON-NLS + " AND obj_id NOT IN (SELECT obj_id FROM content_tags WHERE content_tags.tag_name_id IN " + catTagNameIDs + ")"; //NON-NLS
try (SleuthkitCase.CaseDbQuery executeQuery = controller.getSleuthKitCase().executeQuery(name); try (SleuthkitCase.CaseDbQuery executeQuery = controller.getSleuthKitCase().executeQuery(name);
ResultSet resultSet = executeQuery.getResultSet();) { ResultSet resultSet = executeQuery.getResultSet();) {

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